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 "sched/task_state.h"
17 #include "sched/task_manager.h"
18 #include "dfx/log/ffrt_log_api.h"
19 #include "sched/scheduler.h"
20 
21 namespace ffrt {
22 std::array<TaskState::Op, static_cast<size_t>(TaskState::MAX)> TaskState::ops;
23 
OnTransition(State state,CPUEUTask * task,Op && op)24 int TaskState::OnTransition(State state, CPUEUTask* task, Op&& op)
25 {
26     if (task == nullptr) {
27         FFRT_LOGE("task nullptr");
28         return -1;
29     }
30     if (task->IsRoot()) {
31         return 0;
32     }
33 
34     if (task->state == TaskState::EXITED) {
35         FFRT_LOGE("task[%s] have finished", task->label.c_str());
36         return -1;
37     }
38 
39     task->state.preState = task->state.curState;
40     task->state.curState = state;
41 
42 #if (TASKSTAT_LOG_ENABLE == 1)
43     task->state.stat.Count(task);
44 #endif
45 
46     if (ops[static_cast<size_t>(state)] &&
47         !ops[static_cast<size_t>(state)](task)) {
48         return -1;
49     }
50 
51     if (op && !op(task)) {
52         return -1;
53     }
54 
55     return 0;
56 }
57 
WaitingTime() const58 uint64_t TaskState::TaskStateStat::WaitingTime() const
59 {
60     return CalcDuration(TaskState::READY, TaskState::RUNNING);
61 }
62 
RunningTime() const63 uint64_t TaskState::TaskStateStat::RunningTime() const
64 {
65     return CalcDuration(TaskState::RUNNING, TaskState::EXITED);
66 }
67 
Count(CPUEUTask * task)68 void TaskState::TaskStateStat::Count(CPUEUTask* task)
69 {
70     Count(task->state.CurState());
71     TaskManager::Instance().TaskStateCount(task);
72 }
73 
Count(State state)74 void TaskState::TaskStateStat::Count(State state)
75 {
76     size_t index = static_cast<size_t>(state);
77     switch (state) {
78         case TaskState::READY:
79             if (timepoint[index].time_since_epoch() == std::chrono::steady_clock::duration::zero()) {
80                 timepoint[index] = std::chrono::steady_clock::now();
81             }
82             break;
83         case TaskState::MAX:
84             break;
85         default:
86             timepoint[index] = std::chrono::steady_clock::now();
87             break;
88     }
89 }
90 
CalcDuration(State pre,State cur) const91 uint64_t TaskState::TaskStateStat::CalcDuration(State pre, State cur) const
92 {
93     return timepoint[static_cast<size_t>(cur)].time_since_epoch() == std::chrono::steady_clock::duration::zero() ?
94         0 :
95         std::chrono::duration_cast<std::chrono::microseconds>(
96             timepoint[static_cast<size_t>(cur)] - timepoint[static_cast<size_t>(pre)])
97             .count();
98 }
99 } // namespace ffrt
100