@@ -56,6 +56,13 @@ static ContextualClassifier *gClassifier = nullptr;
5656static const int32_t pendingQueueControlSize = 30 ;
5757
5858ContextualClassifier::ContextualClassifier () {
59+ this ->mClientTracker = 0 ;
60+ this ->mActiveAppThreshold = 1 ; // single-app mode
61+
62+ // In multi-app mode, at most 3 concurrent apps are supported
63+ if (UrmSettings::metaConfigs.mAcceptMode & ACCEPT_AND_PERSIST ) {
64+ this ->mActiveAppThreshold = 3 ;
65+ }
5966 this ->mInference = GetInferenceObject ();
6067}
6168
@@ -179,49 +186,45 @@ void ContextualClassifier::ClassifierMain() {
179186 this ->mPendingEv .pop ();
180187
181188 if (ev.type == CC_APP_OPEN ) {
182- std::string comm;
183- uint32_t sigId = URM_SIG_APP_OPEN ;
184- uint32_t sigType = DEFAULT_SIGNAL_TYPE ;
185- uint32_t ctxDetails = 0U ;
186-
187189 if (ev.pid != -1 ) {
190+ std::string comm;
191+ uint32_t sigId = URM_SIG_APP_OPEN ;
192+ uint32_t sigType = DEFAULT_SIGNAL_TYPE ;
193+ uint32_t ctxDetails = 0U ;
188194 if (AuxRoutines::fetchComm (ev.pid , comm) != 0 ) {
189195 continue ;
190196 }
191197
192- // Step 1: Figure out workload type
193- int32_t contextType =
194- this ->ClassifyProcess (ev.pid , ev.tgid , comm, ctxDetails);
195- if (contextType == CC_IGNORE ) {
196- // Ignore and wait for next event
197- continue ;
198- }
199-
200- // Identify if any signal configuration exists
201- // Will return the sigID based on the workload
202- // For example: game, browser, multimedia
203- sigId = this ->GetSignalIDForWorkload (contextType);
204-
205- // Step 2:
198+ // Step 1:
206199 // Untune any Configurations from the last proc-invocation
207- for (int64_t handle: this ->mCurrRestuneHandles ) {
208- if (handle > 0 ) {
209- this ->untuneRequestHelper (handle);
200+ uint64_t currActiveCount = 0 ;
201+ if (!this ->mCurrRestuneHandles .empty ()) {
202+ currActiveCount =
203+ this ->mClientTracker - this ->mCurrRestuneHandles .front ().first ;
204+ }
205+
206+ if (currActiveCount == this ->mActiveAppThreshold ) {
207+ uint64_t minClientId = this ->mCurrRestuneHandles .front ().first ;
208+ while (!this ->mCurrRestuneHandles .empty ()) {
209+ if (minClientId == this ->mCurrRestuneHandles .front ().first ) {
210+ this ->mCurrRestuneHandles .pop ();
211+ } else {
212+ break ;
213+ }
210214 }
211215 }
212- this ->mCurrRestuneHandles .clear ();
213216
214- // Step 3 :
217+ // Step 2 :
215218 // - Move the process to focused-cgroup, Also involves removing the process
216219 // already there from the cgroup.
217220 // - Move the "threads" from per-app config to appropriate cgroups
218221 this ->MoveAppThreadsToCGroup (ev.pid , ev.tgid , comm, FOCUSED_CGROUP_IDENTIFIER );
219222
220- // Step 4 :
223+ // Step 3 :
221224 // Configure any per-app config specified signals.
222225 this ->configureAppSignals (ev.pid , ev.tgid , comm);
223226
224- // Step 5 : If the post processing block exists, call it
227+ // Step 4 : If the post processing block exists, call it
225228 // It might provide us a more specific sigID or sigType
226229 PostProcessingCallback postCb =
227230 Extensions::getPostProcessingCallback (comm);
@@ -237,11 +240,43 @@ void ContextualClassifier::ClassifierMain() {
237240 postCb ((void *)&postProcessData);
238241
239242 // Record any Configurations made
240- if (postProcessData.mHandleAcq != - 1 ) {
241- this ->mCurrRestuneHandles .push_back (postProcessData.mHandleAcq );
243+ if (postProcessData.mHandleAcq != -1 ) {
244+ this ->mCurrRestuneHandles .push (
245+ {this ->mClientTracker , postProcessData.mHandleAcq }
246+ );
247+ }
248+ } else {
249+ // Figure out workload type
250+ int32_t contextType =
251+ this ->ClassifyProcess (ev.pid , ev.tgid , comm, ctxDetails);
252+ if (contextType == CC_IGNORE ) {
253+ // Ignore and wait for next event
254+ continue ;
255+ }
256+
257+ // Identify if any signal configuration exists
258+ // Will return the sigID based on the workload
259+ // For example: game, browser, multimedia
260+ sigId = this ->GetSignalIDForWorkload (contextType);
261+
262+ int64_t handle = acquireSignal (
263+ sigId,
264+ sigType,
265+ ev.pid ,
266+ ev.tgid
267+ );
268+ if (handle != -1 ) {
269+ this ->mCurrRestuneHandles .push (
270+ {this ->mClientTracker , handle}
271+ );
242272 }
243273 }
244274 }
275+
276+ // Increment client count, this helps in tracking older Requests,
277+ // which will need to be untuned once the active threshold is hit.
278+ this ->mClientTracker ++;
279+
245280 } else if (ev.type == CC_APP_CLOSE ) {
246281 // No Action Needed, Pulse Monitor to take care of cleanup
247282 ClientGarbageCollector::getInstance ()->submitClientForCleanup (ev.pid );
@@ -462,7 +497,7 @@ void ContextualClassifier::MoveAppThreadsToCGroup(pid_t incomingPID,
462497 // Anything to issue
463498 if (request->getResourcesCount () > 0 ) {
464499 // Record:
465- this ->mCurrRestuneHandles .push_back ( request->getHandle ());
500+ this ->mCurrRestuneHandles .push ({ this -> mClientTracker , request->getHandle ()} );
466501
467502 // fast path to Request Queue
468503 submitResProvisionRequest (request, true );
@@ -493,7 +528,7 @@ void ContextualClassifier::configureAppSignals(pid_t incomingPID,
493528 );
494529
495530 if (handle != -1 ) {
496- this ->mCurrRestuneHandles .push_back ( handle);
531+ this ->mCurrRestuneHandles .push ({ this -> mClientTracker , handle} );
497532 }
498533 }
499534 }
0 commit comments