• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "sched/stask_scheduler.h"
16 #include "util/ffrt_facade.h"
17 
18 namespace {
19 constexpr int TASK_OVERRUN_THRESHOLD = 1000;
20 constexpr int TASK_OVERRUN_ALARM_FREQ = 500;
21 }
22 
23 namespace ffrt {
PushTaskGlobal(TaskBase * task,bool rtb)24 bool STaskScheduler::PushTaskGlobal(TaskBase* task, bool rtb)
25 {
26     int taskCount = 0;
27     (void)rtb; // rtb is deprecated here
28     FFRT_COND_DO_ERR((task == nullptr), return false, "task is nullptr");
29 
30     int level = task->GetQos();
31     uint64_t gid = task->gid;
32     std::string label = task->GetLabel();
33 
34     FFRT_READY_MARKER(gid); // ffrt normal task ready to enqueue
35     {
36         std::lock_guard lg(*GetMutex());
37         // enqueue task and read size under lock-protection
38         que->EnQueue(task);
39         taskCount = que->Size();
40     }
41     // The ownership of the task belongs to ReadyTaskQueue, and the task cannot be accessed any more.
42     if (taskCount >= TASK_OVERRUN_THRESHOLD && taskCount % TASK_OVERRUN_ALARM_FREQ == 0) {
43         FFRT_SYSEVENT_LOGW("qos [%d], task [%s] entered q, task count [%d] exceeds threshold.",
44             level, label.c_str(), taskCount);
45     }
46 
47     return taskCount == 1; // whether it's rising edge
48 }
49 
PopTaskHybridProcess()50 TaskBase* STaskScheduler::PopTaskHybridProcess()
51 {
52     TaskBase *task = PopTaskGlobal();
53     if (task == nullptr) {
54         return nullptr;
55     }
56     int wakedWorkerNum = FFRTFacade::GetEUInstance().GetWorkerGroup(qos).executingNum;
57     // when there is only one worker, the global queue is equivalent to the local queue
58     // prevents local queue tasks that cannot be executed due to blocking tasks
59     if (wakedWorkerNum <= 1) {
60         return task;
61     }
62 
63     SpmcQueue *queue = GetLocalQueue();
64     int expectedTask = GetGlobalTaskCnt() / wakedWorkerNum - 1;
65     for (int i = 0; i < expectedTask; i++) {
66         if (queue->GetLength() == queue->GetCapacity()) {
67             return task;
68         }
69 
70         TaskBase *task2local = PopTaskGlobal();
71         if (task2local == nullptr) {
72             return task;
73         }
74         queue->PushTail(task2local);
75     }
76     if (NeedNotifyWorker(task)) {
77         FFRTFacade::GetEUInstance().NotifyTask<TaskNotifyType::TASK_PICKED>(qos);
78     }
79     return task;
80 }
81 }
82