blob: de10ff1824eed678f3fab3ded6e4153707d20c53 [file] [log] [blame]
Romain Guy5dc7fa72013-03-11 20:48:31 -07001/*
2 * Copyright (C) 2013 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
John Reck21be43e2014-08-14 10:25:16 -070017#include <sys/resource.h>
Yabin Cui16104862015-01-26 19:43:58 -080018#include <sys/sysinfo.h>
Romain Guy5dc7fa72013-03-11 20:48:31 -070019
20#include "Task.h"
John Reck1bcacfd2017-11-03 10:12:19 -070021#include "TaskManager.h"
Romain Guy5dc7fa72013-03-11 20:48:31 -070022#include "TaskProcessor.h"
Chris Craik05f3d6e2014-06-02 16:27:04 -070023#include "utils/MathUtils.h"
Stan Iliev80dbc352019-02-05 15:31:28 -050024#include "renderthread/RenderThread.h"
Romain Guy5dc7fa72013-03-11 20:48:31 -070025
26namespace android {
27namespace uirenderer {
28
29///////////////////////////////////////////////////////////////////////////////
30// Manager
31///////////////////////////////////////////////////////////////////////////////
32
33TaskManager::TaskManager() {
34 // Get the number of available CPUs. This value does not change over time.
Romain Guy0a8c51b2013-08-21 17:35:38 -070035 int cpuCount = sysconf(_SC_NPROCESSORS_CONF);
Romain Guy5dc7fa72013-03-11 20:48:31 -070036
John Reckc4526542015-07-07 12:17:50 -070037 // Really no point in making more than 2 of these worker threads, but
38 // we do want to limit ourselves to 1 worker thread on dual-core devices.
39 int workerCount = cpuCount > 2 ? 2 : 1;
Chris Craik05f3d6e2014-06-02 16:27:04 -070040 for (int i = 0; i < workerCount; i++) {
Romain Guy5dc7fa72013-03-11 20:48:31 -070041 String8 name;
42 name.appendFormat("hwuiTask%d", i + 1);
John Reck272a6852015-07-29 16:48:58 -070043 mThreads.push_back(new WorkerThread(name));
Romain Guy5dc7fa72013-03-11 20:48:31 -070044 }
45}
46
47TaskManager::~TaskManager() {
48 for (size_t i = 0; i < mThreads.size(); i++) {
49 mThreads[i]->exit();
50 }
51}
52
53bool TaskManager::canRunTasks() const {
54 return mThreads.size() > 0;
55}
56
Romain Guyc5cbee72013-03-20 19:15:02 -070057void TaskManager::stop() {
58 for (size_t i = 0; i < mThreads.size(); i++) {
59 mThreads[i]->exit();
60 }
61}
62
Romain Guy5dc7fa72013-03-11 20:48:31 -070063bool TaskManager::addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) {
64 if (mThreads.size() > 0) {
65 TaskWrapper wrapper(task, processor);
66
67 size_t minQueueSize = INT_MAX;
68 sp<WorkerThread> thread;
69
70 for (size_t i = 0; i < mThreads.size(); i++) {
71 if (mThreads[i]->getTaskCount() < minQueueSize) {
72 thread = mThreads[i];
73 minQueueSize = mThreads[i]->getTaskCount();
74 }
75 }
76
77 return thread->addTask(wrapper);
78 }
79 return false;
80}
81
82///////////////////////////////////////////////////////////////////////////////
83// Thread
84///////////////////////////////////////////////////////////////////////////////
85
John Reck21be43e2014-08-14 10:25:16 -070086status_t TaskManager::WorkerThread::readyToRun() {
John Reck21be43e2014-08-14 10:25:16 -070087 setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND);
Stan Iliev80dbc352019-02-05 15:31:28 -050088 auto onStartHook = renderthread::RenderThread::getOnStartHook();
89 if (onStartHook) {
Stan Iliev978d5322019-02-06 12:02:28 -050090 onStartHook(mName.c_str());
Stan Iliev80dbc352019-02-05 15:31:28 -050091 }
92
John Reck21be43e2014-08-14 10:25:16 -070093 return NO_ERROR;
94}
95
Romain Guy5dc7fa72013-03-11 20:48:31 -070096bool TaskManager::WorkerThread::threadLoop() {
97 mSignal.wait();
John Reck272a6852015-07-29 16:48:58 -070098 std::vector<TaskWrapper> tasks;
Romain Guy5dc7fa72013-03-11 20:48:31 -070099 {
100 Mutex::Autolock l(mLock);
John Reck272a6852015-07-29 16:48:58 -0700101 tasks.swap(mTasks);
Romain Guy5dc7fa72013-03-11 20:48:31 -0700102 }
103
104 for (size_t i = 0; i < tasks.size(); i++) {
John Reck272a6852015-07-29 16:48:58 -0700105 const TaskWrapper& task = tasks[i];
Romain Guy5dc7fa72013-03-11 20:48:31 -0700106 task.mProcessor->process(task.mTask);
107 }
108
109 return true;
110}
111
Chris Craikb251a2f2016-02-08 19:36:46 +0000112bool TaskManager::WorkerThread::addTask(const TaskWrapper& task) {
Romain Guy5dc7fa72013-03-11 20:48:31 -0700113 if (!isRunning()) {
114 run(mName.string(), PRIORITY_DEFAULT);
Sangkyu Leec3c58e02015-01-12 09:51:53 +0900115 } else if (exitPending()) {
116 return false;
Romain Guy5dc7fa72013-03-11 20:48:31 -0700117 }
118
John Reck815f2a02015-03-24 12:16:37 -0700119 {
120 Mutex::Autolock l(mLock);
John Reck272a6852015-07-29 16:48:58 -0700121 mTasks.push_back(task);
John Reck815f2a02015-03-24 12:16:37 -0700122 }
Romain Guy5dc7fa72013-03-11 20:48:31 -0700123 mSignal.signal();
124
John Reck272a6852015-07-29 16:48:58 -0700125 return true;
Romain Guy5dc7fa72013-03-11 20:48:31 -0700126}
127
128size_t TaskManager::WorkerThread::getTaskCount() const {
129 Mutex::Autolock l(mLock);
130 return mTasks.size();
131}
132
133void TaskManager::WorkerThread::exit() {
Romain Guy5dc7fa72013-03-11 20:48:31 -0700134 requestExit();
135 mSignal.signal();
136}
137
Chris Blume7b8a8082018-11-30 15:51:58 -0800138} // namespace uirenderer
139} // namespace android