1 /*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "CommonPool.h"
18
19 #undef LOG_TAG
20 #define LOG_TAG "RenderEngine"
21 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
22
23 #include <sys/resource.h>
24 #include <utils/Trace.h>
25
26 #include <system/thread_defs.h>
27 #include <array>
28
29 namespace android {
30 namespace renderengine {
31 namespace skia {
32
CommonPool()33 CommonPool::CommonPool() {
34 ATRACE_CALL();
35
36 CommonPool* pool = this;
37 // Create 2 workers
38 for (int i = 0; i < THREAD_COUNT; i++) {
39 std::thread worker([pool, i] {
40 {
41 std::array<char, 20> name{"reTask"};
42 snprintf(name.data(), name.size(), "reTask%d", i);
43 auto self = pthread_self();
44 pthread_setname_np(self, name.data());
45 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_FOREGROUND);
46 }
47 pool->workerLoop();
48 });
49 worker.detach();
50 }
51 }
52
instance()53 CommonPool& CommonPool::instance() {
54 static CommonPool pool;
55 return pool;
56 }
57
post(Task && task)58 void CommonPool::post(Task&& task) {
59 instance().enqueue(std::move(task));
60 }
61
enqueue(Task && task)62 void CommonPool::enqueue(Task&& task) {
63 std::unique_lock lock(mLock);
64 while (mWorkQueue.size() > QUEUE_SIZE) {
65 lock.unlock();
66 ALOGW("Queue is full: %d, waiting before adding more tasks.", QUEUE_SIZE);
67 usleep(100);
68 lock.lock();
69 }
70 mWorkQueue.push(std::move(task));
71 if (mWaitingThreads == THREAD_COUNT || (mWaitingThreads > 0 && mWorkQueue.size() > 1)) {
72 mCondition.notify_one();
73 }
74 }
75
workerLoop()76 void CommonPool::workerLoop() {
77 std::unique_lock lock(mLock);
78 while (true) {
79 if (mWorkQueue.size() == 0) {
80 mWaitingThreads++;
81 mCondition.wait(lock);
82 mWaitingThreads--;
83 }
84 // Need to double-check that work is still available now that we have the lock
85 // It may have already been grabbed by a different thread
86 while (mWorkQueue.size() > 0) {
87 auto work = mWorkQueue.front();
88 mWorkQueue.pop();
89 lock.unlock();
90 work();
91 lock.lock();
92 }
93 }
94 }
95
96 } // namespace skia
97 } // namespace renderengine
98 } // namespace android