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