blob: 29a0195e33f585a67366252004fc2e44b567ccad [file] [log] [blame]
Elliott Hughes8daa0922011-09-11 13:46:25 -07001/*
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#include "thread_list.h"
18
Elliott Hughes038a8062011-09-18 14:12:41 -070019#include <unistd.h>
20
Elliott Hughes8daa0922011-09-11 13:46:25 -070021namespace art {
22
Elliott Hughes14357e82011-09-26 10:42:15 -070023ThreadList::ThreadList(bool verbose)
24 : verbose_(verbose),
25 thread_list_lock_("thread list lock"),
Elliott Hughes5f791332011-09-15 17:45:30 -070026 thread_start_cond_("thread_start_cond_"),
Elliott Hughes038a8062011-09-18 14:12:41 -070027 thread_exit_cond_("thread_exit_cond_"),
Elliott Hughes5f791332011-09-15 17:45:30 -070028 thread_suspend_count_lock_("thread suspend count lock"),
29 thread_suspend_count_cond_("thread_suspend_count_cond_") {
Elliott Hughes8daa0922011-09-11 13:46:25 -070030}
31
32ThreadList::~ThreadList() {
Elliott Hughes038a8062011-09-18 14:12:41 -070033 // Detach the current thread if necessary.
Elliott Hughes8daa0922011-09-11 13:46:25 -070034 if (Contains(Thread::Current())) {
35 Runtime::Current()->DetachCurrentThread();
36 }
37
Elliott Hughes038a8062011-09-18 14:12:41 -070038 WaitForNonDaemonThreadsToExit();
39 SuspendAllDaemonThreads();
Elliott Hughes8daa0922011-09-11 13:46:25 -070040}
41
42bool ThreadList::Contains(Thread* thread) {
43 return find(list_.begin(), list_.end(), thread) != list_.end();
44}
45
Brian Carlstrom24a3c2e2011-10-17 18:07:52 -070046pid_t ThreadList::GetLockOwner() {
Elliott Hughesaccd83d2011-10-17 14:25:58 -070047 return thread_list_lock_.GetOwner();
48}
49
Elliott Hughes8daa0922011-09-11 13:46:25 -070050void ThreadList::Dump(std::ostream& os) {
Elliott Hughes8d768a92011-09-14 16:35:25 -070051 MutexLock mu(thread_list_lock_);
Elliott Hughes8daa0922011-09-11 13:46:25 -070052 os << "DALVIK THREADS (" << list_.size() << "):\n";
Elliott Hughes8daa0922011-09-11 13:46:25 -070053 for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
54 (*it)->Dump(os);
55 os << "\n";
56 }
57}
58
Elliott Hughes8d768a92011-09-14 16:35:25 -070059void ThreadList::FullSuspendCheck(Thread* thread) {
60 CHECK(thread != NULL);
61 CHECK_GE(thread->suspend_count_, 0);
62
63 MutexLock mu(thread_suspend_count_lock_);
64 if (thread->suspend_count_ == 0) {
65 return;
66 }
67
Elliott Hughes14357e82011-09-26 10:42:15 -070068 if (verbose_) {
69 LOG(INFO) << *thread << " self-suspending";
70 }
Elliott Hughes8d768a92011-09-14 16:35:25 -070071 {
72 ScopedThreadStateChange tsc(thread, Thread::kSuspended);
73 while (thread->suspend_count_ != 0) {
74 /*
75 * Wait for wakeup signal, releasing lock. The act of releasing
76 * and re-acquiring the lock provides the memory barriers we
77 * need for correct behavior on SMP.
78 */
Elliott Hughes5f791332011-09-15 17:45:30 -070079 thread_suspend_count_cond_.Wait(thread_suspend_count_lock_);
Elliott Hughes8d768a92011-09-14 16:35:25 -070080 }
81 CHECK_EQ(thread->suspend_count_, 0);
82 }
Elliott Hughes14357e82011-09-26 10:42:15 -070083 if (verbose_) {
84 LOG(INFO) << *thread << " self-reviving";
85 }
Elliott Hughes8d768a92011-09-14 16:35:25 -070086}
87
88void ThreadList::SuspendAll() {
89 Thread* self = Thread::Current();
90
91 // TODO: add another thread_suspend_lock_ to avoid GC/debugger races.
92
Elliott Hughes14357e82011-09-26 10:42:15 -070093 if (verbose_) {
94 LOG(INFO) << *self << " SuspendAll starting...";
95 }
Elliott Hughes8d768a92011-09-14 16:35:25 -070096
Brian Carlstrom6fbb5162011-10-20 20:55:38 -070097 // Avoid deadlock between two threads trying to SuspendAll
98 // simultaneously by going to kVmWait if the lock cannot be
99 // immediately acquired.
100 if (!thread_list_lock_.TryLock()) {
101 ScopedThreadStateChange tsc(Thread::Current(), Thread::kVmWait);
102 thread_list_lock_.Lock();
103 }
Elliott Hughes8d768a92011-09-14 16:35:25 -0700104
105 {
106 // Increment everybody's suspend count (except our own).
107 MutexLock mu(thread_suspend_count_lock_);
108 for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
109 Thread* thread = *it;
110 if (thread != self) {
Elliott Hughes14357e82011-09-26 10:42:15 -0700111 if (verbose_) {
112 LOG(INFO) << "requesting thread suspend: " << *thread;
113 }
Elliott Hughes8d768a92011-09-14 16:35:25 -0700114 ++thread->suspend_count_;
115 }
116 }
117 }
118
119 /*
120 * Wait for everybody in kRunnable state to stop. Other states
121 * indicate the code is either running natively or sleeping quietly.
122 * Any attempt to transition back to kRunnable will cause a check
123 * for suspension, so it should be impossible for anything to execute
124 * interpreted code or modify objects (assuming native code plays nicely).
125 *
126 * It's also okay if the thread transitions to a non-kRunnable state.
127 *
Elliott Hughes038a8062011-09-18 14:12:41 -0700128 * Note we released the thread_suspend_count_lock_ before getting here,
Elliott Hughes8d768a92011-09-14 16:35:25 -0700129 * so if another thread is fiddling with its suspend count (perhaps
130 * self-suspending for the debugger) it won't block while we're waiting
131 * in here.
132 */
133 for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
134 Thread* thread = *it;
135 if (thread != self) {
136 thread->WaitUntilSuspended();
Elliott Hughes14357e82011-09-26 10:42:15 -0700137 if (verbose_) {
138 LOG(INFO) << "thread suspended: " << *thread;
139 }
Elliott Hughes8d768a92011-09-14 16:35:25 -0700140 }
141 }
142
Brian Carlstrom6fbb5162011-10-20 20:55:38 -0700143 thread_list_lock_.Unlock();
144
Elliott Hughes14357e82011-09-26 10:42:15 -0700145 if (verbose_) {
146 LOG(INFO) << *self << " SuspendAll complete";
147 }
Elliott Hughes8d768a92011-09-14 16:35:25 -0700148}
149
Elliott Hughes01158d72011-09-19 19:47:10 -0700150void ThreadList::Suspend(Thread* thread) {
151 DCHECK(thread != Thread::Current());
152
153 // TODO: add another thread_suspend_lock_ to avoid GC/debugger races.
154
Elliott Hughes14357e82011-09-26 10:42:15 -0700155 if (verbose_) {
156 LOG(INFO) << "Suspend(" << *thread << ") starting...";
157 }
Elliott Hughes01158d72011-09-19 19:47:10 -0700158
159 MutexLock mu(thread_list_lock_);
160 if (!Contains(thread)) {
161 return;
162 }
163
164 {
165 MutexLock mu(thread_suspend_count_lock_);
166 ++thread->suspend_count_;
167 }
168
169 thread->WaitUntilSuspended();
170
Elliott Hughes14357e82011-09-26 10:42:15 -0700171 if (verbose_) {
172 LOG(INFO) << "Suspend(" << *thread << ") complete";
173 }
Elliott Hughes01158d72011-09-19 19:47:10 -0700174}
175
176
Elliott Hughes8d768a92011-09-14 16:35:25 -0700177void ThreadList::ResumeAll() {
178 Thread* self = Thread::Current();
179
Elliott Hughes14357e82011-09-26 10:42:15 -0700180 if (verbose_) {
181 LOG(INFO) << *self << " ResumeAll starting";
182 }
Elliott Hughes8d768a92011-09-14 16:35:25 -0700183
184 // Decrement the suspend counts for all threads. No need for atomic
185 // writes, since nobody should be moving until we decrement the count.
186 // We do need to hold the thread list because of JNI attaches.
187 {
188 MutexLock mu1(thread_list_lock_);
189 MutexLock mu2(thread_suspend_count_lock_);
190 for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
191 Thread* thread = *it;
192 if (thread != self) {
193 if (thread->suspend_count_ > 0) {
194 --thread->suspend_count_;
195 } else {
196 LOG(WARNING) << *thread << " suspend count already zero";
197 }
198 }
199 }
200 }
201
202 // Broadcast a notification to all suspended threads, some or all of
203 // which may choose to wake up. No need to wait for them.
204 {
Elliott Hughes14357e82011-09-26 10:42:15 -0700205 if (verbose_) {
206 LOG(INFO) << *self << " ResumeAll waking others";
207 }
Elliott Hughes8d768a92011-09-14 16:35:25 -0700208 MutexLock mu(thread_suspend_count_lock_);
Elliott Hughes5f791332011-09-15 17:45:30 -0700209 thread_suspend_count_cond_.Broadcast();
Elliott Hughes8d768a92011-09-14 16:35:25 -0700210 }
211
Elliott Hughes14357e82011-09-26 10:42:15 -0700212 if (verbose_) {
213 LOG(INFO) << *self << " ResumeAll complete";
214 }
Elliott Hughes8d768a92011-09-14 16:35:25 -0700215}
216
Elliott Hughes01158d72011-09-19 19:47:10 -0700217void ThreadList::Resume(Thread* thread) {
218 DCHECK(thread != Thread::Current());
219
Elliott Hughes14357e82011-09-26 10:42:15 -0700220 if (verbose_) {
221 LOG(INFO) << "Resume(" << *thread << ") starting...";
222 }
Elliott Hughes01158d72011-09-19 19:47:10 -0700223
224 {
225 MutexLock mu1(thread_list_lock_);
226 MutexLock mu2(thread_suspend_count_lock_);
227 if (!Contains(thread)) {
228 return;
229 }
230 if (thread->suspend_count_ > 0) {
231 --thread->suspend_count_;
232 } else {
233 LOG(WARNING) << *thread << " suspend count already zero";
234 }
235 }
236
237 {
Elliott Hughes14357e82011-09-26 10:42:15 -0700238 if (verbose_) {
239 LOG(INFO) << "Resume(" << *thread << ") waking others";
240 }
Elliott Hughes01158d72011-09-19 19:47:10 -0700241 MutexLock mu(thread_suspend_count_lock_);
242 thread_suspend_count_cond_.Broadcast();
243 }
244
Elliott Hughes14357e82011-09-26 10:42:15 -0700245 if (verbose_) {
246 LOG(INFO) << "Resume(" << *thread << ") complete";
247 }
Elliott Hughes01158d72011-09-19 19:47:10 -0700248}
249
250void ThreadList::RunWhileSuspended(Thread* thread, void (*callback)(void*), void* arg) {
251 DCHECK(thread != NULL);
252 Thread* self = Thread::Current();
253 if (thread != self) {
254 Suspend(thread);
255 }
256 callback(arg);
257 if (thread != self) {
258 Resume(thread);
259 }
260}
261
Elliott Hughes7a3aeb42011-09-25 17:39:47 -0700262void ThreadList::Register() {
263 Thread* self = Thread::Current();
264
Elliott Hughes14357e82011-09-26 10:42:15 -0700265 if (verbose_) {
266 LOG(INFO) << "ThreadList::Register() " << *self;
267 self->Dump(std::cerr);
268 }
Elliott Hughes7a3aeb42011-09-25 17:39:47 -0700269
Elliott Hughes8d768a92011-09-14 16:35:25 -0700270 MutexLock mu(thread_list_lock_);
Elliott Hughes7a3aeb42011-09-25 17:39:47 -0700271 CHECK(!Contains(self));
272 list_.push_back(self);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700273}
274
275void ThreadList::Unregister() {
276 Thread* self = Thread::Current();
277
Elliott Hughes14357e82011-09-26 10:42:15 -0700278 if (verbose_) {
279 LOG(INFO) << "ThreadList::Unregister() " << *self;
280 }
281
Elliott Hughesaccd83d2011-10-17 14:25:58 -0700282 // This may need to call user-supplied managed code. Make sure we do this before we start tearing
283 // down the Thread* and removing it from the thread list (or start taking any locks).
284 self->HandleUncaughtExceptions();
285
Elliott Hughes8d768a92011-09-14 16:35:25 -0700286 MutexLock mu(thread_list_lock_);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700287
288 // Remove this thread from the list.
289 CHECK(Contains(self));
290 list_.remove(self);
291
292 // Delete the Thread* and release the thin lock id.
293 uint32_t thin_lock_id = self->thin_lock_id_;
294 delete self;
295 ReleaseThreadId(thin_lock_id);
296
297 // Clear the TLS data, so that thread is recognizably detached.
298 // (It may wish to reattach later.)
Elliott Hughes8d768a92011-09-14 16:35:25 -0700299 CHECK_PTHREAD_CALL(pthread_setspecific, (Thread::pthread_key_self_, NULL), "detach self");
Elliott Hughes038a8062011-09-18 14:12:41 -0700300
301 // Signal that a thread just detached.
302 thread_exit_cond_.Signal();
Elliott Hughes8daa0922011-09-11 13:46:25 -0700303}
304
305void ThreadList::VisitRoots(Heap::RootVisitor* visitor, void* arg) const {
Elliott Hughes8d768a92011-09-14 16:35:25 -0700306 MutexLock mu(thread_list_lock_);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700307 for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
308 (*it)->VisitRoots(visitor, arg);
309 }
310}
311
Elliott Hughes93e74e82011-09-13 11:07:03 -0700312/*
313 * Tell a new thread it's safe to start.
314 *
315 * We must hold the thread list lock before messing with another thread.
316 * In the general case we would also need to verify that the new thread was
317 * still in the thread list, but in our case the thread has not started
318 * executing user code and therefore has not had a chance to exit.
319 *
320 * We move it to kVmWait, and it then shifts itself to kRunning, which
321 * comes with a suspend-pending check. We do this after
322 */
323void ThreadList::SignalGo(Thread* child) {
324 Thread* self = Thread::Current();
325 CHECK(child != self);
326
327 {
Elliott Hughes8d768a92011-09-14 16:35:25 -0700328 MutexLock mu(thread_list_lock_);
Elliott Hughes93e74e82011-09-13 11:07:03 -0700329
330 // We wait for the child to tell us that it's in the thread list.
331 while (child->GetState() != Thread::kStarting) {
Elliott Hughes5f791332011-09-15 17:45:30 -0700332 thread_start_cond_.Wait(thread_list_lock_);
Elliott Hughes93e74e82011-09-13 11:07:03 -0700333 }
334 }
335
336 // If we switch out of runnable and then back in, we know there's no pending suspend.
337 self->SetState(Thread::kVmWait);
338 self->SetState(Thread::kRunnable);
339
340 // Tell the child that it's safe: it will see any future suspend request.
341 child->SetState(Thread::kVmWait);
Elliott Hughes5f791332011-09-15 17:45:30 -0700342 thread_start_cond_.Broadcast();
Elliott Hughes93e74e82011-09-13 11:07:03 -0700343}
344
345void ThreadList::WaitForGo() {
346 Thread* self = Thread::Current();
347 DCHECK(Contains(self));
348
Brian Carlstrom6fbb5162011-10-20 20:55:38 -0700349 {
350 MutexLock mu(thread_list_lock_);
Elliott Hughes93e74e82011-09-13 11:07:03 -0700351
Brian Carlstrom6fbb5162011-10-20 20:55:38 -0700352 // Tell our parent that we're in the thread list.
353 self->SetState(Thread::kStarting);
354 thread_start_cond_.Broadcast();
Elliott Hughes93e74e82011-09-13 11:07:03 -0700355
Brian Carlstrom6fbb5162011-10-20 20:55:38 -0700356 // Wait until our parent tells us there's no suspend still pending
357 // from before we were on the thread list.
358 while (self->GetState() != Thread::kVmWait) {
359 thread_start_cond_.Wait(thread_list_lock_);
360 }
Elliott Hughes93e74e82011-09-13 11:07:03 -0700361 }
362
363 // Enter the runnable state. We know that any pending suspend will affect us now.
364 self->SetState(Thread::kRunnable);
365}
366
Elliott Hughes038a8062011-09-18 14:12:41 -0700367bool ThreadList::AllThreadsAreDaemons() {
368 for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
Ian Rogerscbba6ac2011-09-22 16:28:37 -0700369 // TODO: there's a race here with thread exit that's being worked around by checking if the peer
370 // is null.
371 if ((*it)->GetPeer() != NULL && !(*it)->IsDaemon()) {
Elliott Hughes038a8062011-09-18 14:12:41 -0700372 return false;
373 }
374 }
375 return true;
376}
377
378void ThreadList::WaitForNonDaemonThreadsToExit() {
379 MutexLock mu(thread_list_lock_);
380 while (!AllThreadsAreDaemons()) {
381 thread_exit_cond_.Wait(thread_list_lock_);
382 }
383}
384
385void ThreadList::SuspendAllDaemonThreads() {
386 MutexLock mu(thread_list_lock_);
387
388 // Tell all the daemons it's time to suspend. (At this point, we know
389 // all threads are daemons.)
390 {
391 MutexLock mu(thread_suspend_count_lock_);
392 for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
393 Thread* thread = *it;
394 ++thread->suspend_count_;
395 }
396 }
397
398 // Give the threads a chance to suspend, complaining if they're slow.
399 bool have_complained = false;
400 for (int i = 0; i < 10; ++i) {
401 usleep(200 * 1000);
402 bool all_suspended = true;
403 for (It it = list_.begin(), end = list_.end(); it != end; ++it) {
404 Thread* thread = *it;
405 if (thread->GetState() == Thread::kRunnable) {
406 if (!have_complained) {
407 LOG(WARNING) << "daemon thread not yet suspended: " << *thread;
408 have_complained = true;
409 }
410 all_suspended = false;
411 }
412 }
413 if (all_suspended) {
414 return;
415 }
416 }
417}
418
Elliott Hughes8daa0922011-09-11 13:46:25 -0700419uint32_t ThreadList::AllocThreadId() {
Elliott Hughes8d768a92011-09-14 16:35:25 -0700420 MutexLock mu(thread_list_lock_);
Elliott Hughes8daa0922011-09-11 13:46:25 -0700421 for (size_t i = 0; i < allocated_ids_.size(); ++i) {
422 if (!allocated_ids_[i]) {
423 allocated_ids_.set(i);
424 return i + 1; // Zero is reserved to mean "invalid".
425 }
426 }
427 LOG(FATAL) << "Out of internal thread ids";
428 return 0;
429}
430
431void ThreadList::ReleaseThreadId(uint32_t id) {
Elliott Hughes8d768a92011-09-14 16:35:25 -0700432 thread_list_lock_.AssertHeld();
Elliott Hughes8daa0922011-09-11 13:46:25 -0700433 --id; // Zero is reserved to mean "invalid".
434 DCHECK(allocated_ids_[id]) << id;
435 allocated_ids_.reset(id);
436}
437
438} // namespace art