1 /*
2 * Copyright (C) 2024 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 "skia_task_executor.h"
17 #include "utils/log.h"
18
19 #ifdef SKIA_PRIO_SCHED_ENABLE
20 #include "qos.h"
21 #endif
22
23 namespace OHOS {
24 namespace Rosen {
25
TaskPoolExecutor()26 TaskPoolExecutor::TaskPoolExecutor()
27 {
28 InitThreadPool();
29 }
30
GetInstance()31 TaskPoolExecutor& TaskPoolExecutor::GetInstance()
32 {
33 static TaskPoolExecutor pool;
34 return pool;
35 }
36
PostTask(Task && task)37 void TaskPoolExecutor::PostTask(Task&& task)
38 {
39 GetInstance().EnqueueTask(std::move(task));
40 }
41
InitThreadPool()42 void TaskPoolExecutor::InitThreadPool()
43 {
44 TaskPoolExecutor* pool = this;
45 // 3 threads are created by default.
46 for (uint32_t i = 0; i < DEFAULT_THREAD_COUNT; i++) {
47 std::thread thread([pool, i] {
48 {
49 std::string name{"SkiaExecutor-"};
50 name.append(std::to_string(i));
51 #if defined(MAC_PLATFORM) || defined(IOS_PLATFORM)
52 pthread_setname_np(name.c_str());
53 #else
54 pthread_setname_np(pthread_self(), name.c_str());
55 #endif
56 }
57 pool->ThreadLoop();
58 });
59 thread.detach();
60 }
61 }
62
EnqueueTask(Task && task)63 void TaskPoolExecutor::EnqueueTask(Task&& task)
64 {
65 std::unique_lock lock(mutex_);
66 while (!taskQueue_.HasSpace()) {
67 lock.unlock();
68 usleep(WAIT_SLEEP_TIME);
69 lock.lock();
70 }
71 taskQueue_.Push(std::move(task));
72 if (waitingThread_ == DEFAULT_THREAD_COUNT || (waitingThread_ > 0 && taskQueue_.Size() > 1)) {
73 condition_.notify_one();
74 }
75 }
76
77 #ifdef RES_SCHED_ENABLE
PromoteThreadPriority()78 void TaskPoolExecutor::PromoteThreadPriority()
79 {
80 if (RsFrameReport::GetInstance().GetEnable()) {
81 RsFrameReport::GetInstance().SetFrameParam(REQUEST_THREAD_PRIORITY_ID, REQUEST_THREAD_PRIORITY_LOAD,
82 REQUEST_THREAD_PRIORITY_NUM, gettid());
83 }
84 }
85 #endif
86
ThreadLoop()87 void TaskPoolExecutor::ThreadLoop()
88 {
89 #ifdef RES_SCHED_ENABLE
90 PromoteThreadPriority();
91 #endif
92
93 #ifdef SKIA_PRIO_SCHED_ENABLE
94 auto ret = OHOS::QOS::SetThreadQos(OHOS::QOS::QosLevel::QOS_USER_INTERACTIVE);
95 LOGI("SkiaExecutor: SetThreadQos retcode = %{public}d", ret);
96 #endif
97 std::unique_lock lock(mutex_);
98 while (running_) {
99 if (!taskQueue_.HasTask()) {
100 waitingThread_++;
101 condition_.wait(lock);
102 waitingThread_--;
103 }
104 while (taskQueue_.HasTask()) {
105 auto task = taskQueue_.Pop();
106 lock.unlock();
107 if (task != nullptr) {
108 task();
109 }
110 lock.lock();
111 }
112 }
113 }
114 } // namespace Rosen
115 } // namespace OHOS