• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 
16 #include "scheduler.h"
17 
18 #include "util/ffrt_facade.h"
19 #include "util/singleton_register.h"
20 
21 namespace {
22 constexpr int TASK_OVERRUN_THRESHOLD = 1000;
23 constexpr int TASK_OVERRUN_ALARM_FREQ = 500;
24 }
25 
26 namespace ffrt {
27 
Instance()28 FFRTScheduler* FFRTScheduler::Instance()
29 {
30     return &SingletonRegister<FFRTScheduler>::Instance();
31 }
32 
RegistInsCb(SingleInsCB<FFRTScheduler>::Instance && cb)33 void FFRTScheduler::RegistInsCb(SingleInsCB<FFRTScheduler>::Instance &&cb)
34 {
35     SingletonRegister<FFRTScheduler>::RegistInsCb(std::move(cb));
36 }
37 
InsertNode(LinkedList * node,const QoS qos)38 bool FFRTScheduler::InsertNode(LinkedList* node, const QoS qos)
39 {
40     FFRT_COND_DO_ERR((node == nullptr), return false, "Node is NULL");
41 
42     int level = qos();
43     FFRT_COND_DO_ERR((level == qos_inherit), return false, "Level incorrect");
44 
45     ffrt_executor_task_t* task = reinterpret_cast<ffrt_executor_task_t*>(reinterpret_cast<char*>(node) -
46         offsetof(ffrt_executor_task_t, wq));
47     uintptr_t taskType = task->type;
48 
49     auto lock = FFRTFacade::GetEUInstance().GetSleepCtl(level);
50     lock->lock();
51     fifoQue[static_cast<unsigned short>(level)]->WakeupNode(node);
52     lock->unlock();
53 
54     if (taskType == ffrt_io_task) {
55         FFRTFacade::GetEUInstance().NotifyLocalTaskAdded(qos);
56         return true;
57     }
58 
59     FFRTFacade::GetEUInstance().NotifyTaskAdded(qos);
60     return true;
61 }
62 
RemoveNode(LinkedList * node,const QoS qos)63 bool FFRTScheduler::RemoveNode(LinkedList* node, const QoS qos)
64 {
65     FFRT_COND_DO_ERR((node == nullptr), return false, "Node is NULL");
66 
67     int level = qos();
68     FFRT_COND_DO_ERR((level == qos_inherit), return false, "Level incorrect");
69 
70     auto lock = FFRTFacade::GetEUInstance().GetSleepCtl(level);
71     lock->lock();
72     if (!node->InList()) {
73         lock->unlock();
74         return false;
75     }
76     fifoQue[static_cast<unsigned short>(level)]->RemoveNode(node);
77     lock->unlock();
78     return true;
79 }
80 
WakeupTask(CPUEUTask * task)81 bool FFRTScheduler::WakeupTask(CPUEUTask* task)
82 {
83     FFRT_COND_DO_ERR((task == nullptr), return false, "task is nullptr");
84 
85     int qosLevel = task->qos_();
86     if (qosLevel == qos_inherit) {
87         FFRT_LOGE("qos inhert not support wake up task[%lu], type[%d], name[%s]",
88             task->gid, task->type, task->label.c_str());
89         return false;
90     }
91 
92     QoS _qos = qosLevel;
93     int level = _qos();
94     uint64_t gid = task->gid;
95     bool notifyWorker = task->notifyWorker_;
96     std::string label = task->label;
97 
98     FFRT_READY_MARKER(gid); // ffrt normal task ready to enque
99     auto lock = FFRTFacade::GetEUInstance().GetSleepCtl(level);
100     lock->lock();
101     fifoQue[static_cast<unsigned short>(level)]->WakeupTask(task);
102     int taskCount = fifoQue[static_cast<size_t>(level)]->RQSize();
103     lock->unlock();
104 
105     // The ownership of the task belongs to ReadyTaskQueue, and the task cannot be accessed any more.
106     FFRT_LOGD("qos[%d] task[%lu] entered q", level, gid);
107     if (taskCount >= TASK_OVERRUN_THRESHOLD && taskCount % TASK_OVERRUN_ALARM_FREQ == 0) {
108         FFRT_LOGW("qos [%d], task [%s] entered q, task count [%d] exceeds threshold.",
109             level, label.c_str(), taskCount);
110     }
111 
112     if (notifyWorker) {
113         FFRTFacade::GetEUInstance().NotifyTaskAdded(_qos);
114     }
115 
116     return true;
117 }
118 
119 } // namespace ffrt