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 "cpu_worker.h"
17 #include "eu/worker_thread.h"
18 #include "dfx/trace/ffrt_trace.h"
19 #include "sched/scheduler.h"
20 #include "eu/cpu_manager_interface.h"
21 #include "dfx/bbox/bbox.h"
22 #include "eu/func_manager.h"
23
24 namespace ffrt {
Run(TaskCtx * task)25 void CPUWorker::Run(TaskCtx* task)
26 {
27 FFRT_TRACE_SCOPE(TRACE_LEVEL2, Run);
28 if constexpr(USE_COROUTINE) {
29 CoStart(task);
30 } else {
31 auto f = reinterpret_cast<ffrt_function_header_t*>(task->func_storage);
32 auto exp = ffrt::SkipStatus::SUBMITTED;
33 if (likely(__atomic_compare_exchange_n(&task->skipped, &exp, ffrt::SkipStatus::EXECUTED, 0, __ATOMIC_ACQUIRE,
34 __ATOMIC_RELAXED))) {
35 f->exec(f);
36 }
37 f->destroy(f);
38 task->UpdateState(ffrt::TaskState::EXITED);
39 }
40 }
41
Run(ffrt_executor_task_t * task,ffrt_qos_t qos)42 void CPUWorker::Run(ffrt_executor_task_t* task, ffrt_qos_t qos)
43 {
44 #ifdef FFRT_BBOX_ENABLE
45 TaskRunCounterInc();
46 #endif
47 ffrt_executor_task_func func = nullptr;
48 if (task->type == ffrt_rust_task) {
49 func = FuncManager::Instance()->getFunc(ffrt_rust_task);
50 } else {
51 func = FuncManager::Instance()->getFunc(ffrt_uv_task);
52 }
53 if (func == nullptr) {
54 FFRT_LOGE("func is nullptr");
55 return;
56 }
57 func(task, qos);
58 #ifdef FFRT_BBOX_ENABLE
59 TaskFinishCounterInc();
60 #endif
61 }
62
Dispatch(CPUWorker * worker)63 void CPUWorker::Dispatch(CPUWorker* worker)
64 {
65 auto ctx = ExecuteCtx::Cur();
66 TaskCtx* lastTask = nullptr;
67
68 FFRT_LOGD("qos[%d] thread start succ", (int)worker->GetQos());
69 for (;;) {
70 FFRT_LOGD("task picking");
71 TaskCtx* task = worker->ops.PickUpTask(worker);
72 if (task) {
73 worker->ops.NotifyTaskPicked(worker);
74 } else {
75 FFRT_WORKER_IDLE_BEGIN_MARKER();
76 auto action = worker->ops.WaitForNewAction(worker);
77 FFRT_WORKER_IDLE_END_MARKER();
78 if (action == WorkerAction::RETRY) {
79 continue;
80 } else if (action == WorkerAction::RETIRE) {
81 break;
82 }
83 }
84
85 BboxCheckAndFreeze();
86
87 FFRT_LOGD("EU pick task[%lu]", task->gid);
88
89 if (task->type != 0) {
90 ffrt_executor_task_t* work = (ffrt_executor_task_t*)task;
91 Run(work, (int)worker->GetQos());
92 } else {
93 UserSpaceLoadRecord::UpdateTaskSwitch(lastTask, task);
94 task->UpdateState(TaskState::RUNNING);
95
96 lastTask = task;
97 ctx->task = task;
98 worker->curTask = task;
99 Run(task);
100 }
101 BboxCheckAndFreeze();
102 worker->curTask = nullptr;
103 ctx->task = nullptr;
104 }
105
106 CoWorkerExit();
107 FFRT_LOGD("ExecutionThread exited");
108 worker->ops.WorkerRetired(worker);
109 }
110 } // namespace ffrt
111