• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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_THREAD_LIST_H_
18 #define ART_RUNTIME_THREAD_LIST_H_
19 
20 #include "base/histogram.h"
21 #include "base/mutex.h"
22 #include "base/value_object.h"
23 #include "gc_root.h"
24 #include "jni.h"
25 #include "object_callbacks.h"
26 
27 #include <bitset>
28 #include <list>
29 
30 namespace art {
31 namespace gc {
32   namespace collector {
33     class GarbageCollector;
34   }  // namespac collector
35 }  // namespace gc
36 class Closure;
37 class Thread;
38 class TimingLogger;
39 
40 class ThreadList {
41  public:
42   static const uint32_t kMaxThreadId = 0xFFFF;
43   static const uint32_t kInvalidThreadId = 0;
44   static const uint32_t kMainThreadId = 1;
45 
46   explicit ThreadList();
47   ~ThreadList();
48 
49   void DumpForSigQuit(std::ostream& os)
50       REQUIRES(!Locks::thread_list_lock_, !Locks::mutator_lock_);
51   // For thread suspend timeout dumps.
52   void Dump(std::ostream& os, bool dump_native_stack = true)
53       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
54   pid_t GetLockOwner();  // For SignalCatcher.
55 
56   // Thread suspension support.
57   void ResumeAll()
58       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_)
59       UNLOCK_FUNCTION(Locks::mutator_lock_);
60   void Resume(Thread* thread, bool for_debugger = false)
61       REQUIRES(!Locks::thread_suspend_count_lock_);
62 
63   // Suspends all threads and gets exclusive access to the mutator_lock_.
64   // If long_suspend is true, then other threads who try to suspend will never timeout.
65   // long_suspend is currenly used for hprof since large heaps take a long time.
66   void SuspendAll(const char* cause, bool long_suspend = false)
67       EXCLUSIVE_LOCK_FUNCTION(Locks::mutator_lock_)
68       REQUIRES(!Locks::thread_list_lock_,
69                !Locks::thread_suspend_count_lock_,
70                !Locks::mutator_lock_);
71 
72   // Suspend a thread using a peer, typically used by the debugger. Returns the thread on success,
73   // else null. The peer is used to identify the thread to avoid races with the thread terminating.
74   // If the thread should be suspended then value of request_suspension should be true otherwise
75   // the routine will wait for a previous suspend request. If the suspension times out then *timeout
76   // is set to true.
77   Thread* SuspendThreadByPeer(jobject peer, bool request_suspension, bool debug_suspension,
78                               bool* timed_out)
79       REQUIRES(!Locks::mutator_lock_,
80                !Locks::thread_list_lock_,
81                !Locks::thread_suspend_count_lock_);
82 
83   // Suspend a thread using its thread id, typically used by lock/monitor inflation. Returns the
84   // thread on success else null. The thread id is used to identify the thread to avoid races with
85   // the thread terminating. Note that as thread ids are recycled this may not suspend the expected
86   // thread, that may be terminating. If the suspension times out then *timeout is set to true.
87   Thread* SuspendThreadByThreadId(uint32_t thread_id, bool debug_suspension, bool* timed_out)
88       REQUIRES(!Locks::mutator_lock_,
89                !Locks::thread_list_lock_,
90                !Locks::thread_suspend_count_lock_);
91 
92   // Find an existing thread (or self) by its thread id (not tid).
93   Thread* FindThreadByThreadId(uint32_t thread_id) REQUIRES(Locks::thread_list_lock_);
94 
95   // Run a checkpoint on threads, running threads are not suspended but run the checkpoint inside
96   // of the suspend check. Returns how many checkpoints that are expected to run, including for
97   // already suspended threads for b/24191051.
98   size_t RunCheckpoint(Closure* checkpoint_function)
99       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
100 
101   size_t RunCheckpointOnRunnableThreads(Closure* checkpoint_function)
102       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
103 
104   // Flip thread roots from from-space refs to to-space refs. Used by
105   // the concurrent copying collector.
106   size_t FlipThreadRoots(Closure* thread_flip_visitor,
107                          Closure* flip_callback,
108                          gc::collector::GarbageCollector* collector)
109       REQUIRES(!Locks::mutator_lock_,
110                !Locks::thread_list_lock_,
111                !Locks::thread_suspend_count_lock_);
112 
113   // Suspends all threads
114   void SuspendAllForDebugger()
115       REQUIRES(!Locks::mutator_lock_,
116                !Locks::thread_list_lock_,
117                !Locks::thread_suspend_count_lock_);
118 
119   void SuspendSelfForDebugger()
120       REQUIRES(!Locks::thread_suspend_count_lock_);
121 
122   // Resume all threads
123   void ResumeAllForDebugger()
124       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
125 
126   void UndoDebuggerSuspensions()
127       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
128 
129   // Iterates over all the threads.
130   void ForEach(void (*callback)(Thread*, void*), void* context)
131       REQUIRES(Locks::thread_list_lock_);
132 
133   // Add/remove current thread from list.
134   void Register(Thread* self)
135       REQUIRES(Locks::runtime_shutdown_lock_)
136       REQUIRES(!Locks::mutator_lock_,
137                !Locks::thread_list_lock_,
138                !Locks::thread_suspend_count_lock_);
139   void Unregister(Thread* self)
140       REQUIRES(!Locks::mutator_lock_,
141                !Locks::thread_list_lock_,
142                !Locks::thread_suspend_count_lock_);
143 
144   void VisitRoots(RootVisitor* visitor) const
145       SHARED_REQUIRES(Locks::mutator_lock_);
146 
147   // Return a copy of the thread list.
GetList()148   std::list<Thread*> GetList() REQUIRES(Locks::thread_list_lock_) {
149     return list_;
150   }
151 
152   void DumpNativeStacks(std::ostream& os)
153       REQUIRES(!Locks::thread_list_lock_);
154 
155  private:
156   uint32_t AllocThreadId(Thread* self);
157   void ReleaseThreadId(Thread* self, uint32_t id) REQUIRES(!Locks::allocated_thread_ids_lock_);
158 
159   bool Contains(Thread* thread) REQUIRES(Locks::thread_list_lock_);
160   bool Contains(pid_t tid) REQUIRES(Locks::thread_list_lock_);
161   size_t RunCheckpoint(Closure* checkpoint_function, bool includeSuspended)
162       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
163 
164   void DumpUnattachedThreads(std::ostream& os, bool dump_native_stack)
165       REQUIRES(!Locks::thread_list_lock_);
166 
167   void SuspendAllDaemonThreadsForShutdown()
168       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
169   void WaitForOtherNonDaemonThreadsToExit()
170       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
171 
172   void SuspendAllInternal(Thread* self,
173                           Thread* ignore1,
174                           Thread* ignore2 = nullptr,
175                           bool debug_suspend = false)
176       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
177 
178   void AssertThreadsAreSuspended(Thread* self, Thread* ignore1, Thread* ignore2 = nullptr)
179       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_);
180 
181   std::bitset<kMaxThreadId> allocated_ids_ GUARDED_BY(Locks::allocated_thread_ids_lock_);
182 
183   // The actual list of all threads.
184   std::list<Thread*> list_ GUARDED_BY(Locks::thread_list_lock_);
185 
186   // Ongoing suspend all requests, used to ensure threads added to list_ respect SuspendAll.
187   int suspend_all_count_ GUARDED_BY(Locks::thread_suspend_count_lock_);
188   int debug_suspend_all_count_ GUARDED_BY(Locks::thread_suspend_count_lock_);
189 
190   // Number of threads unregistering, ~ThreadList blocks until this hits 0.
191   int unregistering_count_ GUARDED_BY(Locks::thread_list_lock_);
192 
193   // Thread suspend time histogram. Only modified when all the threads are suspended, so guarding
194   // by mutator lock ensures no thread can read when another thread is modifying it.
195   Histogram<uint64_t> suspend_all_historam_ GUARDED_BY(Locks::mutator_lock_);
196 
197   // Whether or not the current thread suspension is long.
198   bool long_suspend_;
199 
200   friend class Thread;
201 
202   DISALLOW_COPY_AND_ASSIGN(ThreadList);
203 };
204 
205 // Helper for suspending all threads and
206 class ScopedSuspendAll : public ValueObject {
207  public:
208   ScopedSuspendAll(const char* cause, bool long_suspend = false)
209      EXCLUSIVE_LOCK_FUNCTION(Locks::mutator_lock_)
210      REQUIRES(!Locks::thread_list_lock_,
211               !Locks::thread_suspend_count_lock_,
212               !Locks::mutator_lock_);
213   // No REQUIRES(mutator_lock_) since the unlock function already asserts this.
214   ~ScopedSuspendAll()
215       REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_)
216       UNLOCK_FUNCTION(Locks::mutator_lock_);
217 };
218 
219 }  // namespace art
220 
221 #endif  // ART_RUNTIME_THREAD_LIST_H_
222