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 #ifndef _CPU_TASK_H_
16 #define _CPU_TASK_H_
17
18 #include <string>
19 #include <functional>
20 #include <unordered_set>
21 #include <vector>
22 #include <mutex>
23 #include <atomic>
24 #include <string>
25 #include <set>
26 #include <list>
27 #include <memory>
28 #include <unistd.h>
29 #include "task_base.h"
30 #include "sched/task_state.h"
31 #include "eu/co_routine.h"
32 #include "core/task_attr_private.h"
33 #include "core/task_io.h"
34 #include "dfx/log/ffrt_log_api.h"
35 #include "eu/func_manager.h"
36 #ifdef FFRT_ASYNC_STACKTRACE
37 #include "dfx/async_stack/ffrt_async_stack.h"
38 #endif
39
40 namespace ffrt {
41 constexpr int CO_CREATE_RETRY_INTERVAL = 500 * 1000;
42 struct VersionCtx;
43 class SCPUEUTask;
44
45 class CPUEUTask : public CoTask {
46 public:
47 CPUEUTask(const task_attr_private *attr, CPUEUTask *parent, const uint64_t &id, const QoS &qos);
48 SkipStatus skipped = SkipStatus::SUBMITTED;
49 TaskStatus status = TaskStatus::PENDING;
50
51 uint8_t func_storage[ffrt_auto_managed_function_storage_size]; // 函数闭包、指针或函数对象
52 CPUEUTask* parent = nullptr;
53 const uint64_t rank = 0x0;
54 std::mutex lock; // used in coroute
55 std::vector<CPUEUTask*> in_handles;
56 TaskState state;
57
58 /* The current number of child nodes does not represent the real number of child nodes,
59 * because the dynamic graph child nodes will grow to assist in the generation of id
60 */
61 std::atomic<uint64_t> childNum {0};
62 bool isWatchdogEnable = false;
63 bool notifyWorker_ = true;
64
65 void** threadTsd = nullptr;
66 void** tsd = nullptr;
67 bool taskLocal = false;
68
69 bool pollerEnable = false; // set true if task call ffrt_epoll_ctl
70
71 void SetQos(const QoS& newQos);
72 uint64_t reserved[8];
73
74 void FreeMem() override;
75 void Execute() override;
76
77 virtual void RecycleTask() = 0;
78
IsRoot()79 inline bool IsRoot()
80 {
81 return parent == nullptr;
82 }
83
UpdateState(TaskState::State taskState)84 int UpdateState(TaskState::State taskState)
85 {
86 return TaskState::OnTransition(taskState, this);
87 }
88
UpdateState(TaskState::State taskState,TaskState::Op && op)89 int UpdateState(TaskState::State taskState, TaskState::Op&& op)
90 {
91 return TaskState::OnTransition(taskState, this, std::move(op));
92 }
93 };
94
ExecutedOnWorker(CPUEUTask * task)95 inline bool ExecutedOnWorker(CPUEUTask* task)
96 {
97 return task && (task->type != ffrt_normal_task || !task->IsRoot());
98 }
99
LegacyMode(CPUEUTask * task)100 inline bool LegacyMode(CPUEUTask* task)
101 {
102 return task && (task->legacyCountNum > 0);
103 }
104
BlockThread(CPUEUTask * task)105 inline bool BlockThread(CPUEUTask* task)
106 {
107 return task && task->blockType == BlockType::BLOCK_THREAD;
108 }
109
ThreadWaitMode(CPUEUTask * task)110 inline bool ThreadWaitMode(CPUEUTask* task)
111 {
112 if constexpr(!USE_COROUTINE) {
113 // static switch controlled by macro
114 return true;
115 }
116 if (!ExecutedOnWorker(task)) {
117 // task is executed on user thread
118 return true;
119 }
120 if (LegacyMode(task)) {
121 // set_legacy_mode controlled by user
122 return true;
123 }
124 return false;
125 }
126
ThreadNotifyMode(CPUEUTask * task)127 inline bool ThreadNotifyMode(CPUEUTask* task)
128 {
129 if constexpr(!USE_COROUTINE) {
130 // static switch controlled by macro
131 return true;
132 }
133 if (BlockThread(task)) {
134 // thread wait happended when task in legacy mode
135 return true;
136 }
137 return false;
138 }
139
IsCoTask(TaskBase * task)140 inline bool IsCoTask(TaskBase* task)
141 {
142 return task->type == ffrt_normal_task || task->type == ffrt_queue_task;
143 }
144
NeedNotifyWorker(TaskBase * task)145 inline bool NeedNotifyWorker(TaskBase* task)
146 {
147 if (task == nullptr) {
148 return false;
149 }
150 bool needNotify = true;
151 if (task->type == ffrt_normal_task) {
152 CPUEUTask* cpuTask = static_cast<CPUEUTask*>(task);
153 needNotify = cpuTask->notifyWorker_;
154 cpuTask->notifyWorker_ = true;
155 }
156 return needNotify;
157 }
158
159 void ExecuteTask(TaskBase* task, QoS qos);
160 } /* namespace ffrt */
161 #endif
162