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>
185dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
195dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy#include "Task.h"
205dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy#include "TaskProcessor.h"
215dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy#include "TaskManager.h"
225dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
235dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guynamespace android {
245dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guynamespace uirenderer {
255dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
265dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy///////////////////////////////////////////////////////////////////////////////
275dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy// Manager
285dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy///////////////////////////////////////////////////////////////////////////////
295dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
305dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain GuyTaskManager::TaskManager() {
315dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    // Get the number of available CPUs. This value does not change over time.
320a8c51b1d0d66d6060afcec1eab33091d49332aeRomain Guy    int cpuCount = sysconf(_SC_NPROCESSORS_CONF);
335dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
345dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    for (int i = 0; i < cpuCount / 2; i++) {
355dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        String8 name;
365dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        name.appendFormat("hwuiTask%d", i + 1);
375dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        mThreads.add(new WorkerThread(name));
385dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
395dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
405dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
415dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain GuyTaskManager::~TaskManager() {
425dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    for (size_t i = 0; i < mThreads.size(); i++) {
435dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        mThreads[i]->exit();
445dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
455dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
465dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
475dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guybool TaskManager::canRunTasks() const {
485dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return mThreads.size() > 0;
495dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
505dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
51c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guyvoid TaskManager::stop() {
52c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy    for (size_t i = 0; i < mThreads.size(); i++) {
53c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy        mThreads[i]->exit();
54c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy    }
55c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy}
56c5cbee7d78513527e89450e6369a30a04b2d5e7aRomain Guy
575dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guybool TaskManager::addTaskBase(const sp<TaskBase>& task, const sp<TaskProcessorBase>& processor) {
585dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    if (mThreads.size() > 0) {
595dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        TaskWrapper wrapper(task, processor);
605dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
615dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        size_t minQueueSize = INT_MAX;
625dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        sp<WorkerThread> thread;
635dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
645dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        for (size_t i = 0; i < mThreads.size(); i++) {
655dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy            if (mThreads[i]->getTaskCount() < minQueueSize) {
665dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy                thread = mThreads[i];
675dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy                minQueueSize = mThreads[i]->getTaskCount();
685dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy            }
695dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        }
705dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
715dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        return thread->addTask(wrapper);
725dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
735dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return false;
745dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
755dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
765dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy///////////////////////////////////////////////////////////////////////////////
775dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy// Thread
785dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy///////////////////////////////////////////////////////////////////////////////
795dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
805dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guybool TaskManager::WorkerThread::threadLoop() {
815dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    mSignal.wait();
825dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    Vector<TaskWrapper> tasks;
835dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    {
845dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        Mutex::Autolock l(mLock);
855dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        tasks = mTasks;
865dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        mTasks.clear();
875dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
885dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
895dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    for (size_t i = 0; i < tasks.size(); i++) {
905dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        const TaskWrapper& task = tasks.itemAt(i);
915dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        task.mProcessor->process(task.mTask);
925dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
935dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
945dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return true;
955dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
965dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
975dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guybool TaskManager::WorkerThread::addTask(TaskWrapper task) {
985dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    if (!isRunning()) {
995dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        run(mName.string(), PRIORITY_DEFAULT);
1005dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
1015dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1025dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    Mutex::Autolock l(mLock);
1035dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    ssize_t index = mTasks.add(task);
1045dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    mSignal.signal();
1055dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1065dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return index >= 0;
1075dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
1085dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1095dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guysize_t TaskManager::WorkerThread::getTaskCount() const {
1105dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    Mutex::Autolock l(mLock);
1115dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    return mTasks.size();
1125dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
1135dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1145dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guyvoid TaskManager::WorkerThread::exit() {
1155dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    {
1165dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        Mutex::Autolock l(mLock);
1175dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy        mTasks.clear();
1185dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    }
1195dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    requestExit();
1205dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy    mSignal.signal();
1215dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}
1225dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy
1235dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}; // namespace uirenderer
1245dc7fa709646799a5207a5d217f70aa02bf4a3aaRomain Guy}; // namespace android
125