15dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy/*
25dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy * Copyright (C) 2013 The Android Open Source Project
35dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy *
45dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
55dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy * you may not use this file except in compliance with the License.
65dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy * You may obtain a copy of the License at
75dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy *
85dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
95dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy *
105dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy * Unless required by applicable law or agreed to in writing, software
115dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
125dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy * See the License for the specific language governing permissions and
145dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy * limitations under the License.
155dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy */
165dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
175dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy#include <sys/sysinfo.h>
1821be43e142a6fcb3283d7b2da14eb39b690cf643John Reck#if defined(HAVE_PTHREADS)
1921be43e142a6fcb3283d7b2da14eb39b690cf643John Reck#include <sys/resource.h>
2021be43e142a6fcb3283d7b2da14eb39b690cf643John Reck#endif
215dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
2205f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "TaskManager.h"
235dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy#include "Task.h"
245dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy#include "TaskProcessor.h"
2505f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik#include "utils/MathUtils.h"
265dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
275dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guynamespace android {
285dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guynamespace uirenderer {
295dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
305dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy///////////////////////////////////////////////////////////////////////////////
315dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy// Manager
325dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy///////////////////////////////////////////////////////////////////////////////
335dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
345dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain GuyTaskManager::TaskManager() {
355dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    // Get the number of available CPUs. This value does not change over time.
360a8c51b1d0d66d6060afcec1eab33091d49332aeRomain Guy    int cpuCount = sysconf(_SC_NPROCESSORS_CONF);
375dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
3805f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    int workerCount = MathUtils::max(1, cpuCount / 2);
3905f3d6e5111fd08df5cd9aae2c3d28399dc0e7f5Chris Craik    for (int i = 0; i < workerCount; i++) {
405dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        String8 name;
415dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        name.appendFormat("hwuiTask%d", i + 1);
425dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        mThreads.add(new WorkerThread(name));
435dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
445dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
455dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
465dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain GuyTaskManager::~TaskManager() {
475dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    for (size_t i = 0; i < mThreads.size(); i++) {
485dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        mThreads[i]->exit();
495dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
505dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
515dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
525dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guybool TaskManager::canRunTasks() const {
535dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return mThreads.size() > 0;
545dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
555dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
56c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guyvoid TaskManager::stop() {
57c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy    for (size_t i = 0; i < mThreads.size(); i++) {
58c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy        mThreads[i]->exit();
59c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy    }
60c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy}
61c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy
625dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guybool TaskManager::addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) {
635dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    if (mThreads.size() > 0) {
645dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        TaskWrapper wrapper(task, processor);
655dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
665dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        size_t minQueueSize = INT_MAX;
675dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        sp<WorkerThread> thread;
685dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
695dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        for (size_t i = 0; i < mThreads.size(); i++) {
705dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy            if (mThreads[i]->getTaskCount() < minQueueSize) {
715dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy                thread = mThreads[i];
725dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy                minQueueSize = mThreads[i]->getTaskCount();
735dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy            }
745dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        }
755dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
765dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        return thread->addTask(wrapper);
775dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
785dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return false;
795dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
805dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
815dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy///////////////////////////////////////////////////////////////////////////////
825dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy// Thread
835dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy///////////////////////////////////////////////////////////////////////////////
845dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
8521be43e142a6fcb3283d7b2da14eb39b690cf643John Reckstatus_t TaskManager::WorkerThread::readyToRun() {
8621be43e142a6fcb3283d7b2da14eb39b690cf643John Reck#if defined(HAVE_PTHREADS)
8721be43e142a6fcb3283d7b2da14eb39b690cf643John Reck    setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND);
8821be43e142a6fcb3283d7b2da14eb39b690cf643John Reck#endif
8921be43e142a6fcb3283d7b2da14eb39b690cf643John Reck    return NO_ERROR;
9021be43e142a6fcb3283d7b2da14eb39b690cf643John Reck}
9121be43e142a6fcb3283d7b2da14eb39b690cf643John Reck
925dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guybool TaskManager::WorkerThread::threadLoop() {
935dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    mSignal.wait();
945dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    Vector<TaskWrapper> tasks;
955dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    {
965dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        Mutex::Autolock l(mLock);
975dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        tasks = mTasks;
985dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        mTasks.clear();
995dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
1005dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1015dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    for (size_t i = 0; i < tasks.size(); i++) {
1025dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        const TaskWrapper& task = tasks.itemAt(i);
1035dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        task.mProcessor->process(task.mTask);
1045dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
1055dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1065dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return true;
1075dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
1085dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1095dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guybool TaskManager::WorkerThread::addTask(TaskWrapper task) {
1105dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    if (!isRunning()) {
1115dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        run(mName.string(), PRIORITY_DEFAULT);
1125dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
1135dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1145dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    Mutex::Autolock l(mLock);
1155dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    ssize_t index = mTasks.add(task);
1165dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    mSignal.signal();
1175dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1185dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return index >= 0;
1195dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
1205dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1215dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guysize_t TaskManager::WorkerThread::getTaskCount() const {
1225dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    Mutex::Autolock l(mLock);
1235dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return mTasks.size();
1245dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
1255dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1265dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guyvoid TaskManager::WorkerThread::exit() {
1275dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    {
1285dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        Mutex::Autolock l(mLock);
1295dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        mTasks.clear();
1305dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
1315dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    requestExit();
1325dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    mSignal.signal();
1335dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
1345dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1355dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}; // namespace uirenderer
1365dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}; // namespace android
137