1 /*
2  * Copyright (C) 2014 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 
17 #ifndef ART_RUNTIME_GC_TASK_PROCESSOR_H_
18 #define ART_RUNTIME_GC_TASK_PROCESSOR_H_
19 
20 #include <memory>
21 #include <set>
22 
23 #include "base/macros.h"
24 #include "base/mutex.h"
25 #include "runtime_globals.h"
26 #include "thread_pool.h"
27 
28 namespace art HIDDEN {
29 namespace gc {
30 
31 class HeapTask : public SelfDeletingTask {
32  public:
HeapTask(uint64_t target_run_time)33   explicit HeapTask(uint64_t target_run_time) : target_run_time_(target_run_time) {
34   }
GetTargetRunTime()35   uint64_t GetTargetRunTime() const {
36     return target_run_time_;
37   }
38 
39  private:
40   // Update the updated_target_run_time_, the task processor will re-insert the task when it is
41   // popped and update the target_run_time_.
SetTargetRunTime(uint64_t new_target_run_time)42   void SetTargetRunTime(uint64_t new_target_run_time) {
43     target_run_time_ = new_target_run_time;
44   }
45 
46   // Time in ns at which we want the task to run.
47   uint64_t target_run_time_;
48 
49   friend class TaskProcessor;
50   DISALLOW_IMPLICIT_CONSTRUCTORS(HeapTask);
51 };
52 
53 // Used to process GC tasks (heap trim, heap transitions, concurrent GC).
54 class TaskProcessor {
55  public:
56   TaskProcessor();
57   virtual ~TaskProcessor();
58   void AddTask(Thread* self, HeapTask* task) REQUIRES(!lock_);
59   HeapTask* GetTask(Thread* self) REQUIRES(!lock_);
60   void Start(Thread* self) REQUIRES(!lock_);
61   // Stop tells the RunAllTasks to finish up the remaining tasks as soon as
62   // possible then return.
63   void Stop(Thread* self) REQUIRES(!lock_);
64   void RunAllTasks(Thread* self) REQUIRES(!lock_);
65   bool IsRunning() const REQUIRES(!lock_);
66   void UpdateTargetRunTime(Thread* self, HeapTask* target_time, uint64_t new_target_time)
67       REQUIRES(!lock_);
68   // Is the given thread the task processor thread?
69   // If wait is true, and no thread has been registered via Start(), we briefly
70   // wait for one to be registered. If we time out, we return true.
71   bool IsRunningThread(Thread* t, bool wait = false) REQUIRES(!lock_);
72 
73  private:
74   // Wait briefly for running_thread_ to become non-null. Return false on timeout.
75   bool WaitForThread(Thread* self) REQUIRES(lock_);
76 
77   class CompareByTargetRunTime {
78    public:
operator()79     bool operator()(const HeapTask* a, const HeapTask* b) const {
80       return a->GetTargetRunTime() < b->GetTargetRunTime();
81     }
82   };
83 
84   mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
85   ConditionVariable cond_ GUARDED_BY(lock_);
86   bool is_running_ GUARDED_BY(lock_);
87   std::multiset<HeapTask*, CompareByTargetRunTime> tasks_ GUARDED_BY(lock_);
88   Thread* running_thread_ GUARDED_BY(lock_);
89 
90   DISALLOW_COPY_AND_ASSIGN(TaskProcessor);
91 };
92 
93 }  // namespace gc
94 }  // namespace art
95 
96 #endif  // ART_RUNTIME_GC_TASK_PROCESSOR_H_
97