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
19namespace OHOS {
20namespace PowerMgr {
21void FFRTUtils::SubmitTask(const FFRTTask& task)
22{
23    ffrt::submit(task);
24}
25
26void FFRTUtils::SubmitTaskSync(const FFRTTask& task)
27{
28    ffrt::submit(task);
29    ffrt::wait();
30}
31
32void 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
42FFRTHandle 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
50FFRTHandle 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
58bool 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
65int FFRTUtils::CancelTask(FFRTHandle& handle, FFRTQueue& queue)
66{
67    return queue.cancel(handle);
68}
69
70int FFRTUtils::CancelTask(FFRTHandle& handle, std::shared_ptr<FFRTQueue> queue)
71{
72    return queue->cancel(handle);
73}
74
75void FFRTMutexMap::Lock(uint32_t mutexId)
76{
77    mutexMap_[mutexId].lock();
78}
79
80void FFRTMutexMap::Unlock(uint32_t mutexId)
81{
82    mutexMap_[mutexId].unlock();
83}
84
85FFRTTimer::FFRTTimer(): queue_("ffrt_timer")
86{
87}
88
89FFRTTimer::FFRTTimer(const char *timer_name): queue_(timer_name)
90{
91}
92
93FFRTTimer::~FFRTTimer()
94{
95    Clear();
96    // queue_ will be destructed thereafter.
97}
98
99void FFRTTimer::Clear()
100{
101    mutex_.lock();
102    POWER_HILOGD(FEATURE_UTIL, "FFRT Timer Clear");
103    CancelAllTimerInner();
104    handleMap_.clear();
105    taskId_.clear();
106    mutex_.unlock();
107}
108
109void FFRTTimer::CancelAllTimer()
110{
111    mutex_.lock();
112    CancelAllTimerInner();
113    mutex_.unlock();
114}
115
116void FFRTTimer::CancelTimer(uint32_t timerId)
117{
118    mutex_.lock();
119    CancelTimerInner(timerId);
120    mutex_.unlock();
121}
122
123void FFRTTimer::SetTimer(uint32_t timerId, FFRTTask& task, uint32_t delayMs)
124{
125    mutex_.lock();
126    CancelTimerInner(timerId);
127    ++taskId_[timerId];
128    POWER_HILOGD(FEATURE_UTIL, "Timer[%{public}u] Add Task[%{public}u] with delay = %{public}u",
129        timerId, taskId_[timerId], delayMs);
130    handleMap_[timerId] = FFRTUtils::SubmitDelayTask(task, delayMs, queue_);
131    mutex_.unlock();
132}
133
134uint32_t FFRTTimer::GetTaskId(uint32_t timerId)
135{
136    mutex_.lock();
137    uint32_t id = taskId_[timerId];
138    mutex_.unlock();
139    return id;
140}
141
142const void* FFRTTimer::GetTaskHandlePtr(uint32_t timerId)
143{
144    std::lock_guard lock(mutex_);
145    // conversion function to void* defined in task.h
146    return static_cast<void*>(handleMap_[timerId]);
147}
148
149/* inner functions must be called when mutex_ is locked */
150void FFRTTimer::CancelAllTimerInner()
151{
152    for (auto &p : handleMap_) {
153        if (p.second != nullptr) {
154            POWER_HILOGD(FEATURE_UTIL, "Timer[%{public}u] Cancel Task[%{public}u]", p.first, taskId_[p.first]);
155            FFRTUtils::CancelTask(p.second, queue_);
156            p.second = nullptr;
157        }
158    }
159}
160
161void FFRTTimer::CancelTimerInner(uint32_t timerId)
162{
163    if (handleMap_[timerId] != nullptr) {
164        POWER_HILOGD(FEATURE_UTIL, "Timer[%{public}u] Cancel Task[%{public}u]", timerId, taskId_[timerId]);
165        FFRTUtils::CancelTask(handleMap_[timerId], queue_);
166        handleMap_[timerId] = nullptr;
167    }
168}
169
170} // namespace PowerMgr
171} // namespace OHOS