1a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier/* 2a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * Copyright (C) 2014 The Android Open Source Project 3a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * 4a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License"); 5a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * you may not use this file except in compliance with the License. 6a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * You may obtain a copy of the License at 7a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * 8a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * http://www.apache.org/licenses/LICENSE-2.0 9a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * 10a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * Unless required by applicable law or agreed to in writing, software 11a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS, 12a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * See the License for the specific language governing permissions and 14a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier * limitations under the License. 15a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier */ 16a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 17a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier#include "task_processor.h" 18a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 1980afd02024d20e60b197d3adfbb43cc303cf29e0Vladimir Marko#include "base/time_utils.h" 20a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier#include "scoped_thread_state_change.h" 21a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 22a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartiernamespace art { 23a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartiernamespace gc { 24a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 25a5eae69589ff562ad66c57665882cd16f237321cMathieu ChartierTaskProcessor::TaskProcessor() 26a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi : lock_(new Mutex("Task processor lock", kReferenceProcessorLock)), is_running_(false), 27a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi running_thread_(nullptr) { 28a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // Piggyback off the reference processor lock level. 29a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier cond_.reset(new ConditionVariable("Task processor condition", *lock_)); 30a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} 31a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 32a5eae69589ff562ad66c57665882cd16f237321cMathieu ChartierTaskProcessor::~TaskProcessor() { 33a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier delete lock_; 34a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} 35a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 36a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartiervoid TaskProcessor::AddTask(Thread* self, HeapTask* task) { 37a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier ScopedThreadStateChange tsc(self, kBlocked); 38a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier MutexLock mu(self, *lock_); 39a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier tasks_.insert(task); 40a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier cond_->Signal(self); 41a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} 42a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 43a5eae69589ff562ad66c57665882cd16f237321cMathieu ChartierHeapTask* TaskProcessor::GetTask(Thread* self) { 44a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier ScopedThreadStateChange tsc(self, kBlocked); 45a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier MutexLock mu(self, *lock_); 46a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier while (true) { 47a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier if (tasks_.empty()) { 48a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier if (!is_running_) { 49a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier return nullptr; 50a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 51a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier cond_->Wait(self); // Empty queue, wait until we are signalled. 52a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } else { 53a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // Non empty queue, look at the top element and see if we are ready to run it. 54a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier const uint64_t current_time = NanoTime(); 55a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier HeapTask* task = *tasks_.begin(); 56a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // If we are shutting down, return the task right away without waiting. Otherwise return the 57a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // task if it is late enough. 58a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier uint64_t target_time = task->GetTargetRunTime(); 59a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier if (!is_running_ || target_time <= current_time) { 60a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier tasks_.erase(tasks_.begin()); 61a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier return task; 62a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 63a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier DCHECK_GT(target_time, current_time); 64a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // Wait untl we hit the target run time. 65a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier const uint64_t delta_time = target_time - current_time; 66a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier const uint64_t ms_delta = NsToMs(delta_time); 67a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier const uint64_t ns_delta = delta_time - MsToNs(ms_delta); 68a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier cond_->TimedWait(self, static_cast<int64_t>(ms_delta), static_cast<int32_t>(ns_delta)); 69a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 70a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 71a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier UNREACHABLE(); 72a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} 73a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 74a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartiervoid TaskProcessor::UpdateTargetRunTime(Thread* self, HeapTask* task, uint64_t new_target_time) { 75a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier MutexLock mu(self, *lock_); 76a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // Find the task. 77a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier auto range = tasks_.equal_range(task); 78a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier for (auto it = range.first; it != range.second; ++it) { 79a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier if (*it == task) { 80a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // Check if the target time was updated, if so re-insert then wait. 81a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier if (new_target_time != task->GetTargetRunTime()) { 82a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier tasks_.erase(it); 83a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier task->SetTargetRunTime(new_target_time); 84a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier tasks_.insert(task); 85a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // If we became the first task then we may need to signal since we changed the task that we 86a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // are sleeping on. 87a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier if (*tasks_.begin() == task) { 88a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier cond_->Signal(self); 89a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 90a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier return; 91a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 92a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 93a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 94a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} 95a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 96a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartierbool TaskProcessor::IsRunning() const { 97a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier MutexLock mu(Thread::Current(), *lock_); 98a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier return is_running_; 99a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} 100a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 101a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi YamauchiThread* TaskProcessor::GetRunningThread() const { 102a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi MutexLock mu(Thread::Current(), *lock_); 103a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi return running_thread_; 104a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi} 105a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi 106a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartiervoid TaskProcessor::Stop(Thread* self) { 107a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier MutexLock mu(self, *lock_); 108a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier is_running_ = false; 109a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi running_thread_ = nullptr; 110a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier cond_->Broadcast(self); 111a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} 112a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 113a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartiervoid TaskProcessor::Start(Thread* self) { 114a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier MutexLock mu(self, *lock_); 115a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier is_running_ = true; 116a1c9f013c034fbddb9337cc5c7ecf0e5a8b77547Hiroshi Yamauchi running_thread_ = self; 117a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} 118a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 119a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartiervoid TaskProcessor::RunAllTasks(Thread* self) { 120a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier while (true) { 121a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier // Wait and get a task, may be interrupted. 122a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier HeapTask* task = GetTask(self); 123a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier if (task != nullptr) { 124a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier task->Run(self); 125a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier task->Finalize(); 126a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } else if (!IsRunning()) { 127a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier break; 128a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 129a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier } 130a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} 131a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier 132a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} // namespace gc 133a5eae69589ff562ad66c57665882cd16f237321cMathieu Chartier} // namespace art 134