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 "ffrt_utils.h"
17 #include "power_log.h"
18 
19 namespace OHOS {
20 namespace PowerMgr {
SubmitTask(const FFRTTask & task)21 void FFRTUtils::SubmitTask(const FFRTTask& task)
22 {
23     ffrt::submit(task);
24 }
25 
SubmitTaskSync(const FFRTTask & task)26 void FFRTUtils::SubmitTaskSync(const FFRTTask& task)
27 {
28     ffrt::submit(task);
29     ffrt::wait();
30 }
31 
SubmitQueueTasks(const std::vector<FFRTTask> & tasks,FFRTQueue & queue)32 void FFRTUtils::SubmitQueueTasks(const std::vector<FFRTTask>& tasks, FFRTQueue& queue)
33 {
34     if (tasks.empty()) {
35         return;
36     }
37     for (auto task : tasks) {
38         queue.submit(task);
39     }
40 }
41 
SubmitDelayTask(FFRTTask & task,uint32_t delayMs,FFRTQueue & queue)42 FFRTHandle FFRTUtils::SubmitDelayTask(FFRTTask& task, uint32_t delayMs, FFRTQueue& queue)
43 {
44     using namespace std::chrono;
45     milliseconds ms(delayMs);
46     microseconds us = duration_cast<microseconds>(ms);
47     return queue.submit_h(task, ffrt::task_attr().delay(us.count()));
48 }
49 
SubmitDelayTask(FFRTTask & task,uint32_t delayMs,std::shared_ptr<FFRTQueue> queue)50 FFRTHandle FFRTUtils::SubmitDelayTask(FFRTTask& task, uint32_t delayMs, std::shared_ptr<FFRTQueue> queue)
51 {
52     using namespace std::chrono;
53     milliseconds ms(delayMs);
54     microseconds us = duration_cast<microseconds>(ms);
55     return queue->submit_h(task, ffrt::task_attr().delay(us.count()));
56 }
57 
SubmitTimeoutTask(const FFRTTask & task,uint32_t timeoutMs)58 bool FFRTUtils::SubmitTimeoutTask(const FFRTTask& task, uint32_t timeoutMs)
59 {
60     ffrt::future<void> future = ffrt::async(task);
61     auto status = future.wait_for(std::chrono::milliseconds(timeoutMs));
62     return status == ffrt::future_status::ready;
63 }
64 
CancelTask(FFRTHandle & handle,FFRTQueue & queue)65 int FFRTUtils::CancelTask(FFRTHandle& handle, FFRTQueue& queue)
66 {
67     return queue.cancel(handle);
68 }
69 
CancelTask(FFRTHandle & handle,std::shared_ptr<FFRTQueue> queue)70 int FFRTUtils::CancelTask(FFRTHandle& handle, std::shared_ptr<FFRTQueue> queue)
71 {
72     return queue->cancel(handle);
73 }
74 
Lock(uint32_t mutexId)75 void FFRTMutexMap::Lock(uint32_t mutexId)
76 {
77     mutexMap_[mutexId].lock();
78 }
79 
Unlock(uint32_t mutexId)80 void FFRTMutexMap::Unlock(uint32_t mutexId)
81 {
82     mutexMap_[mutexId].unlock();
83 }
84 
FFRTTimer()85 FFRTTimer::FFRTTimer(): queue_("ffrt_timer")
86 {
87 }
88 
FFRTTimer(const char * timer_name)89 FFRTTimer::FFRTTimer(const char *timer_name): queue_(timer_name)
90 {
91 }
92 
~FFRTTimer()93 FFRTTimer::~FFRTTimer()
94 {
95     Clear();
96 }
97 
Clear()98 void FFRTTimer::Clear()
99 {
100     mutex_.lock();
101     POWER_HILOGD(FEATURE_UTIL, "FFRT Timer Clear");
102     CancelAllTimerInner();
103     handleMap_.clear();
104     taskId_.clear();
105     mutex_.unlock();
106 }
107 
CancelAllTimer()108 void FFRTTimer::CancelAllTimer()
109 {
110     mutex_.lock();
111     CancelAllTimerInner();
112     mutex_.unlock();
113 }
114 
CancelTimer(uint32_t timerId)115 void FFRTTimer::CancelTimer(uint32_t timerId)
116 {
117     mutex_.lock();
118     CancelTimerInner(timerId);
119     mutex_.unlock();
120 }
121 
SetTimer(uint32_t timerId,FFRTTask & task)122 void FFRTTimer::SetTimer(uint32_t timerId, FFRTTask& task)
123 {
124     mutex_.lock();
125     CancelTimerInner(timerId);
126     ++taskId_[timerId];
127     POWER_HILOGD(FEATURE_UTIL, "Timer[%{public}u] Add Task[%{public}u]", timerId, taskId_[timerId]);
128     FFRTUtils::SubmitTask(task);
129     mutex_.unlock();
130 }
131 
SetTimer(uint32_t timerId,FFRTTask & task,uint32_t delayMs)132 void FFRTTimer::SetTimer(uint32_t timerId, FFRTTask& task, uint32_t delayMs)
133 {
134     if (delayMs == 0) {
135         return SetTimer(timerId, task);
136     }
137 
138     mutex_.lock();
139     CancelTimerInner(timerId);
140     ++taskId_[timerId];
141     POWER_HILOGD(FEATURE_UTIL, "Timer[%{public}u] Add Task[%{public}u] with delay = %{public}u",
142         timerId, taskId_[timerId], delayMs);
143     handleMap_[timerId] = FFRTUtils::SubmitDelayTask(task, delayMs, queue_);
144     mutex_.unlock();
145 }
146 
GetTaskId(uint32_t timerId)147 uint32_t FFRTTimer::GetTaskId(uint32_t timerId)
148 {
149     mutex_.lock();
150     uint32_t id = taskId_[timerId];
151     mutex_.unlock();
152     return id;
153 }
154 
155 /* inner functions must be called when mutex_ is locked */
CancelAllTimerInner()156 void FFRTTimer::CancelAllTimerInner()
157 {
158     for (auto &p : handleMap_) {
159         if (p.second != nullptr) {
160             POWER_HILOGD(FEATURE_UTIL, "Timer[%{public}u] Cancel Task[%{public}u]", p.first, taskId_[p.first]);
161             FFRTUtils::CancelTask(p.second, queue_);
162             p.second = nullptr;
163         }
164     }
165 }
166 
CancelTimerInner(uint32_t timerId)167 void FFRTTimer::CancelTimerInner(uint32_t timerId)
168 {
169     if (handleMap_[timerId] != nullptr) {
170         POWER_HILOGD(FEATURE_UTIL, "Timer[%{public}u] Cancel Task[%{public}u]", timerId, taskId_[timerId]);
171         FFRTUtils::CancelTask(handleMap_[timerId], queue_);
172         handleMap_[timerId] = nullptr;
173     }
174 }
175 
176 } // namespace PowerMgr
177 } // namespace OHOS