1 /*
2 * Copyright (C) 2008 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 /*
18 * Thread support.
19 */
20 #include "Dalvik.h"
21 #include "native/SystemThread.h"
22
23 #include "utils/threads.h" // need Android thread priorities
24
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <sys/time.h>
28 #include <sys/resource.h>
29 #include <sys/mman.h>
30 #include <errno.h>
31 #include <fcntl.h>
32
33 #include <cutils/sched_policy.h>
34
35 #if defined(HAVE_PRCTL)
36 #include <sys/prctl.h>
37 #endif
38
39 /* desktop Linux needs a little help with gettid() */
40 #if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
41 #define __KERNEL__
42 # include <linux/unistd.h>
43 #ifdef _syscall0
44 _syscall0(pid_t,gettid)
45 #else
46 pid_t gettid() { return syscall(__NR_gettid);}
47 #endif
48 #undef __KERNEL__
49 #endif
50
51 // Change this to enable logging on cgroup errors
52 #define ENABLE_CGROUP_ERR_LOGGING 0
53
54 // change this to LOGV/LOGD to debug thread activity
55 #define LOG_THREAD LOGVV
56
57 /*
58 Notes on Threading
59
60 All threads are native pthreads. All threads, except the JDWP debugger
61 thread, are visible to code running in the VM and to the debugger. (We
62 don't want the debugger to try to manipulate the thread that listens for
63 instructions from the debugger.) Internal VM threads are in the "system"
64 ThreadGroup, all others are in the "main" ThreadGroup, per convention.
65
66 The GC only runs when all threads have been suspended. Threads are
67 expected to suspend themselves, using a "safe point" mechanism. We check
68 for a suspend request at certain points in the main interpreter loop,
69 and on requests coming in from native code (e.g. all JNI functions).
70 Certain debugger events may inspire threads to self-suspend.
71
72 Native methods must use JNI calls to modify object references to avoid
73 clashes with the GC. JNI doesn't provide a way for native code to access
74 arrays of objects as such -- code must always get/set individual entries --
75 so it should be possible to fully control access through JNI.
76
77 Internal native VM threads, such as the finalizer thread, must explicitly
78 check for suspension periodically. In most cases they will be sound
79 asleep on a condition variable, and won't notice the suspension anyway.
80
81 Threads may be suspended by the GC, debugger, or the SIGQUIT listener
82 thread. The debugger may suspend or resume individual threads, while the
83 GC always suspends all threads. Each thread has a "suspend count" that
84 is incremented on suspend requests and decremented on resume requests.
85 When the count is zero, the thread is runnable. This allows us to fulfill
86 a debugger requirement: if the debugger suspends a thread, the thread is
87 not allowed to run again until the debugger resumes it (or disconnects,
88 in which case we must resume all debugger-suspended threads).
89
90 Paused threads sleep on a condition variable, and are awoken en masse.
91 Certain "slow" VM operations, such as starting up a new thread, will be
92 done in a separate "VMWAIT" state, so that the rest of the VM doesn't
93 freeze up waiting for the operation to finish. Threads must check for
94 pending suspension when leaving VMWAIT.
95
96 Because threads suspend themselves while interpreting code or when native
97 code makes JNI calls, there is no risk of suspending while holding internal
98 VM locks. All threads can enter a suspended (or native-code-only) state.
99 Also, we don't have to worry about object references existing solely
100 in hardware registers.
101
102 We do, however, have to worry about objects that were allocated internally
103 and aren't yet visible to anything else in the VM. If we allocate an
104 object, and then go to sleep on a mutex after changing to a non-RUNNING
105 state (e.g. while trying to allocate a second object), the first object
106 could be garbage-collected out from under us while we sleep. To manage
107 this, we automatically add all allocated objects to an internal object
108 tracking list, and only remove them when we know we won't be suspended
109 before the object appears in the GC root set.
110
111 The debugger may choose to suspend or resume a single thread, which can
112 lead to application-level deadlocks; this is expected behavior. The VM
113 will only check for suspension of single threads when the debugger is
114 active (the java.lang.Thread calls for this are deprecated and hence are
115 not supported). Resumption of a single thread is handled by decrementing
116 the thread's suspend count and sending a broadcast signal to the condition
117 variable. (This will cause all threads to wake up and immediately go back
118 to sleep, which isn't tremendously efficient, but neither is having the
119 debugger attached.)
120
121 The debugger is not allowed to resume threads suspended by the GC. This
122 is trivially enforced by ignoring debugger requests while the GC is running
123 (the JDWP thread is suspended during GC).
124
125 The VM maintains a Thread struct for every pthread known to the VM. There
126 is a java/lang/Thread object associated with every Thread. At present,
127 there is no safe way to go from a Thread object to a Thread struct except by
128 locking and scanning the list; this is necessary because the lifetimes of
129 the two are not closely coupled. We may want to change this behavior,
130 though at present the only performance impact is on the debugger (see
131 threadObjToThread()). See also notes about dvmDetachCurrentThread().
132 */
133 /*
134 Alternate implementation (signal-based):
135
136 Threads run without safe points -- zero overhead. The VM uses a signal
137 (e.g. pthread_kill(SIGUSR1)) to notify threads of suspension or resumption.
138
139 The trouble with using signals to suspend threads is that it means a thread
140 can be in the middle of an operation when garbage collection starts.
141 To prevent some sticky situations, we have to introduce critical sections
142 to the VM code.
143
144 Critical sections temporarily block suspension for a given thread.
145 The thread must move to a non-blocked state (and self-suspend) after
146 finishing its current task. If the thread blocks on a resource held
147 by a suspended thread, we're hosed.
148
149 One approach is to require that no blocking operations, notably
150 acquisition of mutexes, can be performed within a critical section.
151 This is too limiting. For example, if thread A gets suspended while
152 holding the thread list lock, it will prevent the GC or debugger from
153 being able to safely access the thread list. We need to wrap the critical
154 section around the entire operation (enter critical, get lock, do stuff,
155 release lock, exit critical).
156
157 A better approach is to declare that certain resources can only be held
158 within critical sections. A thread that enters a critical section and
159 then gets blocked on the thread list lock knows that the thread it is
160 waiting for is also in a critical section, and will release the lock
161 before suspending itself. Eventually all threads will complete their
162 operations and self-suspend. For this to work, the VM must:
163
164 (1) Determine the set of resources that may be accessed from the GC or
165 debugger threads. The mutexes guarding those go into the "critical
166 resource set" (CRS).
167 (2) Ensure that no resource in the CRS can be acquired outside of a
168 critical section. This can be verified with an assert().
169 (3) Ensure that only resources in the CRS can be held while in a critical
170 section. This is harder to enforce.
171
172 If any of these conditions are not met, deadlock can ensue when grabbing
173 resources in the GC or debugger (#1) or waiting for threads to suspend
174 (#2,#3). (You won't actually deadlock in the GC, because if the semantics
175 above are followed you don't need to lock anything in the GC. The risk is
176 rather that the GC will access data structures in an intermediate state.)
177
178 This approach requires more care and awareness in the VM than
179 safe-pointing. Because the GC and debugger are fairly intrusive, there
180 really aren't any internal VM resources that aren't shared. Thus, the
181 enter/exit critical calls can be added to internal mutex wrappers, which
182 makes it easy to get #1 and #2 right.
183
184 An ordering should be established for all locks to avoid deadlocks.
185
186 Monitor locks, which are also implemented with pthread calls, should not
187 cause any problems here. Threads fighting over such locks will not be in
188 critical sections and can be suspended freely.
189
190 This can get tricky if we ever need exclusive access to VM and non-VM
191 resources at the same time. It's not clear if this is a real concern.
192
193 There are (at least) two ways to handle the incoming signals:
194
195 (a) Always accept signals. If we're in a critical section, the signal
196 handler just returns without doing anything (the "suspend level"
197 should have been incremented before the signal was sent). Otherwise,
198 if the "suspend level" is nonzero, we go to sleep.
199 (b) Block signals in critical sections. This ensures that we can't be
200 interrupted in a critical section, but requires pthread_sigmask()
201 calls on entry and exit.
202
203 This is a choice between blocking the message and blocking the messenger.
204 Because UNIX signals are unreliable (you can only know that you have been
205 signaled, not whether you were signaled once or 10 times), the choice is
206 not significant for correctness. The choice depends on the efficiency
207 of pthread_sigmask() and the desire to actually block signals. Either way,
208 it is best to ensure that there is only one indication of "blocked";
209 having two (i.e. block signals and set a flag, then only send a signal
210 if the flag isn't set) can lead to race conditions.
211
212 The signal handler must take care to copy registers onto the stack (via
213 setjmp), so that stack scans find all references. Because we have to scan
214 native stacks, "exact" GC is not possible with this approach.
215
216 Some other concerns with flinging signals around:
217 - Odd interactions with some debuggers (e.g. gdb on the Mac)
218 - Restrictions on some standard library calls during GC (e.g. don't
219 use printf on stdout to print GC debug messages)
220 */
221
222 #define kMaxThreadId ((1<<15) - 1)
223 #define kMainThreadId ((1<<1) | 1)
224
225
226 static Thread* allocThread(int interpStackSize);
227 static bool prepareThread(Thread* thread);
228 static void setThreadSelf(Thread* thread);
229 static void unlinkThread(Thread* thread);
230 static void freeThread(Thread* thread);
231 static void assignThreadId(Thread* thread);
232 static bool createFakeEntryFrame(Thread* thread);
233 static bool createFakeRunFrame(Thread* thread);
234 static void* interpThreadStart(void* arg);
235 static void* internalThreadStart(void* arg);
236 static void threadExitUncaughtException(Thread* thread, Object* group);
237 static void threadExitCheck(void* arg);
238 static void waitForThreadSuspend(Thread* self, Thread* thread);
239 static int getThreadPriorityFromSystem(void);
240
241 /*
242 * The JIT needs to know if any thread is suspended. We do this by
243 * maintaining a global sum of all threads' suspend counts. All suspendCount
244 * updates should go through this after aquiring threadSuspendCountLock.
245 */
dvmAddToThreadSuspendCount(int * pSuspendCount,int delta)246 static inline void dvmAddToThreadSuspendCount(int *pSuspendCount, int delta)
247 {
248 *pSuspendCount += delta;
249 gDvm.sumThreadSuspendCount += delta;
250 }
251
252 /*
253 * Initialize thread list and main thread's environment. We need to set
254 * up some basic stuff so that dvmThreadSelf() will work when we start
255 * loading classes (e.g. to check for exceptions).
256 */
dvmThreadStartup(void)257 bool dvmThreadStartup(void)
258 {
259 Thread* thread;
260
261 /* allocate a TLS slot */
262 if (pthread_key_create(&gDvm.pthreadKeySelf, threadExitCheck) != 0) {
263 LOGE("ERROR: pthread_key_create failed\n");
264 return false;
265 }
266
267 /* test our pthread lib */
268 if (pthread_getspecific(gDvm.pthreadKeySelf) != NULL)
269 LOGW("WARNING: newly-created pthread TLS slot is not NULL\n");
270
271 /* prep thread-related locks and conditions */
272 dvmInitMutex(&gDvm.threadListLock);
273 pthread_cond_init(&gDvm.threadStartCond, NULL);
274 //dvmInitMutex(&gDvm.vmExitLock);
275 pthread_cond_init(&gDvm.vmExitCond, NULL);
276 dvmInitMutex(&gDvm._threadSuspendLock);
277 dvmInitMutex(&gDvm.threadSuspendCountLock);
278 pthread_cond_init(&gDvm.threadSuspendCountCond, NULL);
279 #ifdef WITH_DEADLOCK_PREDICTION
280 dvmInitMutex(&gDvm.deadlockHistoryLock);
281 #endif
282
283 /*
284 * Dedicated monitor for Thread.sleep().
285 * TODO: change this to an Object* so we don't have to expose this
286 * call, and we interact better with JDWP monitor calls. Requires
287 * deferring the object creation to much later (e.g. final "main"
288 * thread prep) or until first use.
289 */
290 gDvm.threadSleepMon = dvmCreateMonitor(NULL);
291
292 gDvm.threadIdMap = dvmAllocBitVector(kMaxThreadId, false);
293
294 thread = allocThread(gDvm.stackSize);
295 if (thread == NULL)
296 return false;
297
298 /* switch mode for when we run initializers */
299 thread->status = THREAD_RUNNING;
300
301 /*
302 * We need to assign the threadId early so we can lock/notify
303 * object monitors. We'll set the "threadObj" field later.
304 */
305 prepareThread(thread);
306 gDvm.threadList = thread;
307
308 #ifdef COUNT_PRECISE_METHODS
309 gDvm.preciseMethods = dvmPointerSetAlloc(200);
310 #endif
311
312 return true;
313 }
314
315 /*
316 * We're a little farther up now, and can load some basic classes.
317 *
318 * We're far enough along that we can poke at java.lang.Thread and friends,
319 * but should not assume that static initializers have run (or cause them
320 * to do so). That means no object allocations yet.
321 */
dvmThreadObjStartup(void)322 bool dvmThreadObjStartup(void)
323 {
324 /*
325 * Cache the locations of these classes. It's likely that we're the
326 * first to reference them, so they're being loaded now.
327 */
328 gDvm.classJavaLangThread =
329 dvmFindSystemClassNoInit("Ljava/lang/Thread;");
330 gDvm.classJavaLangVMThread =
331 dvmFindSystemClassNoInit("Ljava/lang/VMThread;");
332 gDvm.classJavaLangThreadGroup =
333 dvmFindSystemClassNoInit("Ljava/lang/ThreadGroup;");
334 if (gDvm.classJavaLangThread == NULL ||
335 gDvm.classJavaLangThreadGroup == NULL ||
336 gDvm.classJavaLangThreadGroup == NULL)
337 {
338 LOGE("Could not find one or more essential thread classes\n");
339 return false;
340 }
341
342 /*
343 * Cache field offsets. This makes things a little faster, at the
344 * expense of hard-coding non-public field names into the VM.
345 */
346 gDvm.offJavaLangThread_vmThread =
347 dvmFindFieldOffset(gDvm.classJavaLangThread,
348 "vmThread", "Ljava/lang/VMThread;");
349 gDvm.offJavaLangThread_group =
350 dvmFindFieldOffset(gDvm.classJavaLangThread,
351 "group", "Ljava/lang/ThreadGroup;");
352 gDvm.offJavaLangThread_daemon =
353 dvmFindFieldOffset(gDvm.classJavaLangThread, "daemon", "Z");
354 gDvm.offJavaLangThread_name =
355 dvmFindFieldOffset(gDvm.classJavaLangThread,
356 "name", "Ljava/lang/String;");
357 gDvm.offJavaLangThread_priority =
358 dvmFindFieldOffset(gDvm.classJavaLangThread, "priority", "I");
359
360 if (gDvm.offJavaLangThread_vmThread < 0 ||
361 gDvm.offJavaLangThread_group < 0 ||
362 gDvm.offJavaLangThread_daemon < 0 ||
363 gDvm.offJavaLangThread_name < 0 ||
364 gDvm.offJavaLangThread_priority < 0)
365 {
366 LOGE("Unable to find all fields in java.lang.Thread\n");
367 return false;
368 }
369
370 gDvm.offJavaLangVMThread_thread =
371 dvmFindFieldOffset(gDvm.classJavaLangVMThread,
372 "thread", "Ljava/lang/Thread;");
373 gDvm.offJavaLangVMThread_vmData =
374 dvmFindFieldOffset(gDvm.classJavaLangVMThread, "vmData", "I");
375 if (gDvm.offJavaLangVMThread_thread < 0 ||
376 gDvm.offJavaLangVMThread_vmData < 0)
377 {
378 LOGE("Unable to find all fields in java.lang.VMThread\n");
379 return false;
380 }
381
382 /*
383 * Cache the vtable offset for "run()".
384 *
385 * We don't want to keep the Method* because then we won't find see
386 * methods defined in subclasses.
387 */
388 Method* meth;
389 meth = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangThread, "run", "()V");
390 if (meth == NULL) {
391 LOGE("Unable to find run() in java.lang.Thread\n");
392 return false;
393 }
394 gDvm.voffJavaLangThread_run = meth->methodIndex;
395
396 /*
397 * Cache vtable offsets for ThreadGroup methods.
398 */
399 meth = dvmFindVirtualMethodByDescriptor(gDvm.classJavaLangThreadGroup,
400 "removeThread", "(Ljava/lang/Thread;)V");
401 if (meth == NULL) {
402 LOGE("Unable to find removeThread(Thread) in java.lang.ThreadGroup\n");
403 return false;
404 }
405 gDvm.voffJavaLangThreadGroup_removeThread = meth->methodIndex;
406
407 return true;
408 }
409
410 /*
411 * All threads should be stopped by now. Clean up some thread globals.
412 */
dvmThreadShutdown(void)413 void dvmThreadShutdown(void)
414 {
415 if (gDvm.threadList != NULL) {
416 /*
417 * If we walk through the thread list and try to free the
418 * lingering thread structures (which should only be for daemon
419 * threads), the daemon threads may crash if they execute before
420 * the process dies. Let them leak.
421 */
422 freeThread(gDvm.threadList);
423 gDvm.threadList = NULL;
424 }
425
426 dvmFreeBitVector(gDvm.threadIdMap);
427
428 dvmFreeMonitorList();
429
430 pthread_key_delete(gDvm.pthreadKeySelf);
431 }
432
433
434 /*
435 * Grab the suspend count global lock.
436 */
lockThreadSuspendCount(void)437 static inline void lockThreadSuspendCount(void)
438 {
439 /*
440 * Don't try to change to VMWAIT here. When we change back to RUNNING
441 * we have to check for a pending suspend, which results in grabbing
442 * this lock recursively. Doesn't work with "fast" pthread mutexes.
443 *
444 * This lock is always held for very brief periods, so as long as
445 * mutex ordering is respected we shouldn't stall.
446 */
447 int cc = pthread_mutex_lock(&gDvm.threadSuspendCountLock);
448 assert(cc == 0);
449 }
450
451 /*
452 * Release the suspend count global lock.
453 */
unlockThreadSuspendCount(void)454 static inline void unlockThreadSuspendCount(void)
455 {
456 dvmUnlockMutex(&gDvm.threadSuspendCountLock);
457 }
458
459 /*
460 * Grab the thread list global lock.
461 *
462 * This is held while "suspend all" is trying to make everybody stop. If
463 * the shutdown is in progress, and somebody tries to grab the lock, they'll
464 * have to wait for the GC to finish. Therefore it's important that the
465 * thread not be in RUNNING mode.
466 *
467 * We don't have to check to see if we should be suspended once we have
468 * the lock. Nobody can suspend all threads without holding the thread list
469 * lock while they do it, so by definition there isn't a GC in progress.
470 *
471 * TODO: consider checking for suspend after acquiring the lock, and
472 * backing off if set. As stated above, it can't happen during normal
473 * execution, but it *can* happen during shutdown when daemon threads
474 * are being suspended.
475 */
dvmLockThreadList(Thread * self)476 void dvmLockThreadList(Thread* self)
477 {
478 ThreadStatus oldStatus;
479
480 if (self == NULL) /* try to get it from TLS */
481 self = dvmThreadSelf();
482
483 if (self != NULL) {
484 oldStatus = self->status;
485 self->status = THREAD_VMWAIT;
486 } else {
487 /* happens during VM shutdown */
488 //LOGW("NULL self in dvmLockThreadList\n");
489 oldStatus = -1; // shut up gcc
490 }
491
492 int cc = pthread_mutex_lock(&gDvm.threadListLock);
493 assert(cc == 0);
494
495 if (self != NULL)
496 self->status = oldStatus;
497 }
498
499 /*
500 * Release the thread list global lock.
501 */
dvmUnlockThreadList(void)502 void dvmUnlockThreadList(void)
503 {
504 int cc = pthread_mutex_unlock(&gDvm.threadListLock);
505 assert(cc == 0);
506 }
507
508 /*
509 * Convert SuspendCause to a string.
510 */
getSuspendCauseStr(SuspendCause why)511 static const char* getSuspendCauseStr(SuspendCause why)
512 {
513 switch (why) {
514 case SUSPEND_NOT: return "NOT?";
515 case SUSPEND_FOR_GC: return "gc";
516 case SUSPEND_FOR_DEBUG: return "debug";
517 case SUSPEND_FOR_DEBUG_EVENT: return "debug-event";
518 case SUSPEND_FOR_STACK_DUMP: return "stack-dump";
519 default: return "UNKNOWN";
520 }
521 }
522
523 /*
524 * Grab the "thread suspend" lock. This is required to prevent the
525 * GC and the debugger from simultaneously suspending all threads.
526 *
527 * If we fail to get the lock, somebody else is trying to suspend all
528 * threads -- including us. If we go to sleep on the lock we'll deadlock
529 * the VM. Loop until we get it or somebody puts us to sleep.
530 */
lockThreadSuspend(const char * who,SuspendCause why)531 static void lockThreadSuspend(const char* who, SuspendCause why)
532 {
533 const int kSpinSleepTime = 3*1000*1000; /* 3s */
534 u8 startWhen = 0; // init req'd to placate gcc
535 int sleepIter = 0;
536 int cc;
537
538 do {
539 cc = pthread_mutex_trylock(&gDvm._threadSuspendLock);
540 if (cc != 0) {
541 if (!dvmCheckSuspendPending(NULL)) {
542 /*
543 * Could be that a resume-all is in progress, and something
544 * grabbed the CPU when the wakeup was broadcast. The thread
545 * performing the resume hasn't had a chance to release the
546 * thread suspend lock. (We release before the broadcast,
547 * so this should be a narrow window.)
548 *
549 * Could be we hit the window as a suspend was started,
550 * and the lock has been grabbed but the suspend counts
551 * haven't been incremented yet.
552 *
553 * Could be an unusual JNI thread-attach thing.
554 *
555 * Could be the debugger telling us to resume at roughly
556 * the same time we're posting an event.
557 */
558 LOGI("threadid=%d ODD: want thread-suspend lock (%s:%s),"
559 " it's held, no suspend pending\n",
560 dvmThreadSelf()->threadId, who, getSuspendCauseStr(why));
561 } else {
562 /* we suspended; reset timeout */
563 sleepIter = 0;
564 }
565
566 /* give the lock-holder a chance to do some work */
567 if (sleepIter == 0)
568 startWhen = dvmGetRelativeTimeUsec();
569 if (!dvmIterativeSleep(sleepIter++, kSpinSleepTime, startWhen)) {
570 LOGE("threadid=%d: couldn't get thread-suspend lock (%s:%s),"
571 " bailing\n",
572 dvmThreadSelf()->threadId, who, getSuspendCauseStr(why));
573 /* threads are not suspended, thread dump could crash */
574 dvmDumpAllThreads(false);
575 dvmAbort();
576 }
577 }
578 } while (cc != 0);
579 assert(cc == 0);
580 }
581
582 /*
583 * Release the "thread suspend" lock.
584 */
unlockThreadSuspend(void)585 static inline void unlockThreadSuspend(void)
586 {
587 int cc = pthread_mutex_unlock(&gDvm._threadSuspendLock);
588 assert(cc == 0);
589 }
590
591
592 /*
593 * Kill any daemon threads that still exist. All of ours should be
594 * stopped, so these should be Thread objects or JNI-attached threads
595 * started by the application. Actively-running threads are likely
596 * to crash the process if they continue to execute while the VM
597 * shuts down, so we really need to kill or suspend them. (If we want
598 * the VM to restart within this process, we need to kill them, but that
599 * leaves open the possibility of orphaned resources.)
600 *
601 * Waiting for the thread to suspend may be unwise at this point, but
602 * if one of these is wedged in a critical section then we probably
603 * would've locked up on the last GC attempt.
604 *
605 * It's possible for this function to get called after a failed
606 * initialization, so be careful with assumptions about the environment.
607 *
608 * This will be called from whatever thread calls DestroyJavaVM, usually
609 * but not necessarily the main thread. It's likely, but not guaranteed,
610 * that the current thread has already been cleaned up.
611 */
dvmSlayDaemons(void)612 void dvmSlayDaemons(void)
613 {
614 Thread* self = dvmThreadSelf(); // may be null
615 Thread* target;
616 int threadId = 0;
617 bool doWait = false;
618
619 //dvmEnterCritical(self);
620 dvmLockThreadList(self);
621
622 if (self != NULL)
623 threadId = self->threadId;
624
625 target = gDvm.threadList;
626 while (target != NULL) {
627 if (target == self) {
628 target = target->next;
629 continue;
630 }
631
632 if (!dvmGetFieldBoolean(target->threadObj,
633 gDvm.offJavaLangThread_daemon))
634 {
635 /* should never happen; suspend it with the rest */
636 LOGW("threadid=%d: non-daemon id=%d still running at shutdown?!\n",
637 threadId, target->threadId);
638 }
639
640 char* threadName = dvmGetThreadName(target);
641 LOGD("threadid=%d: suspending daemon id=%d name='%s'\n",
642 threadId, target->threadId, threadName);
643 free(threadName);
644
645 /* mark as suspended */
646 lockThreadSuspendCount();
647 dvmAddToThreadSuspendCount(&target->suspendCount, 1);
648 unlockThreadSuspendCount();
649 doWait = true;
650
651 target = target->next;
652 }
653
654 //dvmDumpAllThreads(false);
655
656 /*
657 * Unlock the thread list, relocking it later if necessary. It's
658 * possible a thread is in VMWAIT after calling dvmLockThreadList,
659 * and that function *doesn't* check for pending suspend after
660 * acquiring the lock. We want to let them finish their business
661 * and see the pending suspend before we continue here.
662 *
663 * There's no guarantee of mutex fairness, so this might not work.
664 * (The alternative is to have dvmLockThreadList check for suspend
665 * after acquiring the lock and back off, something we should consider.)
666 */
667 dvmUnlockThreadList();
668
669 if (doWait) {
670 usleep(200 * 1000);
671
672 dvmLockThreadList(self);
673
674 /*
675 * Sleep for a bit until the threads have suspended. We're trying
676 * to exit, so don't wait for too long.
677 */
678 int i;
679 for (i = 0; i < 10; i++) {
680 bool allSuspended = true;
681
682 target = gDvm.threadList;
683 while (target != NULL) {
684 if (target == self) {
685 target = target->next;
686 continue;
687 }
688
689 if (target->status == THREAD_RUNNING && !target->isSuspended) {
690 LOGD("threadid=%d not ready yet\n", target->threadId);
691 allSuspended = false;
692 break;
693 }
694
695 target = target->next;
696 }
697
698 if (allSuspended) {
699 LOGD("threadid=%d: all daemons have suspended\n", threadId);
700 break;
701 } else {
702 LOGD("threadid=%d: waiting for daemons to suspend\n", threadId);
703 }
704
705 usleep(200 * 1000);
706 }
707 dvmUnlockThreadList();
708 }
709
710 #if 0 /* bad things happen if they come out of JNI or "spuriously" wake up */
711 /*
712 * Abandon the threads and recover their resources.
713 */
714 target = gDvm.threadList;
715 while (target != NULL) {
716 Thread* nextTarget = target->next;
717 unlinkThread(target);
718 freeThread(target);
719 target = nextTarget;
720 }
721 #endif
722
723 //dvmDumpAllThreads(true);
724 }
725
726
727 /*
728 * Finish preparing the parts of the Thread struct required to support
729 * JNI registration.
730 */
dvmPrepMainForJni(JNIEnv * pEnv)731 bool dvmPrepMainForJni(JNIEnv* pEnv)
732 {
733 Thread* self;
734
735 /* main thread is always first in list at this point */
736 self = gDvm.threadList;
737 assert(self->threadId == kMainThreadId);
738
739 /* create a "fake" JNI frame at the top of the main thread interp stack */
740 if (!createFakeEntryFrame(self))
741 return false;
742
743 /* fill these in, since they weren't ready at dvmCreateJNIEnv time */
744 dvmSetJniEnvThreadId(pEnv, self);
745 dvmSetThreadJNIEnv(self, (JNIEnv*) pEnv);
746
747 return true;
748 }
749
750
751 /*
752 * Finish preparing the main thread, allocating some objects to represent
753 * it. As part of doing so, we finish initializing Thread and ThreadGroup.
754 * This will execute some interpreted code (e.g. class initializers).
755 */
dvmPrepMainThread(void)756 bool dvmPrepMainThread(void)
757 {
758 Thread* thread;
759 Object* groupObj;
760 Object* threadObj;
761 Object* vmThreadObj;
762 StringObject* threadNameStr;
763 Method* init;
764 JValue unused;
765
766 LOGV("+++ finishing prep on main VM thread\n");
767
768 /* main thread is always first in list at this point */
769 thread = gDvm.threadList;
770 assert(thread->threadId == kMainThreadId);
771
772 /*
773 * Make sure the classes are initialized. We have to do this before
774 * we create an instance of them.
775 */
776 if (!dvmInitClass(gDvm.classJavaLangClass)) {
777 LOGE("'Class' class failed to initialize\n");
778 return false;
779 }
780 if (!dvmInitClass(gDvm.classJavaLangThreadGroup) ||
781 !dvmInitClass(gDvm.classJavaLangThread) ||
782 !dvmInitClass(gDvm.classJavaLangVMThread))
783 {
784 LOGE("thread classes failed to initialize\n");
785 return false;
786 }
787
788 groupObj = dvmGetMainThreadGroup();
789 if (groupObj == NULL)
790 return false;
791
792 /*
793 * Allocate and construct a Thread with the internal-creation
794 * constructor.
795 */
796 threadObj = dvmAllocObject(gDvm.classJavaLangThread, ALLOC_DEFAULT);
797 if (threadObj == NULL) {
798 LOGE("unable to allocate main thread object\n");
799 return false;
800 }
801 dvmReleaseTrackedAlloc(threadObj, NULL);
802
803 threadNameStr = dvmCreateStringFromCstr("main", ALLOC_DEFAULT);
804 if (threadNameStr == NULL)
805 return false;
806 dvmReleaseTrackedAlloc((Object*)threadNameStr, NULL);
807
808 init = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangThread, "<init>",
809 "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
810 assert(init != NULL);
811 dvmCallMethod(thread, init, threadObj, &unused, groupObj, threadNameStr,
812 THREAD_NORM_PRIORITY, false);
813 if (dvmCheckException(thread)) {
814 LOGE("exception thrown while constructing main thread object\n");
815 return false;
816 }
817
818 /*
819 * Allocate and construct a VMThread.
820 */
821 vmThreadObj = dvmAllocObject(gDvm.classJavaLangVMThread, ALLOC_DEFAULT);
822 if (vmThreadObj == NULL) {
823 LOGE("unable to allocate main vmthread object\n");
824 return false;
825 }
826 dvmReleaseTrackedAlloc(vmThreadObj, NULL);
827
828 init = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangVMThread, "<init>",
829 "(Ljava/lang/Thread;)V");
830 dvmCallMethod(thread, init, vmThreadObj, &unused, threadObj);
831 if (dvmCheckException(thread)) {
832 LOGE("exception thrown while constructing main vmthread object\n");
833 return false;
834 }
835
836 /* set the VMThread.vmData field to our Thread struct */
837 assert(gDvm.offJavaLangVMThread_vmData != 0);
838 dvmSetFieldInt(vmThreadObj, gDvm.offJavaLangVMThread_vmData, (u4)thread);
839
840 /*
841 * Stuff the VMThread back into the Thread. From this point on, other
842 * Threads will see that this Thread is running (at least, they would,
843 * if there were any).
844 */
845 dvmSetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread,
846 vmThreadObj);
847
848 thread->threadObj = threadObj;
849
850 /*
851 * Set the context class loader. This invokes a ClassLoader method,
852 * which could conceivably call Thread.currentThread(), so we want the
853 * Thread to be fully configured before we do this.
854 */
855 Object* systemLoader = dvmGetSystemClassLoader();
856 if (systemLoader == NULL) {
857 LOGW("WARNING: system class loader is NULL (setting main ctxt)\n");
858 /* keep going */
859 }
860 int ctxtClassLoaderOffset = dvmFindFieldOffset(gDvm.classJavaLangThread,
861 "contextClassLoader", "Ljava/lang/ClassLoader;");
862 if (ctxtClassLoaderOffset < 0) {
863 LOGE("Unable to find contextClassLoader field in Thread\n");
864 return false;
865 }
866 dvmSetFieldObject(threadObj, ctxtClassLoaderOffset, systemLoader);
867
868 /*
869 * Finish our thread prep.
870 */
871
872 /* include self in non-daemon threads (mainly for AttachCurrentThread) */
873 gDvm.nonDaemonThreadCount++;
874
875 return true;
876 }
877
878
879 /*
880 * Alloc and initialize a Thread struct.
881 *
882 * "threadObj" is the java.lang.Thread object. It will be NULL for the
883 * main VM thread, but non-NULL for everything else.
884 *
885 * Does not create any objects, just stuff on the system (malloc) heap. (If
886 * this changes, we need to use ALLOC_NO_GC. And also verify that we're
887 * ready to load classes at the time this is called.)
888 */
allocThread(int interpStackSize)889 static Thread* allocThread(int interpStackSize)
890 {
891 Thread* thread;
892 u1* stackBottom;
893
894 thread = (Thread*) calloc(1, sizeof(Thread));
895 if (thread == NULL)
896 return NULL;
897
898 assert(interpStackSize >= kMinStackSize && interpStackSize <=kMaxStackSize);
899
900 thread->status = THREAD_INITIALIZING;
901 thread->suspendCount = 0;
902
903 #ifdef WITH_ALLOC_LIMITS
904 thread->allocLimit = -1;
905 #endif
906
907 /*
908 * Allocate and initialize the interpreted code stack. We essentially
909 * "lose" the alloc pointer, which points at the bottom of the stack,
910 * but we can get it back later because we know how big the stack is.
911 *
912 * The stack must be aligned on a 4-byte boundary.
913 */
914 #ifdef MALLOC_INTERP_STACK
915 stackBottom = (u1*) malloc(interpStackSize);
916 if (stackBottom == NULL) {
917 free(thread);
918 return NULL;
919 }
920 memset(stackBottom, 0xc5, interpStackSize); // stop valgrind complaints
921 #else
922 stackBottom = mmap(NULL, interpStackSize, PROT_READ | PROT_WRITE,
923 MAP_PRIVATE | MAP_ANON, -1, 0);
924 if (stackBottom == MAP_FAILED) {
925 free(thread);
926 return NULL;
927 }
928 #endif
929
930 assert(((u4)stackBottom & 0x03) == 0); // looks like our malloc ensures this
931 thread->interpStackSize = interpStackSize;
932 thread->interpStackStart = stackBottom + interpStackSize;
933 thread->interpStackEnd = stackBottom + STACK_OVERFLOW_RESERVE;
934
935 /* give the thread code a chance to set things up */
936 dvmInitInterpStack(thread, interpStackSize);
937
938 return thread;
939 }
940
941 /*
942 * Get a meaningful thread ID. At present this only has meaning under Linux,
943 * where getpid() and gettid() sometimes agree and sometimes don't depending
944 * on your thread model (try "export LD_ASSUME_KERNEL=2.4.19").
945 */
dvmGetSysThreadId(void)946 pid_t dvmGetSysThreadId(void)
947 {
948 #ifdef HAVE_GETTID
949 return gettid();
950 #else
951 return getpid();
952 #endif
953 }
954
955 /*
956 * Finish initialization of a Thread struct.
957 *
958 * This must be called while executing in the new thread, but before the
959 * thread is added to the thread list.
960 *
961 * *** NOTE: The threadListLock must be held by the caller (needed for
962 * assignThreadId()).
963 */
prepareThread(Thread * thread)964 static bool prepareThread(Thread* thread)
965 {
966 assignThreadId(thread);
967 thread->handle = pthread_self();
968 thread->systemTid = dvmGetSysThreadId();
969
970 //LOGI("SYSTEM TID IS %d (pid is %d)\n", (int) thread->systemTid,
971 // (int) getpid());
972 setThreadSelf(thread);
973
974 LOGV("threadid=%d: interp stack at %p\n",
975 thread->threadId, thread->interpStackStart - thread->interpStackSize);
976
977 /*
978 * Initialize invokeReq.
979 */
980 pthread_mutex_init(&thread->invokeReq.lock, NULL);
981 pthread_cond_init(&thread->invokeReq.cv, NULL);
982
983 /*
984 * Initialize our reference tracking tables.
985 *
986 * Most threads won't use jniMonitorRefTable, so we clear out the
987 * structure but don't call the init function (which allocs storage).
988 */
989 #ifdef USE_INDIRECT_REF
990 if (!dvmInitIndirectRefTable(&thread->jniLocalRefTable,
991 kJniLocalRefMin, kJniLocalRefMax, kIndirectKindLocal))
992 return false;
993 #else
994 /*
995 * The JNI local ref table *must* be fixed-size because we keep pointers
996 * into the table in our stack frames.
997 */
998 if (!dvmInitReferenceTable(&thread->jniLocalRefTable,
999 kJniLocalRefMax, kJniLocalRefMax))
1000 return false;
1001 #endif
1002 if (!dvmInitReferenceTable(&thread->internalLocalRefTable,
1003 kInternalRefDefault, kInternalRefMax))
1004 return false;
1005
1006 memset(&thread->jniMonitorRefTable, 0, sizeof(thread->jniMonitorRefTable));
1007
1008 return true;
1009 }
1010
1011 /*
1012 * Remove a thread from the internal list.
1013 * Clear out the links to make it obvious that the thread is
1014 * no longer on the list. Caller must hold gDvm.threadListLock.
1015 */
unlinkThread(Thread * thread)1016 static void unlinkThread(Thread* thread)
1017 {
1018 LOG_THREAD("threadid=%d: removing from list\n", thread->threadId);
1019 if (thread == gDvm.threadList) {
1020 assert(thread->prev == NULL);
1021 gDvm.threadList = thread->next;
1022 } else {
1023 assert(thread->prev != NULL);
1024 thread->prev->next = thread->next;
1025 }
1026 if (thread->next != NULL)
1027 thread->next->prev = thread->prev;
1028 thread->prev = thread->next = NULL;
1029 }
1030
1031 /*
1032 * Free a Thread struct, and all the stuff allocated within.
1033 */
freeThread(Thread * thread)1034 static void freeThread(Thread* thread)
1035 {
1036 if (thread == NULL)
1037 return;
1038
1039 /* thread->threadId is zero at this point */
1040 LOGVV("threadid=%d: freeing\n", thread->threadId);
1041
1042 if (thread->interpStackStart != NULL) {
1043 u1* interpStackBottom;
1044
1045 interpStackBottom = thread->interpStackStart;
1046 interpStackBottom -= thread->interpStackSize;
1047 #ifdef MALLOC_INTERP_STACK
1048 free(interpStackBottom);
1049 #else
1050 if (munmap(interpStackBottom, thread->interpStackSize) != 0)
1051 LOGW("munmap(thread stack) failed\n");
1052 #endif
1053 }
1054
1055 #ifdef USE_INDIRECT_REF
1056 dvmClearIndirectRefTable(&thread->jniLocalRefTable);
1057 #else
1058 dvmClearReferenceTable(&thread->jniLocalRefTable);
1059 #endif
1060 dvmClearReferenceTable(&thread->internalLocalRefTable);
1061 if (&thread->jniMonitorRefTable.table != NULL)
1062 dvmClearReferenceTable(&thread->jniMonitorRefTable);
1063
1064 free(thread);
1065 }
1066
1067 /*
1068 * Like pthread_self(), but on a Thread*.
1069 */
dvmThreadSelf(void)1070 Thread* dvmThreadSelf(void)
1071 {
1072 return (Thread*) pthread_getspecific(gDvm.pthreadKeySelf);
1073 }
1074
1075 /*
1076 * Explore our sense of self. Stuffs the thread pointer into TLS.
1077 */
setThreadSelf(Thread * thread)1078 static void setThreadSelf(Thread* thread)
1079 {
1080 int cc;
1081
1082 cc = pthread_setspecific(gDvm.pthreadKeySelf, thread);
1083 if (cc != 0) {
1084 /*
1085 * Sometimes this fails under Bionic with EINVAL during shutdown.
1086 * This can happen if the timing is just right, e.g. a thread
1087 * fails to attach during shutdown, but the "fail" path calls
1088 * here to ensure we clean up after ourselves.
1089 */
1090 if (thread != NULL) {
1091 LOGE("pthread_setspecific(%p) failed, err=%d\n", thread, cc);
1092 dvmAbort(); /* the world is fundamentally hosed */
1093 }
1094 }
1095 }
1096
1097 /*
1098 * This is associated with the pthreadKeySelf key. It's called by the
1099 * pthread library when a thread is exiting and the "self" pointer in TLS
1100 * is non-NULL, meaning the VM hasn't had a chance to clean up. In normal
1101 * operation this should never be called.
1102 *
1103 * This is mainly of use to ensure that we don't leak resources if, for
1104 * example, a thread attaches itself to us with AttachCurrentThread and
1105 * then exits without notifying the VM.
1106 *
1107 * We could do the detach here instead of aborting, but this will lead to
1108 * portability problems. Other implementations do not do this check and
1109 * will simply be unaware that the thread has exited, leading to resource
1110 * leaks (and, if this is a non-daemon thread, an infinite hang when the
1111 * VM tries to shut down).
1112 */
threadExitCheck(void * arg)1113 static void threadExitCheck(void* arg)
1114 {
1115 Thread* thread = (Thread*) arg;
1116
1117 LOGI("In threadExitCheck %p\n", arg);
1118 assert(thread != NULL);
1119
1120 if (thread->status != THREAD_ZOMBIE) {
1121 LOGE("Native thread exited without telling us\n");
1122 dvmAbort();
1123 }
1124 }
1125
1126
1127 /*
1128 * Assign the threadId. This needs to be a small integer so that our
1129 * "thin" locks fit in a small number of bits.
1130 *
1131 * We reserve zero for use as an invalid ID.
1132 *
1133 * This must be called with threadListLock held (unless we're still
1134 * initializing the system).
1135 */
assignThreadId(Thread * thread)1136 static void assignThreadId(Thread* thread)
1137 {
1138 /* Find a small unique integer. threadIdMap is a vector of
1139 * kMaxThreadId bits; dvmAllocBit() returns the index of a
1140 * bit, meaning that it will always be < kMaxThreadId.
1141 *
1142 * The thin locking magic requires that the low bit is always
1143 * set, so we do it once, here.
1144 */
1145 int num = dvmAllocBit(gDvm.threadIdMap);
1146 if (num < 0) {
1147 LOGE("Ran out of thread IDs\n");
1148 dvmAbort(); // TODO: make this a non-fatal error result
1149 }
1150
1151 thread->threadId = ((num + 1) << 1) | 1;
1152
1153 assert(thread->threadId != 0);
1154 assert(thread->threadId != DVM_LOCK_INITIAL_THIN_VALUE);
1155 }
1156
1157 /*
1158 * Give back the thread ID.
1159 */
releaseThreadId(Thread * thread)1160 static void releaseThreadId(Thread* thread)
1161 {
1162 assert(thread->threadId > 0);
1163 dvmClearBit(gDvm.threadIdMap, (thread->threadId >> 1) - 1);
1164 thread->threadId = 0;
1165 }
1166
1167
1168 /*
1169 * Add a stack frame that makes it look like the native code in the main
1170 * thread was originally invoked from interpreted code. This gives us a
1171 * place to hang JNI local references. The VM spec says (v2 5.2) that the
1172 * VM begins by executing "main" in a class, so in a way this brings us
1173 * closer to the spec.
1174 */
createFakeEntryFrame(Thread * thread)1175 static bool createFakeEntryFrame(Thread* thread)
1176 {
1177 assert(thread->threadId == kMainThreadId); // main thread only
1178
1179 /* find the method on first use */
1180 if (gDvm.methFakeNativeEntry == NULL) {
1181 ClassObject* nativeStart;
1182 Method* mainMeth;
1183
1184 nativeStart = dvmFindSystemClassNoInit(
1185 "Ldalvik/system/NativeStart;");
1186 if (nativeStart == NULL) {
1187 LOGE("Unable to find dalvik.system.NativeStart class\n");
1188 return false;
1189 }
1190
1191 /*
1192 * Because we are creating a frame that represents application code, we
1193 * want to stuff the application class loader into the method's class
1194 * loader field, even though we're using the system class loader to
1195 * load it. This makes life easier over in JNI FindClass (though it
1196 * could bite us in other ways).
1197 *
1198 * Unfortunately this is occurring too early in the initialization,
1199 * of necessity coming before JNI is initialized, and we're not quite
1200 * ready to set up the application class loader.
1201 *
1202 * So we save a pointer to the method in gDvm.methFakeNativeEntry
1203 * and check it in FindClass. The method is private so nobody else
1204 * can call it.
1205 */
1206 //nativeStart->classLoader = dvmGetSystemClassLoader();
1207
1208 mainMeth = dvmFindDirectMethodByDescriptor(nativeStart,
1209 "main", "([Ljava/lang/String;)V");
1210 if (mainMeth == NULL) {
1211 LOGE("Unable to find 'main' in dalvik.system.NativeStart\n");
1212 return false;
1213 }
1214
1215 gDvm.methFakeNativeEntry = mainMeth;
1216 }
1217
1218 return dvmPushJNIFrame(thread, gDvm.methFakeNativeEntry);
1219 }
1220
1221
1222 /*
1223 * Add a stack frame that makes it look like the native thread has been
1224 * executing interpreted code. This gives us a place to hang JNI local
1225 * references.
1226 */
createFakeRunFrame(Thread * thread)1227 static bool createFakeRunFrame(Thread* thread)
1228 {
1229 ClassObject* nativeStart;
1230 Method* runMeth;
1231
1232 assert(thread->threadId != 1); // not for main thread
1233
1234 nativeStart =
1235 dvmFindSystemClassNoInit("Ldalvik/system/NativeStart;");
1236 if (nativeStart == NULL) {
1237 LOGE("Unable to find dalvik.system.NativeStart class\n");
1238 return false;
1239 }
1240
1241 runMeth = dvmFindVirtualMethodByDescriptor(nativeStart, "run", "()V");
1242 if (runMeth == NULL) {
1243 LOGE("Unable to find 'run' in dalvik.system.NativeStart\n");
1244 return false;
1245 }
1246
1247 return dvmPushJNIFrame(thread, runMeth);
1248 }
1249
1250 /*
1251 * Helper function to set the name of the current thread
1252 */
setThreadName(const char * threadName)1253 static void setThreadName(const char *threadName)
1254 {
1255 #if defined(HAVE_PRCTL)
1256 int hasAt = 0;
1257 int hasDot = 0;
1258 const char *s = threadName;
1259 while (*s) {
1260 if (*s == '.') hasDot = 1;
1261 else if (*s == '@') hasAt = 1;
1262 s++;
1263 }
1264 int len = s - threadName;
1265 if (len < 15 || hasAt || !hasDot) {
1266 s = threadName;
1267 } else {
1268 s = threadName + len - 15;
1269 }
1270 prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
1271 #endif
1272 }
1273
1274 /*
1275 * Create a thread as a result of java.lang.Thread.start().
1276 *
1277 * We do have to worry about some concurrency problems, e.g. programs
1278 * that try to call Thread.start() on the same object from multiple threads.
1279 * (This will fail for all but one, but we have to make sure that it succeeds
1280 * for exactly one.)
1281 *
1282 * Some of the complexity here arises from our desire to mimic the
1283 * Thread vs. VMThread class decomposition we inherited. We've been given
1284 * a Thread, and now we need to create a VMThread and then populate both
1285 * objects. We also need to create one of our internal Thread objects.
1286 *
1287 * Pass in a stack size of 0 to get the default.
1288 */
dvmCreateInterpThread(Object * threadObj,int reqStackSize)1289 bool dvmCreateInterpThread(Object* threadObj, int reqStackSize)
1290 {
1291 pthread_attr_t threadAttr;
1292 pthread_t threadHandle;
1293 Thread* self;
1294 Thread* newThread = NULL;
1295 Object* vmThreadObj = NULL;
1296 int stackSize;
1297
1298 assert(threadObj != NULL);
1299
1300 if(gDvm.zygote) {
1301 // Allow the sampling profiler thread. We shut it down before forking.
1302 StringObject* nameStr = (StringObject*) dvmGetFieldObject(threadObj,
1303 gDvm.offJavaLangThread_name);
1304 char* threadName = dvmCreateCstrFromString(nameStr);
1305 bool profilerThread = strcmp(threadName, "SamplingProfiler") == 0;
1306 free(threadName);
1307 if (!profilerThread) {
1308 dvmThrowException("Ljava/lang/IllegalStateException;",
1309 "No new threads in -Xzygote mode");
1310
1311 goto fail;
1312 }
1313 }
1314
1315 self = dvmThreadSelf();
1316 if (reqStackSize == 0)
1317 stackSize = gDvm.stackSize;
1318 else if (reqStackSize < kMinStackSize)
1319 stackSize = kMinStackSize;
1320 else if (reqStackSize > kMaxStackSize)
1321 stackSize = kMaxStackSize;
1322 else
1323 stackSize = reqStackSize;
1324
1325 pthread_attr_init(&threadAttr);
1326 pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
1327
1328 /*
1329 * To minimize the time spent in the critical section, we allocate the
1330 * vmThread object here.
1331 */
1332 vmThreadObj = dvmAllocObject(gDvm.classJavaLangVMThread, ALLOC_DEFAULT);
1333 if (vmThreadObj == NULL)
1334 goto fail;
1335
1336 newThread = allocThread(stackSize);
1337 if (newThread == NULL)
1338 goto fail;
1339 newThread->threadObj = threadObj;
1340
1341 assert(newThread->status == THREAD_INITIALIZING);
1342
1343 /*
1344 * We need to lock out other threads while we test and set the
1345 * "vmThread" field in java.lang.Thread, because we use that to determine
1346 * if this thread has been started before. We use the thread list lock
1347 * because it's handy and we're going to need to grab it again soon
1348 * anyway.
1349 */
1350 dvmLockThreadList(self);
1351
1352 if (dvmGetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread) != NULL) {
1353 dvmUnlockThreadList();
1354 dvmThrowException("Ljava/lang/IllegalThreadStateException;",
1355 "thread has already been started");
1356 goto fail;
1357 }
1358
1359 /*
1360 * There are actually three data structures: Thread (object), VMThread
1361 * (object), and Thread (C struct). All of them point to at least one
1362 * other.
1363 *
1364 * As soon as "VMThread.vmData" is assigned, other threads can start
1365 * making calls into us (e.g. setPriority).
1366 */
1367 dvmSetFieldInt(vmThreadObj, gDvm.offJavaLangVMThread_vmData, (u4)newThread);
1368 dvmSetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread, vmThreadObj);
1369
1370 /*
1371 * Thread creation might take a while, so release the lock.
1372 */
1373 dvmUnlockThreadList();
1374
1375 int cc, oldStatus;
1376 oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
1377 cc = pthread_create(&threadHandle, &threadAttr, interpThreadStart,
1378 newThread);
1379 oldStatus = dvmChangeStatus(self, oldStatus);
1380
1381 if (cc != 0) {
1382 /*
1383 * Failure generally indicates that we have exceeded system
1384 * resource limits. VirtualMachineError is probably too severe,
1385 * so use OutOfMemoryError.
1386 */
1387 LOGE("Thread creation failed (err=%s)\n", strerror(errno));
1388
1389 dvmSetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread, NULL);
1390
1391 dvmThrowException("Ljava/lang/OutOfMemoryError;",
1392 "thread creation failed");
1393 goto fail;
1394 }
1395
1396 /*
1397 * We need to wait for the thread to start. Otherwise, depending on
1398 * the whims of the OS scheduler, we could return and the code in our
1399 * thread could try to do operations on the new thread before it had
1400 * finished starting.
1401 *
1402 * The new thread will lock the thread list, change its state to
1403 * THREAD_STARTING, broadcast to gDvm.threadStartCond, and then sleep
1404 * on gDvm.threadStartCond (which uses the thread list lock). This
1405 * thread (the parent) will either see that the thread is already ready
1406 * after we grab the thread list lock, or will be awakened from the
1407 * condition variable on the broadcast.
1408 *
1409 * We don't want to stall the rest of the VM while the new thread
1410 * starts, which can happen if the GC wakes up at the wrong moment.
1411 * So, we change our own status to VMWAIT, and self-suspend if
1412 * necessary after we finish adding the new thread.
1413 *
1414 *
1415 * We have to deal with an odd race with the GC/debugger suspension
1416 * mechanism when creating a new thread. The information about whether
1417 * or not a thread should be suspended is contained entirely within
1418 * the Thread struct; this is usually cleaner to deal with than having
1419 * one or more globally-visible suspension flags. The trouble is that
1420 * we could create the thread while the VM is trying to suspend all
1421 * threads. The suspend-count won't be nonzero for the new thread,
1422 * so dvmChangeStatus(THREAD_RUNNING) won't cause a suspension.
1423 *
1424 * The easiest way to deal with this is to prevent the new thread from
1425 * running until the parent says it's okay. This results in the
1426 * following (correct) sequence of events for a "badly timed" GC
1427 * (where '-' is us, 'o' is the child, and '+' is some other thread):
1428 *
1429 * - call pthread_create()
1430 * - lock thread list
1431 * - put self into THREAD_VMWAIT so GC doesn't wait for us
1432 * - sleep on condition var (mutex = thread list lock) until child starts
1433 * + GC triggered by another thread
1434 * + thread list locked; suspend counts updated; thread list unlocked
1435 * + loop waiting for all runnable threads to suspend
1436 * + success, start GC
1437 * o child thread wakes, signals condition var to wake parent
1438 * o child waits for parent ack on condition variable
1439 * - we wake up, locking thread list
1440 * - add child to thread list
1441 * - unlock thread list
1442 * - change our state back to THREAD_RUNNING; GC causes us to suspend
1443 * + GC finishes; all threads in thread list are resumed
1444 * - lock thread list
1445 * - set child to THREAD_VMWAIT, and signal it to start
1446 * - unlock thread list
1447 * o child resumes
1448 * o child changes state to THREAD_RUNNING
1449 *
1450 * The above shows the GC starting up during thread creation, but if
1451 * it starts anywhere after VMThread.create() is called it will
1452 * produce the same series of events.
1453 *
1454 * Once the child is in the thread list, it will be suspended and
1455 * resumed like any other thread. In the above scenario the resume-all
1456 * code will try to resume the new thread, which was never actually
1457 * suspended, and try to decrement the child's thread suspend count to -1.
1458 * We can catch this in the resume-all code.
1459 *
1460 * Bouncing back and forth between threads like this adds a small amount
1461 * of scheduler overhead to thread startup.
1462 *
1463 * One alternative to having the child wait for the parent would be
1464 * to have the child inherit the parents' suspension count. This
1465 * would work for a GC, since we can safely assume that the parent
1466 * thread didn't cause it, but we must only do so if the parent suspension
1467 * was caused by a suspend-all. If the parent was being asked to
1468 * suspend singly by the debugger, the child should not inherit the value.
1469 *
1470 * We could also have a global "new thread suspend count" that gets
1471 * picked up by new threads before changing state to THREAD_RUNNING.
1472 * This would be protected by the thread list lock and set by a
1473 * suspend-all.
1474 */
1475 dvmLockThreadList(self);
1476 assert(self->status == THREAD_RUNNING);
1477 self->status = THREAD_VMWAIT;
1478 while (newThread->status != THREAD_STARTING)
1479 pthread_cond_wait(&gDvm.threadStartCond, &gDvm.threadListLock);
1480
1481 LOG_THREAD("threadid=%d: adding to list\n", newThread->threadId);
1482 newThread->next = gDvm.threadList->next;
1483 if (newThread->next != NULL)
1484 newThread->next->prev = newThread;
1485 newThread->prev = gDvm.threadList;
1486 gDvm.threadList->next = newThread;
1487
1488 if (!dvmGetFieldBoolean(threadObj, gDvm.offJavaLangThread_daemon))
1489 gDvm.nonDaemonThreadCount++; // guarded by thread list lock
1490
1491 dvmUnlockThreadList();
1492
1493 /* change status back to RUNNING, self-suspending if necessary */
1494 dvmChangeStatus(self, THREAD_RUNNING);
1495
1496 /*
1497 * Tell the new thread to start.
1498 *
1499 * We must hold the thread list lock before messing with another thread.
1500 * In the general case we would also need to verify that newThread was
1501 * still in the thread list, but in our case the thread has not started
1502 * executing user code and therefore has not had a chance to exit.
1503 *
1504 * We move it to VMWAIT, and it then shifts itself to RUNNING, which
1505 * comes with a suspend-pending check.
1506 */
1507 dvmLockThreadList(self);
1508
1509 assert(newThread->status == THREAD_STARTING);
1510 newThread->status = THREAD_VMWAIT;
1511 pthread_cond_broadcast(&gDvm.threadStartCond);
1512
1513 dvmUnlockThreadList();
1514
1515 dvmReleaseTrackedAlloc(vmThreadObj, NULL);
1516 return true;
1517
1518 fail:
1519 freeThread(newThread);
1520 dvmReleaseTrackedAlloc(vmThreadObj, NULL);
1521 return false;
1522 }
1523
1524 /*
1525 * pthread entry function for threads started from interpreted code.
1526 */
interpThreadStart(void * arg)1527 static void* interpThreadStart(void* arg)
1528 {
1529 Thread* self = (Thread*) arg;
1530
1531 char *threadName = dvmGetThreadName(self);
1532 setThreadName(threadName);
1533 free(threadName);
1534
1535 /*
1536 * Finish initializing the Thread struct.
1537 */
1538 prepareThread(self);
1539
1540 LOG_THREAD("threadid=%d: created from interp\n", self->threadId);
1541
1542 /*
1543 * Change our status and wake our parent, who will add us to the
1544 * thread list and advance our state to VMWAIT.
1545 */
1546 dvmLockThreadList(self);
1547 self->status = THREAD_STARTING;
1548 pthread_cond_broadcast(&gDvm.threadStartCond);
1549
1550 /*
1551 * Wait until the parent says we can go. Assuming there wasn't a
1552 * suspend pending, this will happen immediately. When it completes,
1553 * we're full-fledged citizens of the VM.
1554 *
1555 * We have to use THREAD_VMWAIT here rather than THREAD_RUNNING
1556 * because the pthread_cond_wait below needs to reacquire a lock that
1557 * suspend-all is also interested in. If we get unlucky, the parent could
1558 * change us to THREAD_RUNNING, then a GC could start before we get
1559 * signaled, and suspend-all will grab the thread list lock and then
1560 * wait for us to suspend. We'll be in the tail end of pthread_cond_wait
1561 * trying to get the lock.
1562 */
1563 while (self->status != THREAD_VMWAIT)
1564 pthread_cond_wait(&gDvm.threadStartCond, &gDvm.threadListLock);
1565
1566 dvmUnlockThreadList();
1567
1568 /*
1569 * Add a JNI context.
1570 */
1571 self->jniEnv = dvmCreateJNIEnv(self);
1572
1573 /*
1574 * Change our state so the GC will wait for us from now on. If a GC is
1575 * in progress this call will suspend us.
1576 */
1577 dvmChangeStatus(self, THREAD_RUNNING);
1578
1579 /*
1580 * Notify the debugger & DDM. The debugger notification may cause
1581 * us to suspend ourselves (and others).
1582 */
1583 if (gDvm.debuggerConnected)
1584 dvmDbgPostThreadStart(self);
1585
1586 /*
1587 * Set the system thread priority according to the Thread object's
1588 * priority level. We don't usually need to do this, because both the
1589 * Thread object and system thread priorities inherit from parents. The
1590 * tricky case is when somebody creates a Thread object, calls
1591 * setPriority(), and then starts the thread. We could manage this with
1592 * a "needs priority update" flag to avoid the redundant call.
1593 */
1594 int priority = dvmGetFieldInt(self->threadObj,
1595 gDvm.offJavaLangThread_priority);
1596 dvmChangeThreadPriority(self, priority);
1597
1598 /*
1599 * Execute the "run" method.
1600 *
1601 * At this point our stack is empty, so somebody who comes looking for
1602 * stack traces right now won't have much to look at. This is normal.
1603 */
1604 Method* run = self->threadObj->clazz->vtable[gDvm.voffJavaLangThread_run];
1605 JValue unused;
1606
1607 LOGV("threadid=%d: calling run()\n", self->threadId);
1608 assert(strcmp(run->name, "run") == 0);
1609 dvmCallMethod(self, run, self->threadObj, &unused);
1610 LOGV("threadid=%d: exiting\n", self->threadId);
1611
1612 /*
1613 * Remove the thread from various lists, report its death, and free
1614 * its resources.
1615 */
1616 dvmDetachCurrentThread();
1617
1618 return NULL;
1619 }
1620
1621 /*
1622 * The current thread is exiting with an uncaught exception. The
1623 * Java programming language allows the application to provide a
1624 * thread-exit-uncaught-exception handler for the VM, for a specific
1625 * Thread, and for all threads in a ThreadGroup.
1626 *
1627 * Version 1.5 added the per-thread handler. We need to call
1628 * "uncaughtException" in the handler object, which is either the
1629 * ThreadGroup object or the Thread-specific handler.
1630 */
threadExitUncaughtException(Thread * self,Object * group)1631 static void threadExitUncaughtException(Thread* self, Object* group)
1632 {
1633 Object* exception;
1634 Object* handlerObj;
1635 ClassObject* throwable;
1636 Method* uncaughtHandler = NULL;
1637 InstField* threadHandler;
1638
1639 LOGW("threadid=%d: thread exiting with uncaught exception (group=%p)\n",
1640 self->threadId, group);
1641 assert(group != NULL);
1642
1643 /*
1644 * Get a pointer to the exception, then clear out the one in the
1645 * thread. We don't want to have it set when executing interpreted code.
1646 */
1647 exception = dvmGetException(self);
1648 dvmAddTrackedAlloc(exception, self);
1649 dvmClearException(self);
1650
1651 /*
1652 * Get the Thread's "uncaughtHandler" object. Use it if non-NULL;
1653 * else use "group" (which is an instance of UncaughtExceptionHandler).
1654 */
1655 threadHandler = dvmFindInstanceField(gDvm.classJavaLangThread,
1656 "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;");
1657 if (threadHandler == NULL) {
1658 LOGW("WARNING: no 'uncaughtHandler' field in java/lang/Thread\n");
1659 goto bail;
1660 }
1661 handlerObj = dvmGetFieldObject(self->threadObj, threadHandler->byteOffset);
1662 if (handlerObj == NULL)
1663 handlerObj = group;
1664
1665 /*
1666 * Find the "uncaughtHandler" field in this object.
1667 */
1668 uncaughtHandler = dvmFindVirtualMethodHierByDescriptor(handlerObj->clazz,
1669 "uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
1670
1671 if (uncaughtHandler != NULL) {
1672 //LOGI("+++ calling %s.uncaughtException\n",
1673 // handlerObj->clazz->descriptor);
1674 JValue unused;
1675 dvmCallMethod(self, uncaughtHandler, handlerObj, &unused,
1676 self->threadObj, exception);
1677 } else {
1678 /* restore it and dump a stack trace */
1679 LOGW("WARNING: no 'uncaughtException' method in class %s\n",
1680 handlerObj->clazz->descriptor);
1681 dvmSetException(self, exception);
1682 dvmLogExceptionStackTrace();
1683 }
1684
1685 bail:
1686 #if defined(WITH_JIT)
1687 /* Remove this thread's suspendCount from global suspendCount sum */
1688 lockThreadSuspendCount();
1689 dvmAddToThreadSuspendCount(&self->suspendCount, -self->suspendCount);
1690 unlockThreadSuspendCount();
1691 #endif
1692 dvmReleaseTrackedAlloc(exception, self);
1693 }
1694
1695
1696 /*
1697 * Create an internal VM thread, for things like JDWP and finalizers.
1698 *
1699 * The easiest way to do this is create a new thread and then use the
1700 * JNI AttachCurrentThread implementation.
1701 *
1702 * This does not return until after the new thread has begun executing.
1703 */
dvmCreateInternalThread(pthread_t * pHandle,const char * name,InternalThreadStart func,void * funcArg)1704 bool dvmCreateInternalThread(pthread_t* pHandle, const char* name,
1705 InternalThreadStart func, void* funcArg)
1706 {
1707 InternalStartArgs* pArgs;
1708 Object* systemGroup;
1709 pthread_attr_t threadAttr;
1710 volatile Thread* newThread = NULL;
1711 volatile int createStatus = 0;
1712
1713 systemGroup = dvmGetSystemThreadGroup();
1714 if (systemGroup == NULL)
1715 return false;
1716
1717 pArgs = (InternalStartArgs*) malloc(sizeof(*pArgs));
1718 pArgs->func = func;
1719 pArgs->funcArg = funcArg;
1720 pArgs->name = strdup(name); // storage will be owned by new thread
1721 pArgs->group = systemGroup;
1722 pArgs->isDaemon = true;
1723 pArgs->pThread = &newThread;
1724 pArgs->pCreateStatus = &createStatus;
1725
1726 pthread_attr_init(&threadAttr);
1727 //pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
1728
1729 if (pthread_create(pHandle, &threadAttr, internalThreadStart,
1730 pArgs) != 0)
1731 {
1732 LOGE("internal thread creation failed\n");
1733 free(pArgs->name);
1734 free(pArgs);
1735 return false;
1736 }
1737
1738 /*
1739 * Wait for the child to start. This gives us an opportunity to make
1740 * sure that the thread started correctly, and allows our caller to
1741 * assume that the thread has started running.
1742 *
1743 * Because we aren't holding a lock across the thread creation, it's
1744 * possible that the child will already have completed its
1745 * initialization. Because the child only adjusts "createStatus" while
1746 * holding the thread list lock, the initial condition on the "while"
1747 * loop will correctly avoid the wait if this occurs.
1748 *
1749 * It's also possible that we'll have to wait for the thread to finish
1750 * being created, and as part of allocating a Thread object it might
1751 * need to initiate a GC. We switch to VMWAIT while we pause.
1752 */
1753 Thread* self = dvmThreadSelf();
1754 int oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
1755 dvmLockThreadList(self);
1756 while (createStatus == 0)
1757 pthread_cond_wait(&gDvm.threadStartCond, &gDvm.threadListLock);
1758
1759 if (newThread == NULL) {
1760 LOGW("internal thread create failed (createStatus=%d)\n", createStatus);
1761 assert(createStatus < 0);
1762 /* don't free pArgs -- if pthread_create succeeded, child owns it */
1763 dvmUnlockThreadList();
1764 dvmChangeStatus(self, oldStatus);
1765 return false;
1766 }
1767
1768 /* thread could be in any state now (except early init states) */
1769 //assert(newThread->status == THREAD_RUNNING);
1770
1771 dvmUnlockThreadList();
1772 dvmChangeStatus(self, oldStatus);
1773
1774 return true;
1775 }
1776
1777 /*
1778 * pthread entry function for internally-created threads.
1779 *
1780 * We are expected to free "arg" and its contents. If we're a daemon
1781 * thread, and we get cancelled abruptly when the VM shuts down, the
1782 * storage won't be freed. If this becomes a concern we can make a copy
1783 * on the stack.
1784 */
internalThreadStart(void * arg)1785 static void* internalThreadStart(void* arg)
1786 {
1787 InternalStartArgs* pArgs = (InternalStartArgs*) arg;
1788 JavaVMAttachArgs jniArgs;
1789
1790 jniArgs.version = JNI_VERSION_1_2;
1791 jniArgs.name = pArgs->name;
1792 jniArgs.group = pArgs->group;
1793
1794 setThreadName(pArgs->name);
1795
1796 /* use local jniArgs as stack top */
1797 if (dvmAttachCurrentThread(&jniArgs, pArgs->isDaemon)) {
1798 /*
1799 * Tell the parent of our success.
1800 *
1801 * threadListLock is the mutex for threadStartCond.
1802 */
1803 dvmLockThreadList(dvmThreadSelf());
1804 *pArgs->pCreateStatus = 1;
1805 *pArgs->pThread = dvmThreadSelf();
1806 pthread_cond_broadcast(&gDvm.threadStartCond);
1807 dvmUnlockThreadList();
1808
1809 LOG_THREAD("threadid=%d: internal '%s'\n",
1810 dvmThreadSelf()->threadId, pArgs->name);
1811
1812 /* execute */
1813 (*pArgs->func)(pArgs->funcArg);
1814
1815 /* detach ourselves */
1816 dvmDetachCurrentThread();
1817 } else {
1818 /*
1819 * Tell the parent of our failure. We don't have a Thread struct,
1820 * so we can't be suspended, so we don't need to enter a critical
1821 * section.
1822 */
1823 dvmLockThreadList(dvmThreadSelf());
1824 *pArgs->pCreateStatus = -1;
1825 assert(*pArgs->pThread == NULL);
1826 pthread_cond_broadcast(&gDvm.threadStartCond);
1827 dvmUnlockThreadList();
1828
1829 assert(*pArgs->pThread == NULL);
1830 }
1831
1832 free(pArgs->name);
1833 free(pArgs);
1834 return NULL;
1835 }
1836
1837 /*
1838 * Attach the current thread to the VM.
1839 *
1840 * Used for internally-created threads and JNI's AttachCurrentThread.
1841 */
dvmAttachCurrentThread(const JavaVMAttachArgs * pArgs,bool isDaemon)1842 bool dvmAttachCurrentThread(const JavaVMAttachArgs* pArgs, bool isDaemon)
1843 {
1844 Thread* self = NULL;
1845 Object* threadObj = NULL;
1846 Object* vmThreadObj = NULL;
1847 StringObject* threadNameStr = NULL;
1848 Method* init;
1849 bool ok, ret;
1850
1851 /* establish a basic sense of self */
1852 self = allocThread(gDvm.stackSize);
1853 if (self == NULL)
1854 goto fail;
1855 setThreadSelf(self);
1856
1857 /*
1858 * Create Thread and VMThread objects. We have to use ALLOC_NO_GC
1859 * because this thread is not yet visible to the VM. We could also
1860 * just grab the GC lock earlier, but that leaves us executing
1861 * interpreted code with the lock held, which is not prudent.
1862 *
1863 * The alloc calls will block if a GC is in progress, so we don't need
1864 * to check for global suspension here.
1865 *
1866 * It's also possible for the allocation calls to *cause* a GC.
1867 */
1868 //BUG: deadlock if a GC happens here during HeapWorker creation
1869 threadObj = dvmAllocObject(gDvm.classJavaLangThread, ALLOC_NO_GC);
1870 if (threadObj == NULL)
1871 goto fail;
1872 vmThreadObj = dvmAllocObject(gDvm.classJavaLangVMThread, ALLOC_NO_GC);
1873 if (vmThreadObj == NULL)
1874 goto fail;
1875
1876 self->threadObj = threadObj;
1877 dvmSetFieldInt(vmThreadObj, gDvm.offJavaLangVMThread_vmData, (u4)self);
1878
1879 /*
1880 * Do some java.lang.Thread constructor prep before we lock stuff down.
1881 */
1882 if (pArgs->name != NULL) {
1883 threadNameStr = dvmCreateStringFromCstr(pArgs->name, ALLOC_NO_GC);
1884 if (threadNameStr == NULL) {
1885 assert(dvmCheckException(dvmThreadSelf()));
1886 goto fail;
1887 }
1888 }
1889
1890 init = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangThread, "<init>",
1891 "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
1892 if (init == NULL) {
1893 assert(dvmCheckException(dvmThreadSelf()));
1894 goto fail;
1895 }
1896
1897 /*
1898 * Finish our thread prep. We need to do this before invoking any
1899 * interpreted code. prepareThread() requires that we hold the thread
1900 * list lock.
1901 */
1902 dvmLockThreadList(self);
1903 ok = prepareThread(self);
1904 dvmUnlockThreadList();
1905 if (!ok)
1906 goto fail;
1907
1908 self->jniEnv = dvmCreateJNIEnv(self);
1909 if (self->jniEnv == NULL)
1910 goto fail;
1911
1912 /*
1913 * Create a "fake" JNI frame at the top of the main thread interp stack.
1914 * It isn't really necessary for the internal threads, but it gives
1915 * the debugger something to show. It is essential for the JNI-attached
1916 * threads.
1917 */
1918 if (!createFakeRunFrame(self))
1919 goto fail;
1920
1921 /*
1922 * The native side of the thread is ready; add it to the list.
1923 */
1924 LOG_THREAD("threadid=%d: adding to list (attached)\n", self->threadId);
1925
1926 /* Start off in VMWAIT, because we may be about to block
1927 * on the heap lock, and we don't want any suspensions
1928 * to wait for us.
1929 */
1930 self->status = THREAD_VMWAIT;
1931
1932 /*
1933 * Add ourselves to the thread list. Once we finish here we are
1934 * visible to the debugger and the GC.
1935 */
1936 dvmLockThreadList(self);
1937
1938 self->next = gDvm.threadList->next;
1939 if (self->next != NULL)
1940 self->next->prev = self;
1941 self->prev = gDvm.threadList;
1942 gDvm.threadList->next = self;
1943 if (!isDaemon)
1944 gDvm.nonDaemonThreadCount++;
1945
1946 dvmUnlockThreadList();
1947
1948 /*
1949 * It's possible that a GC is currently running. Our thread
1950 * wasn't in the list when the GC started, so it's not properly
1951 * suspended in that case. Synchronize on the heap lock (held
1952 * when a GC is happening) to guarantee that any GCs from here
1953 * on will see this thread in the list.
1954 */
1955 dvmLockMutex(&gDvm.gcHeapLock);
1956 dvmUnlockMutex(&gDvm.gcHeapLock);
1957
1958 /*
1959 * Switch to the running state now that we're ready for
1960 * suspensions. This call may suspend.
1961 */
1962 dvmChangeStatus(self, THREAD_RUNNING);
1963
1964 /*
1965 * Now we're ready to run some interpreted code.
1966 *
1967 * We need to construct the Thread object and set the VMThread field.
1968 * Setting VMThread tells interpreted code that we're alive.
1969 *
1970 * Call the (group, name, priority, daemon) constructor on the Thread.
1971 * This sets the thread's name and adds it to the specified group, and
1972 * provides values for priority and daemon (which are normally inherited
1973 * from the current thread).
1974 */
1975 JValue unused;
1976 dvmCallMethod(self, init, threadObj, &unused, (Object*)pArgs->group,
1977 threadNameStr, getThreadPriorityFromSystem(), isDaemon);
1978 if (dvmCheckException(self)) {
1979 LOGE("exception thrown while constructing attached thread object\n");
1980 goto fail_unlink;
1981 }
1982 //if (isDaemon)
1983 // dvmSetFieldBoolean(threadObj, gDvm.offJavaLangThread_daemon, true);
1984
1985 /*
1986 * Set the VMThread field, which tells interpreted code that we're alive.
1987 *
1988 * The risk of a thread start collision here is very low; somebody
1989 * would have to be deliberately polling the ThreadGroup list and
1990 * trying to start threads against anything it sees, which would
1991 * generally cause problems for all thread creation. However, for
1992 * correctness we test "vmThread" before setting it.
1993 */
1994 if (dvmGetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread) != NULL) {
1995 dvmThrowException("Ljava/lang/IllegalThreadStateException;",
1996 "thread has already been started");
1997 /* We don't want to free anything associated with the thread
1998 * because someone is obviously interested in it. Just let
1999 * it go and hope it will clean itself up when its finished.
2000 * This case should never happen anyway.
2001 *
2002 * Since we're letting it live, we need to finish setting it up.
2003 * We just have to let the caller know that the intended operation
2004 * has failed.
2005 *
2006 * [ This seems strange -- stepping on the vmThread object that's
2007 * already present seems like a bad idea. TODO: figure this out. ]
2008 */
2009 ret = false;
2010 } else
2011 ret = true;
2012 dvmSetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread, vmThreadObj);
2013
2014 /* These are now reachable from the thread groups. */
2015 dvmClearAllocFlags(threadObj, ALLOC_NO_GC);
2016 dvmClearAllocFlags(vmThreadObj, ALLOC_NO_GC);
2017
2018 /*
2019 * The thread is ready to go; let the debugger see it.
2020 */
2021 self->threadObj = threadObj;
2022
2023 LOG_THREAD("threadid=%d: attached from native, name=%s\n",
2024 self->threadId, pArgs->name);
2025
2026 /* tell the debugger & DDM */
2027 if (gDvm.debuggerConnected)
2028 dvmDbgPostThreadStart(self);
2029
2030 return ret;
2031
2032 fail_unlink:
2033 dvmLockThreadList(self);
2034 unlinkThread(self);
2035 if (!isDaemon)
2036 gDvm.nonDaemonThreadCount--;
2037 dvmUnlockThreadList();
2038 /* fall through to "fail" */
2039 fail:
2040 dvmClearAllocFlags(threadObj, ALLOC_NO_GC);
2041 dvmClearAllocFlags(vmThreadObj, ALLOC_NO_GC);
2042 if (self != NULL) {
2043 if (self->jniEnv != NULL) {
2044 dvmDestroyJNIEnv(self->jniEnv);
2045 self->jniEnv = NULL;
2046 }
2047 freeThread(self);
2048 }
2049 setThreadSelf(NULL);
2050 return false;
2051 }
2052
2053 /*
2054 * Detach the thread from the various data structures, notify other threads
2055 * that are waiting to "join" it, and free up all heap-allocated storage.
2056 *
2057 * Used for all threads.
2058 *
2059 * When we get here the interpreted stack should be empty. The JNI 1.6 spec
2060 * requires us to enforce this for the DetachCurrentThread call, probably
2061 * because it also says that DetachCurrentThread causes all monitors
2062 * associated with the thread to be released. (Because the stack is empty,
2063 * we only have to worry about explicit JNI calls to MonitorEnter.)
2064 *
2065 * THOUGHT:
2066 * We might want to avoid freeing our internal Thread structure until the
2067 * associated Thread/VMThread objects get GCed. Our Thread is impossible to
2068 * get to once the thread shuts down, but there is a small possibility of
2069 * an operation starting in another thread before this thread halts, and
2070 * finishing much later (perhaps the thread got stalled by a weird OS bug).
2071 * We don't want something like Thread.isInterrupted() crawling through
2072 * freed storage. Can do with a Thread finalizer, or by creating a
2073 * dedicated ThreadObject class for java/lang/Thread and moving all of our
2074 * state into that.
2075 */
dvmDetachCurrentThread(void)2076 void dvmDetachCurrentThread(void)
2077 {
2078 Thread* self = dvmThreadSelf();
2079 Object* vmThread;
2080 Object* group;
2081
2082 /*
2083 * Make sure we're not detaching a thread that's still running. (This
2084 * could happen with an explicit JNI detach call.)
2085 *
2086 * A thread created by interpreted code will finish with a depth of
2087 * zero, while a JNI-attached thread will have the synthetic "stack
2088 * starter" native method at the top.
2089 */
2090 int curDepth = dvmComputeExactFrameDepth(self->curFrame);
2091 if (curDepth != 0) {
2092 bool topIsNative = false;
2093
2094 if (curDepth == 1) {
2095 /* not expecting a lingering break frame; just look at curFrame */
2096 assert(!dvmIsBreakFrame(self->curFrame));
2097 StackSaveArea* ssa = SAVEAREA_FROM_FP(self->curFrame);
2098 if (dvmIsNativeMethod(ssa->method))
2099 topIsNative = true;
2100 }
2101
2102 if (!topIsNative) {
2103 LOGE("ERROR: detaching thread with interp frames (count=%d)\n",
2104 curDepth);
2105 dvmDumpThread(self, false);
2106 dvmAbort();
2107 }
2108 }
2109
2110 group = dvmGetFieldObject(self->threadObj, gDvm.offJavaLangThread_group);
2111 LOG_THREAD("threadid=%d: detach (group=%p)\n", self->threadId, group);
2112
2113 /*
2114 * Release any held monitors. Since there are no interpreted stack
2115 * frames, the only thing left are the monitors held by JNI MonitorEnter
2116 * calls.
2117 */
2118 dvmReleaseJniMonitors(self);
2119
2120 /*
2121 * Do some thread-exit uncaught exception processing if necessary.
2122 */
2123 if (dvmCheckException(self))
2124 threadExitUncaughtException(self, group);
2125
2126 /*
2127 * Remove the thread from the thread group.
2128 */
2129 if (group != NULL) {
2130 Method* removeThread =
2131 group->clazz->vtable[gDvm.voffJavaLangThreadGroup_removeThread];
2132 JValue unused;
2133 dvmCallMethod(self, removeThread, group, &unused, self->threadObj);
2134 }
2135
2136 /*
2137 * Clear the vmThread reference in the Thread object. Interpreted code
2138 * will now see that this Thread is not running. As this may be the
2139 * only reference to the VMThread object that the VM knows about, we
2140 * have to create an internal reference to it first.
2141 */
2142 vmThread = dvmGetFieldObject(self->threadObj,
2143 gDvm.offJavaLangThread_vmThread);
2144 dvmAddTrackedAlloc(vmThread, self);
2145 dvmSetFieldObject(self->threadObj, gDvm.offJavaLangThread_vmThread, NULL);
2146
2147 /* clear out our struct Thread pointer, since it's going away */
2148 dvmSetFieldObject(vmThread, gDvm.offJavaLangVMThread_vmData, NULL);
2149
2150 /*
2151 * Tell the debugger & DDM. This may cause the current thread or all
2152 * threads to suspend.
2153 *
2154 * The JDWP spec is somewhat vague about when this happens, other than
2155 * that it's issued by the dying thread, which may still appear in
2156 * an "all threads" listing.
2157 */
2158 if (gDvm.debuggerConnected)
2159 dvmDbgPostThreadDeath(self);
2160
2161 /*
2162 * Thread.join() is implemented as an Object.wait() on the VMThread
2163 * object. Signal anyone who is waiting.
2164 */
2165 dvmLockObject(self, vmThread);
2166 dvmObjectNotifyAll(self, vmThread);
2167 dvmUnlockObject(self, vmThread);
2168
2169 dvmReleaseTrackedAlloc(vmThread, self);
2170 vmThread = NULL;
2171
2172 /*
2173 * We're done manipulating objects, so it's okay if the GC runs in
2174 * parallel with us from here out. It's important to do this if
2175 * profiling is enabled, since we can wait indefinitely.
2176 */
2177 self->status = THREAD_VMWAIT;
2178
2179 #ifdef WITH_PROFILER
2180 /*
2181 * If we're doing method trace profiling, we don't want threads to exit,
2182 * because if they do we'll end up reusing thread IDs. This complicates
2183 * analysis and makes it impossible to have reasonable output in the
2184 * "threads" section of the "key" file.
2185 *
2186 * We need to do this after Thread.join() completes, or other threads
2187 * could get wedged. Since self->threadObj is still valid, the Thread
2188 * object will not get GCed even though we're no longer in the ThreadGroup
2189 * list (which is important since the profiling thread needs to get
2190 * the thread's name).
2191 */
2192 MethodTraceState* traceState = &gDvm.methodTrace;
2193
2194 dvmLockMutex(&traceState->startStopLock);
2195 if (traceState->traceEnabled) {
2196 LOGI("threadid=%d: waiting for method trace to finish\n",
2197 self->threadId);
2198 while (traceState->traceEnabled) {
2199 int cc;
2200 cc = pthread_cond_wait(&traceState->threadExitCond,
2201 &traceState->startStopLock);
2202 assert(cc == 0);
2203 }
2204 }
2205 dvmUnlockMutex(&traceState->startStopLock);
2206 #endif
2207
2208 dvmLockThreadList(self);
2209
2210 /*
2211 * Lose the JNI context.
2212 */
2213 dvmDestroyJNIEnv(self->jniEnv);
2214 self->jniEnv = NULL;
2215
2216 self->status = THREAD_ZOMBIE;
2217
2218 /*
2219 * Remove ourselves from the internal thread list.
2220 */
2221 unlinkThread(self);
2222
2223 /*
2224 * If we're the last one standing, signal anybody waiting in
2225 * DestroyJavaVM that it's okay to exit.
2226 */
2227 if (!dvmGetFieldBoolean(self->threadObj, gDvm.offJavaLangThread_daemon)) {
2228 gDvm.nonDaemonThreadCount--; // guarded by thread list lock
2229
2230 if (gDvm.nonDaemonThreadCount == 0) {
2231 int cc;
2232
2233 LOGV("threadid=%d: last non-daemon thread\n", self->threadId);
2234 //dvmDumpAllThreads(false);
2235 // cond var guarded by threadListLock, which we already hold
2236 cc = pthread_cond_signal(&gDvm.vmExitCond);
2237 assert(cc == 0);
2238 }
2239 }
2240
2241 LOGV("threadid=%d: bye!\n", self->threadId);
2242 releaseThreadId(self);
2243 dvmUnlockThreadList();
2244
2245 setThreadSelf(NULL);
2246
2247 dvmDetachSystemThread(self);
2248
2249 freeThread(self);
2250 }
2251
2252
2253 /*
2254 * Suspend a single thread. Do not use to suspend yourself.
2255 *
2256 * This is used primarily for debugger/DDMS activity. Does not return
2257 * until the thread has suspended or is in a "safe" state (e.g. executing
2258 * native code outside the VM).
2259 *
2260 * The thread list lock should be held before calling here -- it's not
2261 * entirely safe to hang on to a Thread* from another thread otherwise.
2262 * (We'd need to grab it here anyway to avoid clashing with a suspend-all.)
2263 */
dvmSuspendThread(Thread * thread)2264 void dvmSuspendThread(Thread* thread)
2265 {
2266 assert(thread != NULL);
2267 assert(thread != dvmThreadSelf());
2268 //assert(thread->handle != dvmJdwpGetDebugThread(gDvm.jdwpState));
2269
2270 lockThreadSuspendCount();
2271 dvmAddToThreadSuspendCount(&thread->suspendCount, 1);
2272 thread->dbgSuspendCount++;
2273
2274 LOG_THREAD("threadid=%d: suspend++, now=%d\n",
2275 thread->threadId, thread->suspendCount);
2276 unlockThreadSuspendCount();
2277
2278 waitForThreadSuspend(dvmThreadSelf(), thread);
2279 }
2280
2281 /*
2282 * Reduce the suspend count of a thread. If it hits zero, tell it to
2283 * resume.
2284 *
2285 * Used primarily for debugger/DDMS activity. The thread in question
2286 * might have been suspended singly or as part of a suspend-all operation.
2287 *
2288 * The thread list lock should be held before calling here -- it's not
2289 * entirely safe to hang on to a Thread* from another thread otherwise.
2290 * (We'd need to grab it here anyway to avoid clashing with a suspend-all.)
2291 */
dvmResumeThread(Thread * thread)2292 void dvmResumeThread(Thread* thread)
2293 {
2294 assert(thread != NULL);
2295 assert(thread != dvmThreadSelf());
2296 //assert(thread->handle != dvmJdwpGetDebugThread(gDvm.jdwpState));
2297
2298 lockThreadSuspendCount();
2299 if (thread->suspendCount > 0) {
2300 dvmAddToThreadSuspendCount(&thread->suspendCount, -1);
2301 thread->dbgSuspendCount--;
2302 } else {
2303 LOG_THREAD("threadid=%d: suspendCount already zero\n",
2304 thread->threadId);
2305 }
2306
2307 LOG_THREAD("threadid=%d: suspend--, now=%d\n",
2308 thread->threadId, thread->suspendCount);
2309
2310 if (thread->suspendCount == 0) {
2311 int cc = pthread_cond_broadcast(&gDvm.threadSuspendCountCond);
2312 assert(cc == 0);
2313 }
2314
2315 unlockThreadSuspendCount();
2316 }
2317
2318 /*
2319 * Suspend yourself, as a result of debugger activity.
2320 */
dvmSuspendSelf(bool jdwpActivity)2321 void dvmSuspendSelf(bool jdwpActivity)
2322 {
2323 Thread* self = dvmThreadSelf();
2324
2325 /* debugger thread may not suspend itself due to debugger activity! */
2326 assert(gDvm.jdwpState != NULL);
2327 if (self->handle == dvmJdwpGetDebugThread(gDvm.jdwpState)) {
2328 assert(false);
2329 return;
2330 }
2331
2332 /*
2333 * Collisions with other suspends aren't really interesting. We want
2334 * to ensure that we're the only one fiddling with the suspend count
2335 * though.
2336 */
2337 lockThreadSuspendCount();
2338 dvmAddToThreadSuspendCount(&self->suspendCount, 1);
2339 self->dbgSuspendCount++;
2340
2341 /*
2342 * Suspend ourselves.
2343 */
2344 assert(self->suspendCount > 0);
2345 self->isSuspended = true;
2346 LOG_THREAD("threadid=%d: self-suspending (dbg)\n", self->threadId);
2347
2348 /*
2349 * Tell JDWP that we've completed suspension. The JDWP thread can't
2350 * tell us to resume before we're fully asleep because we hold the
2351 * suspend count lock.
2352 *
2353 * If we got here via waitForDebugger(), don't do this part.
2354 */
2355 if (jdwpActivity) {
2356 //LOGI("threadid=%d: clearing wait-for-event (my handle=%08x)\n",
2357 // self->threadId, (int) self->handle);
2358 dvmJdwpClearWaitForEventThread(gDvm.jdwpState);
2359 }
2360
2361 while (self->suspendCount != 0) {
2362 int cc;
2363 cc = pthread_cond_wait(&gDvm.threadSuspendCountCond,
2364 &gDvm.threadSuspendCountLock);
2365 assert(cc == 0);
2366 if (self->suspendCount != 0) {
2367 /*
2368 * The condition was signaled but we're still suspended. This
2369 * can happen if the debugger lets go while a SIGQUIT thread
2370 * dump event is pending (assuming SignalCatcher was resumed for
2371 * just long enough to try to grab the thread-suspend lock).
2372 */
2373 LOGD("threadid=%d: still suspended after undo (sc=%d dc=%d s=%c)\n",
2374 self->threadId, self->suspendCount, self->dbgSuspendCount,
2375 self->isSuspended ? 'Y' : 'N');
2376 }
2377 }
2378 assert(self->suspendCount == 0 && self->dbgSuspendCount == 0);
2379 self->isSuspended = false;
2380 LOG_THREAD("threadid=%d: self-reviving (dbg), status=%d\n",
2381 self->threadId, self->status);
2382
2383 unlockThreadSuspendCount();
2384 }
2385
2386
2387 #ifdef HAVE_GLIBC
2388 # define NUM_FRAMES 20
2389 # include <execinfo.h>
2390 /*
2391 * glibc-only stack dump function. Requires link with "--export-dynamic".
2392 *
2393 * TODO: move this into libs/cutils and make it work for all platforms.
2394 */
printBackTrace(void)2395 static void printBackTrace(void)
2396 {
2397 void* array[NUM_FRAMES];
2398 size_t size;
2399 char** strings;
2400 size_t i;
2401
2402 size = backtrace(array, NUM_FRAMES);
2403 strings = backtrace_symbols(array, size);
2404
2405 LOGW("Obtained %zd stack frames.\n", size);
2406
2407 for (i = 0; i < size; i++)
2408 LOGW("%s\n", strings[i]);
2409
2410 free(strings);
2411 }
2412 #else
printBackTrace(void)2413 static void printBackTrace(void) {}
2414 #endif
2415
2416 /*
2417 * Dump the state of the current thread and that of another thread that
2418 * we think is wedged.
2419 */
dumpWedgedThread(Thread * thread)2420 static void dumpWedgedThread(Thread* thread)
2421 {
2422 char exePath[1024];
2423
2424 /*
2425 * The "executablepath" function in libutils is host-side only.
2426 */
2427 strcpy(exePath, "-");
2428 #ifdef HAVE_GLIBC
2429 {
2430 char proc[100];
2431 sprintf(proc, "/proc/%d/exe", getpid());
2432 int len;
2433
2434 len = readlink(proc, exePath, sizeof(exePath)-1);
2435 exePath[len] = '\0';
2436 }
2437 #endif
2438
2439 LOGW("dumping state: process %s %d\n", exePath, getpid());
2440 dvmDumpThread(dvmThreadSelf(), false);
2441 printBackTrace();
2442
2443 // dumping a running thread is risky, but could be useful
2444 dvmDumpThread(thread, true);
2445
2446
2447 // stop now and get a core dump
2448 //abort();
2449 }
2450
2451
2452 /*
2453 * Wait for another thread to see the pending suspension and stop running.
2454 * It can either suspend itself or go into a non-running state such as
2455 * VMWAIT or NATIVE in which it cannot interact with the GC.
2456 *
2457 * If we're running at a higher priority, sched_yield() may not do anything,
2458 * so we need to sleep for "long enough" to guarantee that the other
2459 * thread has a chance to finish what it's doing. Sleeping for too short
2460 * a period (e.g. less than the resolution of the sleep clock) might cause
2461 * the scheduler to return immediately, so we want to start with a
2462 * "reasonable" value and expand.
2463 *
2464 * This does not return until the other thread has stopped running.
2465 * Eventually we time out and the VM aborts.
2466 *
2467 * This does not try to detect the situation where two threads are
2468 * waiting for each other to suspend. In normal use this is part of a
2469 * suspend-all, which implies that the suspend-all lock is held, or as
2470 * part of a debugger action in which the JDWP thread is always the one
2471 * doing the suspending. (We may need to re-evaluate this now that
2472 * getThreadStackTrace is implemented as suspend-snapshot-resume.)
2473 *
2474 * TODO: track basic stats about time required to suspend VM.
2475 */
2476 #define FIRST_SLEEP (250*1000) /* 0.25s */
2477 #define MORE_SLEEP (750*1000) /* 0.75s */
waitForThreadSuspend(Thread * self,Thread * thread)2478 static void waitForThreadSuspend(Thread* self, Thread* thread)
2479 {
2480 const int kMaxRetries = 10;
2481 int spinSleepTime = FIRST_SLEEP;
2482 bool complained = false;
2483 bool needPriorityReset = false;
2484 int savedThreadPrio = -500;
2485
2486 int sleepIter = 0;
2487 int retryCount = 0;
2488 u8 startWhen = 0; // init req'd to placate gcc
2489 u8 firstStartWhen = 0;
2490
2491 while (thread->status == THREAD_RUNNING && !thread->isSuspended) {
2492 if (sleepIter == 0) { // get current time on first iteration
2493 startWhen = dvmGetRelativeTimeUsec();
2494 if (firstStartWhen == 0) // first iteration of first attempt
2495 firstStartWhen = startWhen;
2496
2497 /*
2498 * After waiting for a bit, check to see if the target thread is
2499 * running at a reduced priority. If so, bump it up temporarily
2500 * to give it more CPU time.
2501 *
2502 * getpriority() returns the "nice" value, so larger numbers
2503 * indicate lower priority.
2504 *
2505 * (Not currently changing the cgroup. Wasn't necessary in some
2506 * simple experiments.)
2507 */
2508 if (retryCount == 2) {
2509 assert(thread->systemTid != 0);
2510 errno = 0;
2511 int threadPrio = getpriority(PRIO_PROCESS, thread->systemTid);
2512 if (errno == 0 && threadPrio > 0) {
2513 const int kHigher = 0;
2514 if (setpriority(PRIO_PROCESS, thread->systemTid, kHigher) < 0)
2515 {
2516 LOGW("Couldn't raise priority on tid %d to %d\n",
2517 thread->systemTid, kHigher);
2518 } else {
2519 savedThreadPrio = threadPrio;
2520 needPriorityReset = true;
2521 LOGD("Temporarily raising priority on tid %d (%d -> %d)\n",
2522 thread->systemTid, threadPrio, kHigher);
2523 }
2524 }
2525 }
2526 }
2527
2528 #if defined (WITH_JIT)
2529 /*
2530 * If we're still waiting after the first timeout,
2531 * unchain all translations.
2532 */
2533 if (gDvmJit.pJitEntryTable && retryCount > 0) {
2534 LOGD("JIT unchain all attempt #%d",retryCount);
2535 dvmJitUnchainAll();
2536 }
2537 #endif
2538
2539 /*
2540 * Sleep briefly. This returns false if we've exceeded the total
2541 * time limit for this round of sleeping.
2542 */
2543 if (!dvmIterativeSleep(sleepIter++, spinSleepTime, startWhen)) {
2544 LOGW("threadid=%d: spin on suspend #%d threadid=%d (h=%d)\n",
2545 self->threadId, retryCount,
2546 thread->threadId, (int)thread->handle);
2547 dumpWedgedThread(thread);
2548 complained = true;
2549
2550 // keep going; could be slow due to valgrind
2551 sleepIter = 0;
2552 spinSleepTime = MORE_SLEEP;
2553
2554 if (retryCount++ == kMaxRetries) {
2555 LOGE("threadid=%d: stuck on threadid=%d, giving up\n",
2556 self->threadId, thread->threadId);
2557 dvmDumpAllThreads(false);
2558 dvmAbort();
2559 }
2560 }
2561 }
2562
2563 if (complained) {
2564 LOGW("threadid=%d: spin on suspend resolved in %lld msec\n",
2565 self->threadId,
2566 (dvmGetRelativeTimeUsec() - firstStartWhen) / 1000);
2567 //dvmDumpThread(thread, false); /* suspended, so dump is safe */
2568 }
2569 if (needPriorityReset) {
2570 if (setpriority(PRIO_PROCESS, thread->systemTid, savedThreadPrio) < 0) {
2571 LOGW("NOTE: couldn't reset priority on thread %d to %d\n",
2572 thread->systemTid, savedThreadPrio);
2573 } else {
2574 LOGV("Restored priority on %d to %d\n",
2575 thread->systemTid, savedThreadPrio);
2576 }
2577 }
2578 }
2579
2580 /*
2581 * Suspend all threads except the current one. This is used by the GC,
2582 * the debugger, and by any thread that hits a "suspend all threads"
2583 * debugger event (e.g. breakpoint or exception).
2584 *
2585 * If thread N hits a "suspend all threads" breakpoint, we don't want it
2586 * to suspend the JDWP thread. For the GC, we do, because the debugger can
2587 * create objects and even execute arbitrary code. The "why" argument
2588 * allows the caller to say why the suspension is taking place.
2589 *
2590 * This can be called when a global suspend has already happened, due to
2591 * various debugger gymnastics, so keeping an "everybody is suspended" flag
2592 * doesn't work.
2593 *
2594 * DO NOT grab any locks before calling here. We grab & release the thread
2595 * lock and suspend lock here (and we're not using recursive threads), and
2596 * we might have to self-suspend if somebody else beats us here.
2597 *
2598 * The current thread may not be attached to the VM. This can happen if
2599 * we happen to GC as the result of an allocation of a Thread object.
2600 */
dvmSuspendAllThreads(SuspendCause why)2601 void dvmSuspendAllThreads(SuspendCause why)
2602 {
2603 Thread* self = dvmThreadSelf();
2604 Thread* thread;
2605
2606 assert(why != 0);
2607
2608 /*
2609 * Start by grabbing the thread suspend lock. If we can't get it, most
2610 * likely somebody else is in the process of performing a suspend or
2611 * resume, so lockThreadSuspend() will cause us to self-suspend.
2612 *
2613 * We keep the lock until all other threads are suspended.
2614 */
2615 lockThreadSuspend("susp-all", why);
2616
2617 LOG_THREAD("threadid=%d: SuspendAll starting\n", self->threadId);
2618
2619 /*
2620 * This is possible if the current thread was in VMWAIT mode when a
2621 * suspend-all happened, and then decided to do its own suspend-all.
2622 * This can happen when a couple of threads have simultaneous events
2623 * of interest to the debugger.
2624 */
2625 //assert(self->suspendCount == 0);
2626
2627 /*
2628 * Increment everybody's suspend count (except our own).
2629 */
2630 dvmLockThreadList(self);
2631
2632 lockThreadSuspendCount();
2633 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2634 if (thread == self)
2635 continue;
2636
2637 /* debugger events don't suspend JDWP thread */
2638 if ((why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT) &&
2639 thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState))
2640 continue;
2641
2642 dvmAddToThreadSuspendCount(&thread->suspendCount, 1);
2643 if (why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT)
2644 thread->dbgSuspendCount++;
2645 }
2646 unlockThreadSuspendCount();
2647
2648 /*
2649 * Wait for everybody in THREAD_RUNNING state to stop. Other states
2650 * indicate the code is either running natively or sleeping quietly.
2651 * Any attempt to transition back to THREAD_RUNNING will cause a check
2652 * for suspension, so it should be impossible for anything to execute
2653 * interpreted code or modify objects (assuming native code plays nicely).
2654 *
2655 * It's also okay if the thread transitions to a non-RUNNING state.
2656 *
2657 * Note we released the threadSuspendCountLock before getting here,
2658 * so if another thread is fiddling with its suspend count (perhaps
2659 * self-suspending for the debugger) it won't block while we're waiting
2660 * in here.
2661 */
2662 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2663 if (thread == self)
2664 continue;
2665
2666 /* debugger events don't suspend JDWP thread */
2667 if ((why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT) &&
2668 thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState))
2669 continue;
2670
2671 /* wait for the other thread to see the pending suspend */
2672 waitForThreadSuspend(self, thread);
2673
2674 LOG_THREAD("threadid=%d: threadid=%d status=%d c=%d dc=%d isSusp=%d\n",
2675 self->threadId,
2676 thread->threadId, thread->status, thread->suspendCount,
2677 thread->dbgSuspendCount, thread->isSuspended);
2678 }
2679
2680 dvmUnlockThreadList();
2681 unlockThreadSuspend();
2682
2683 LOG_THREAD("threadid=%d: SuspendAll complete\n", self->threadId);
2684 }
2685
2686 /*
2687 * Resume all threads that are currently suspended.
2688 *
2689 * The "why" must match with the previous suspend.
2690 */
dvmResumeAllThreads(SuspendCause why)2691 void dvmResumeAllThreads(SuspendCause why)
2692 {
2693 Thread* self = dvmThreadSelf();
2694 Thread* thread;
2695 int cc;
2696
2697 lockThreadSuspend("res-all", why); /* one suspend/resume at a time */
2698 LOG_THREAD("threadid=%d: ResumeAll starting\n", self->threadId);
2699
2700 /*
2701 * Decrement the suspend counts for all threads. No need for atomic
2702 * writes, since nobody should be moving until we decrement the count.
2703 * We do need to hold the thread list because of JNI attaches.
2704 */
2705 dvmLockThreadList(self);
2706 lockThreadSuspendCount();
2707 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2708 if (thread == self)
2709 continue;
2710
2711 /* debugger events don't suspend JDWP thread */
2712 if ((why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT) &&
2713 thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState))
2714 {
2715 continue;
2716 }
2717
2718 if (thread->suspendCount > 0) {
2719 dvmAddToThreadSuspendCount(&thread->suspendCount, -1);
2720 if (why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT)
2721 thread->dbgSuspendCount--;
2722 } else {
2723 LOG_THREAD("threadid=%d: suspendCount already zero\n",
2724 thread->threadId);
2725 }
2726 }
2727 unlockThreadSuspendCount();
2728 dvmUnlockThreadList();
2729
2730 /*
2731 * In some ways it makes sense to continue to hold the thread-suspend
2732 * lock while we issue the wakeup broadcast. It allows us to complete
2733 * one operation before moving on to the next, which simplifies the
2734 * thread activity debug traces.
2735 *
2736 * This approach caused us some difficulty under Linux, because the
2737 * condition variable broadcast not only made the threads runnable,
2738 * but actually caused them to execute, and it was a while before
2739 * the thread performing the wakeup had an opportunity to release the
2740 * thread-suspend lock.
2741 *
2742 * This is a problem because, when a thread tries to acquire that
2743 * lock, it times out after 3 seconds. If at some point the thread
2744 * is told to suspend, the clock resets; but since the VM is still
2745 * theoretically mid-resume, there's no suspend pending. If, for
2746 * example, the GC was waking threads up while the SIGQUIT handler
2747 * was trying to acquire the lock, we would occasionally time out on
2748 * a busy system and SignalCatcher would abort.
2749 *
2750 * We now perform the unlock before the wakeup broadcast. The next
2751 * suspend can't actually start until the broadcast completes and
2752 * returns, because we're holding the thread-suspend-count lock, but the
2753 * suspending thread is now able to make progress and we avoid the abort.
2754 *
2755 * (Technically there is a narrow window between when we release
2756 * the thread-suspend lock and grab the thread-suspend-count lock.
2757 * This could cause us to send a broadcast to threads with nonzero
2758 * suspend counts, but this is expected and they'll all just fall
2759 * right back to sleep. It's probably safe to grab the suspend-count
2760 * lock before releasing thread-suspend, since we're still following
2761 * the correct order of acquisition, but it feels weird.)
2762 */
2763
2764 LOG_THREAD("threadid=%d: ResumeAll waking others\n", self->threadId);
2765 unlockThreadSuspend();
2766
2767 /*
2768 * Broadcast a notification to all suspended threads, some or all of
2769 * which may choose to wake up. No need to wait for them.
2770 */
2771 lockThreadSuspendCount();
2772 cc = pthread_cond_broadcast(&gDvm.threadSuspendCountCond);
2773 assert(cc == 0);
2774 unlockThreadSuspendCount();
2775
2776 LOG_THREAD("threadid=%d: ResumeAll complete\n", self->threadId);
2777 }
2778
2779 /*
2780 * Undo any debugger suspensions. This is called when the debugger
2781 * disconnects.
2782 */
dvmUndoDebuggerSuspensions(void)2783 void dvmUndoDebuggerSuspensions(void)
2784 {
2785 Thread* self = dvmThreadSelf();
2786 Thread* thread;
2787 int cc;
2788
2789 lockThreadSuspend("undo", SUSPEND_FOR_DEBUG);
2790 LOG_THREAD("threadid=%d: UndoDebuggerSusp starting\n", self->threadId);
2791
2792 /*
2793 * Decrement the suspend counts for all threads. No need for atomic
2794 * writes, since nobody should be moving until we decrement the count.
2795 * We do need to hold the thread list because of JNI attaches.
2796 */
2797 dvmLockThreadList(self);
2798 lockThreadSuspendCount();
2799 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2800 if (thread == self)
2801 continue;
2802
2803 /* debugger events don't suspend JDWP thread */
2804 if (thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState)) {
2805 assert(thread->dbgSuspendCount == 0);
2806 continue;
2807 }
2808
2809 assert(thread->suspendCount >= thread->dbgSuspendCount);
2810 dvmAddToThreadSuspendCount(&thread->suspendCount,
2811 -thread->dbgSuspendCount);
2812 thread->dbgSuspendCount = 0;
2813 }
2814 unlockThreadSuspendCount();
2815 dvmUnlockThreadList();
2816
2817 /*
2818 * Broadcast a notification to all suspended threads, some or all of
2819 * which may choose to wake up. No need to wait for them.
2820 */
2821 lockThreadSuspendCount();
2822 cc = pthread_cond_broadcast(&gDvm.threadSuspendCountCond);
2823 assert(cc == 0);
2824 unlockThreadSuspendCount();
2825
2826 unlockThreadSuspend();
2827
2828 LOG_THREAD("threadid=%d: UndoDebuggerSusp complete\n", self->threadId);
2829 }
2830
2831 /*
2832 * Determine if a thread is suspended.
2833 *
2834 * As with all operations on foreign threads, the caller should hold
2835 * the thread list lock before calling.
2836 */
dvmIsSuspended(Thread * thread)2837 bool dvmIsSuspended(Thread* thread)
2838 {
2839 /*
2840 * The thread could be:
2841 * (1) Running happily. status is RUNNING, isSuspended is false,
2842 * suspendCount is zero. Return "false".
2843 * (2) Pending suspend. status is RUNNING, isSuspended is false,
2844 * suspendCount is nonzero. Return "false".
2845 * (3) Suspended. suspendCount is nonzero, and either (status is
2846 * RUNNING and isSuspended is true) OR (status is !RUNNING).
2847 * Return "true".
2848 * (4) Waking up. suspendCount is zero, status is RUNNING and
2849 * isSuspended is true. Return "false" (since it could change
2850 * out from under us, unless we hold suspendCountLock).
2851 */
2852
2853 return (thread->suspendCount != 0 &&
2854 ((thread->status == THREAD_RUNNING && thread->isSuspended) ||
2855 (thread->status != THREAD_RUNNING)));
2856 }
2857
2858 /*
2859 * Wait until another thread self-suspends. This is specifically for
2860 * synchronization between the JDWP thread and a thread that has decided
2861 * to suspend itself after sending an event to the debugger.
2862 *
2863 * Threads that encounter "suspend all" events work as well -- the thread
2864 * in question suspends everybody else and then itself.
2865 *
2866 * We can't hold a thread lock here or in the caller, because we could
2867 * get here just before the to-be-waited-for-thread issues a "suspend all".
2868 * There's an opportunity for badness if the thread we're waiting for exits
2869 * and gets cleaned up, but since the thread in question is processing a
2870 * debugger event, that's not really a possibility. (To avoid deadlock,
2871 * it's important that we not be in THREAD_RUNNING while we wait.)
2872 */
dvmWaitForSuspend(Thread * thread)2873 void dvmWaitForSuspend(Thread* thread)
2874 {
2875 Thread* self = dvmThreadSelf();
2876
2877 LOG_THREAD("threadid=%d: waiting for threadid=%d to sleep\n",
2878 self->threadId, thread->threadId);
2879
2880 assert(thread->handle != dvmJdwpGetDebugThread(gDvm.jdwpState));
2881 assert(thread != self);
2882 assert(self->status != THREAD_RUNNING);
2883
2884 waitForThreadSuspend(self, thread);
2885
2886 LOG_THREAD("threadid=%d: threadid=%d is now asleep\n",
2887 self->threadId, thread->threadId);
2888 }
2889
2890 /*
2891 * Check to see if we need to suspend ourselves. If so, go to sleep on
2892 * a condition variable.
2893 *
2894 * Takes "self" as an argument as an optimization. Pass in NULL to have
2895 * it do the lookup.
2896 *
2897 * Returns "true" if we suspended ourselves.
2898 */
dvmCheckSuspendPending(Thread * self)2899 bool dvmCheckSuspendPending(Thread* self)
2900 {
2901 bool didSuspend;
2902
2903 if (self == NULL)
2904 self = dvmThreadSelf();
2905
2906 /* fast path: if count is zero, bail immediately */
2907 if (self->suspendCount == 0)
2908 return false;
2909
2910 lockThreadSuspendCount(); /* grab gDvm.threadSuspendCountLock */
2911
2912 assert(self->suspendCount >= 0); /* XXX: valid? useful? */
2913
2914 didSuspend = (self->suspendCount != 0);
2915 self->isSuspended = true;
2916 LOG_THREAD("threadid=%d: self-suspending\n", self->threadId);
2917 while (self->suspendCount != 0) {
2918 /* wait for wakeup signal; releases lock */
2919 int cc;
2920 cc = pthread_cond_wait(&gDvm.threadSuspendCountCond,
2921 &gDvm.threadSuspendCountLock);
2922 assert(cc == 0);
2923 }
2924 assert(self->suspendCount == 0 && self->dbgSuspendCount == 0);
2925 self->isSuspended = false;
2926 LOG_THREAD("threadid=%d: self-reviving, status=%d\n",
2927 self->threadId, self->status);
2928
2929 unlockThreadSuspendCount();
2930
2931 return didSuspend;
2932 }
2933
2934 /*
2935 * Update our status.
2936 *
2937 * The "self" argument, which may be NULL, is accepted as an optimization.
2938 *
2939 * Returns the old status.
2940 */
dvmChangeStatus(Thread * self,ThreadStatus newStatus)2941 ThreadStatus dvmChangeStatus(Thread* self, ThreadStatus newStatus)
2942 {
2943 ThreadStatus oldStatus;
2944
2945 if (self == NULL)
2946 self = dvmThreadSelf();
2947
2948 LOGVV("threadid=%d: (status %d -> %d)\n",
2949 self->threadId, self->status, newStatus);
2950
2951 oldStatus = self->status;
2952
2953 if (newStatus == THREAD_RUNNING) {
2954 /*
2955 * Change our status to THREAD_RUNNING. The transition requires
2956 * that we check for pending suspension, because the VM considers
2957 * us to be "asleep" in all other states.
2958 *
2959 * We need to do the "suspend pending" check FIRST, because it grabs
2960 * a lock that could be held by something that wants us to suspend.
2961 * If we're in RUNNING it will wait for us, and we'll be waiting
2962 * for the lock it holds.
2963 */
2964 assert(self->status != THREAD_RUNNING);
2965
2966 dvmCheckSuspendPending(self);
2967 self->status = THREAD_RUNNING;
2968 } else {
2969 /*
2970 * Change from one state to another, neither of which is
2971 * THREAD_RUNNING. This is most common during system or thread
2972 * initialization.
2973 */
2974 self->status = newStatus;
2975 }
2976
2977 return oldStatus;
2978 }
2979
2980 /*
2981 * Get a statically defined thread group from a field in the ThreadGroup
2982 * Class object. Expected arguments are "mMain" and "mSystem".
2983 */
getStaticThreadGroup(const char * fieldName)2984 static Object* getStaticThreadGroup(const char* fieldName)
2985 {
2986 StaticField* groupField;
2987 Object* groupObj;
2988
2989 groupField = dvmFindStaticField(gDvm.classJavaLangThreadGroup,
2990 fieldName, "Ljava/lang/ThreadGroup;");
2991 if (groupField == NULL) {
2992 LOGE("java.lang.ThreadGroup does not have an '%s' field\n", fieldName);
2993 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;", NULL);
2994 return NULL;
2995 }
2996 groupObj = dvmGetStaticFieldObject(groupField);
2997 if (groupObj == NULL) {
2998 LOGE("java.lang.ThreadGroup.%s not initialized\n", fieldName);
2999 dvmThrowException("Ljava/lang/InternalError;", NULL);
3000 return NULL;
3001 }
3002
3003 return groupObj;
3004 }
dvmGetSystemThreadGroup(void)3005 Object* dvmGetSystemThreadGroup(void)
3006 {
3007 return getStaticThreadGroup("mSystem");
3008 }
dvmGetMainThreadGroup(void)3009 Object* dvmGetMainThreadGroup(void)
3010 {
3011 return getStaticThreadGroup("mMain");
3012 }
3013
3014 /*
3015 * Given a VMThread object, return the associated Thread*.
3016 *
3017 * NOTE: if the thread detaches, the struct Thread will disappear, and
3018 * we will be touching invalid data. For safety, lock the thread list
3019 * before calling this.
3020 */
dvmGetThreadFromThreadObject(Object * vmThreadObj)3021 Thread* dvmGetThreadFromThreadObject(Object* vmThreadObj)
3022 {
3023 int vmData;
3024
3025 vmData = dvmGetFieldInt(vmThreadObj, gDvm.offJavaLangVMThread_vmData);
3026
3027 if (false) {
3028 Thread* thread = gDvm.threadList;
3029 while (thread != NULL) {
3030 if ((Thread*)vmData == thread)
3031 break;
3032
3033 thread = thread->next;
3034 }
3035
3036 if (thread == NULL) {
3037 LOGW("WARNING: vmThreadObj=%p has thread=%p, not in thread list\n",
3038 vmThreadObj, (Thread*)vmData);
3039 vmData = 0;
3040 }
3041 }
3042
3043 return (Thread*) vmData;
3044 }
3045
3046
3047 /*
3048 * Conversion map for "nice" values.
3049 *
3050 * We use Android thread priority constants to be consistent with the rest
3051 * of the system. In some cases adjacent entries may overlap.
3052 */
3053 static const int kNiceValues[10] = {
3054 ANDROID_PRIORITY_LOWEST, /* 1 (MIN_PRIORITY) */
3055 ANDROID_PRIORITY_BACKGROUND + 6,
3056 ANDROID_PRIORITY_BACKGROUND + 3,
3057 ANDROID_PRIORITY_BACKGROUND,
3058 ANDROID_PRIORITY_NORMAL, /* 5 (NORM_PRIORITY) */
3059 ANDROID_PRIORITY_NORMAL - 2,
3060 ANDROID_PRIORITY_NORMAL - 4,
3061 ANDROID_PRIORITY_URGENT_DISPLAY + 3,
3062 ANDROID_PRIORITY_URGENT_DISPLAY + 2,
3063 ANDROID_PRIORITY_URGENT_DISPLAY /* 10 (MAX_PRIORITY) */
3064 };
3065
3066 /*
3067 * Change the priority of a system thread to match that of the Thread object.
3068 *
3069 * We map a priority value from 1-10 to Linux "nice" values, where lower
3070 * numbers indicate higher priority.
3071 */
dvmChangeThreadPriority(Thread * thread,int newPriority)3072 void dvmChangeThreadPriority(Thread* thread, int newPriority)
3073 {
3074 pid_t pid = thread->systemTid;
3075 int newNice;
3076
3077 if (newPriority < 1 || newPriority > 10) {
3078 LOGW("bad priority %d\n", newPriority);
3079 newPriority = 5;
3080 }
3081 newNice = kNiceValues[newPriority-1];
3082
3083 if (newNice >= ANDROID_PRIORITY_BACKGROUND) {
3084 set_sched_policy(dvmGetSysThreadId(), SP_BACKGROUND);
3085 } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
3086 set_sched_policy(dvmGetSysThreadId(), SP_FOREGROUND);
3087 }
3088
3089 if (setpriority(PRIO_PROCESS, pid, newNice) != 0) {
3090 char* str = dvmGetThreadName(thread);
3091 LOGI("setPriority(%d) '%s' to prio=%d(n=%d) failed: %s\n",
3092 pid, str, newPriority, newNice, strerror(errno));
3093 free(str);
3094 } else {
3095 LOGV("setPriority(%d) to prio=%d(n=%d)\n",
3096 pid, newPriority, newNice);
3097 }
3098 }
3099
3100 /*
3101 * Get the thread priority for the current thread by querying the system.
3102 * This is useful when attaching a thread through JNI.
3103 *
3104 * Returns a value from 1 to 10 (compatible with java.lang.Thread values).
3105 */
getThreadPriorityFromSystem(void)3106 static int getThreadPriorityFromSystem(void)
3107 {
3108 int i, sysprio, jprio;
3109
3110 errno = 0;
3111 sysprio = getpriority(PRIO_PROCESS, 0);
3112 if (sysprio == -1 && errno != 0) {
3113 LOGW("getpriority() failed: %s\n", strerror(errno));
3114 return THREAD_NORM_PRIORITY;
3115 }
3116
3117 jprio = THREAD_MIN_PRIORITY;
3118 for (i = 0; i < NELEM(kNiceValues); i++) {
3119 if (sysprio >= kNiceValues[i])
3120 break;
3121 jprio++;
3122 }
3123 if (jprio > THREAD_MAX_PRIORITY)
3124 jprio = THREAD_MAX_PRIORITY;
3125
3126 return jprio;
3127 }
3128
3129
3130 /*
3131 * Return true if the thread is on gDvm.threadList.
3132 * Caller should not hold gDvm.threadListLock.
3133 */
dvmIsOnThreadList(const Thread * thread)3134 bool dvmIsOnThreadList(const Thread* thread)
3135 {
3136 bool ret = false;
3137
3138 dvmLockThreadList(NULL);
3139 if (thread == gDvm.threadList) {
3140 ret = true;
3141 } else {
3142 ret = thread->prev != NULL || thread->next != NULL;
3143 }
3144 dvmUnlockThreadList();
3145
3146 return ret;
3147 }
3148
3149 /*
3150 * Dump a thread to the log file -- just calls dvmDumpThreadEx() with an
3151 * output target.
3152 */
dvmDumpThread(Thread * thread,bool isRunning)3153 void dvmDumpThread(Thread* thread, bool isRunning)
3154 {
3155 DebugOutputTarget target;
3156
3157 dvmCreateLogOutputTarget(&target, ANDROID_LOG_INFO, LOG_TAG);
3158 dvmDumpThreadEx(&target, thread, isRunning);
3159 }
3160
3161 /*
3162 * Try to get the scheduler group.
3163 *
3164 * The data from /proc/<pid>/cgroup looks like:
3165 * 2:cpu:/bg_non_interactive
3166 *
3167 * We return the part after the "/", which will be an empty string for
3168 * the default cgroup. If the string is longer than "bufLen", the string
3169 * will be truncated.
3170 */
getSchedulerGroup(Thread * thread,char * buf,size_t bufLen)3171 static bool getSchedulerGroup(Thread* thread, char* buf, size_t bufLen)
3172 {
3173 #ifdef HAVE_ANDROID_OS
3174 char pathBuf[32];
3175 char readBuf[256];
3176 ssize_t count;
3177 int fd;
3178
3179 snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", thread->systemTid);
3180 if ((fd = open(pathBuf, O_RDONLY)) < 0) {
3181 LOGV("open(%s) failed: %s\n", pathBuf, strerror(errno));
3182 return false;
3183 }
3184
3185 count = read(fd, readBuf, sizeof(readBuf));
3186 if (count <= 0) {
3187 LOGV("read(%s) failed (%d): %s\n",
3188 pathBuf, (int) count, strerror(errno));
3189 close(fd);
3190 return false;
3191 }
3192 close(fd);
3193
3194 readBuf[--count] = '\0'; /* remove the '\n', now count==strlen */
3195
3196 char* cp = strchr(readBuf, '/');
3197 if (cp == NULL) {
3198 readBuf[sizeof(readBuf)-1] = '\0';
3199 LOGV("no '/' in '%s' (file=%s count=%d)\n",
3200 readBuf, pathBuf, (int) count);
3201 return false;
3202 }
3203
3204 memcpy(buf, cp+1, count); /* count-1 for cp+1, count+1 for NUL */
3205 return true;
3206 #else
3207 return false;
3208 #endif
3209 }
3210
3211 /*
3212 * Print information about the specified thread.
3213 *
3214 * Works best when the thread in question is "self" or has been suspended.
3215 * When dumping a separate thread that's still running, set "isRunning" to
3216 * use a more cautious thread dump function.
3217 */
dvmDumpThreadEx(const DebugOutputTarget * target,Thread * thread,bool isRunning)3218 void dvmDumpThreadEx(const DebugOutputTarget* target, Thread* thread,
3219 bool isRunning)
3220 {
3221 /* tied to ThreadStatus enum */
3222 static const char* kStatusNames[] = {
3223 "ZOMBIE", "RUNNABLE", "TIMED_WAIT", "MONITOR", "WAIT",
3224 "INITIALIZING", "STARTING", "NATIVE", "VMWAIT"
3225 };
3226 Object* threadObj;
3227 Object* groupObj;
3228 StringObject* nameStr;
3229 char* threadName = NULL;
3230 char* groupName = NULL;
3231 char schedulerGroupBuf[32];
3232 bool isDaemon;
3233 int priority; // java.lang.Thread priority
3234 int policy; // pthread policy
3235 struct sched_param sp; // pthread scheduling parameters
3236
3237 threadObj = thread->threadObj;
3238 if (threadObj == NULL) {
3239 LOGW("Can't dump thread %d: threadObj not set\n", thread->threadId);
3240 return;
3241 }
3242 nameStr = (StringObject*) dvmGetFieldObject(threadObj,
3243 gDvm.offJavaLangThread_name);
3244 threadName = dvmCreateCstrFromString(nameStr);
3245
3246 priority = dvmGetFieldInt(threadObj, gDvm.offJavaLangThread_priority);
3247 isDaemon = dvmGetFieldBoolean(threadObj, gDvm.offJavaLangThread_daemon);
3248
3249 if (pthread_getschedparam(pthread_self(), &policy, &sp) != 0) {
3250 LOGW("Warning: pthread_getschedparam failed\n");
3251 policy = -1;
3252 sp.sched_priority = -1;
3253 }
3254 if (!getSchedulerGroup(thread, schedulerGroupBuf,sizeof(schedulerGroupBuf)))
3255 {
3256 strcpy(schedulerGroupBuf, "unknown");
3257 } else if (schedulerGroupBuf[0] == '\0') {
3258 strcpy(schedulerGroupBuf, "default");
3259 }
3260
3261 /* a null value for group is not expected, but deal with it anyway */
3262 groupObj = (Object*) dvmGetFieldObject(threadObj,
3263 gDvm.offJavaLangThread_group);
3264 if (groupObj != NULL) {
3265 int offset = dvmFindFieldOffset(gDvm.classJavaLangThreadGroup,
3266 "name", "Ljava/lang/String;");
3267 if (offset < 0) {
3268 LOGW("Unable to find 'name' field in ThreadGroup\n");
3269 } else {
3270 nameStr = (StringObject*) dvmGetFieldObject(groupObj, offset);
3271 groupName = dvmCreateCstrFromString(nameStr);
3272 }
3273 }
3274 if (groupName == NULL)
3275 groupName = strdup("(BOGUS GROUP)");
3276
3277 assert(thread->status < NELEM(kStatusNames));
3278 dvmPrintDebugMessage(target,
3279 "\"%s\"%s prio=%d tid=%d %s\n",
3280 threadName, isDaemon ? " daemon" : "",
3281 priority, thread->threadId, kStatusNames[thread->status]);
3282 dvmPrintDebugMessage(target,
3283 " | group=\"%s\" sCount=%d dsCount=%d s=%c obj=%p self=%p\n",
3284 groupName, thread->suspendCount, thread->dbgSuspendCount,
3285 thread->isSuspended ? 'Y' : 'N', thread->threadObj, thread);
3286 dvmPrintDebugMessage(target,
3287 " | sysTid=%d nice=%d sched=%d/%d cgrp=%s handle=%d\n",
3288 thread->systemTid, getpriority(PRIO_PROCESS, thread->systemTid),
3289 policy, sp.sched_priority, schedulerGroupBuf, (int)thread->handle);
3290
3291 #ifdef WITH_MONITOR_TRACKING
3292 if (!isRunning) {
3293 LockedObjectData* lod = thread->pLockedObjects;
3294 if (lod != NULL)
3295 dvmPrintDebugMessage(target, " | monitors held:\n");
3296 else
3297 dvmPrintDebugMessage(target, " | monitors held: <none>\n");
3298 while (lod != NULL) {
3299 dvmPrintDebugMessage(target, " > %p[%d] (%s)\n",
3300 lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
3301 lod = lod->next;
3302 }
3303 }
3304 #endif
3305
3306 if (isRunning)
3307 dvmDumpRunningThreadStack(target, thread);
3308 else
3309 dvmDumpThreadStack(target, thread);
3310
3311 free(threadName);
3312 free(groupName);
3313
3314 }
3315
3316 /*
3317 * Get the name of a thread.
3318 *
3319 * For correctness, the caller should hold the thread list lock to ensure
3320 * that the thread doesn't go away mid-call.
3321 *
3322 * Returns a newly-allocated string, or NULL if the Thread doesn't have a name.
3323 */
dvmGetThreadName(Thread * thread)3324 char* dvmGetThreadName(Thread* thread)
3325 {
3326 StringObject* nameObj;
3327
3328 if (thread->threadObj == NULL) {
3329 LOGW("threadObj is NULL, name not available\n");
3330 return strdup("-unknown-");
3331 }
3332
3333 nameObj = (StringObject*)
3334 dvmGetFieldObject(thread->threadObj, gDvm.offJavaLangThread_name);
3335 return dvmCreateCstrFromString(nameObj);
3336 }
3337
3338 /*
3339 * Dump all threads to the log file -- just calls dvmDumpAllThreadsEx() with
3340 * an output target.
3341 */
dvmDumpAllThreads(bool grabLock)3342 void dvmDumpAllThreads(bool grabLock)
3343 {
3344 DebugOutputTarget target;
3345
3346 dvmCreateLogOutputTarget(&target, ANDROID_LOG_INFO, LOG_TAG);
3347 dvmDumpAllThreadsEx(&target, grabLock);
3348 }
3349
3350 /*
3351 * Print information about all known threads. Assumes they have been
3352 * suspended (or are in a non-interpreting state, e.g. WAIT or NATIVE).
3353 *
3354 * If "grabLock" is true, we grab the thread lock list. This is important
3355 * to do unless the caller already holds the lock.
3356 */
dvmDumpAllThreadsEx(const DebugOutputTarget * target,bool grabLock)3357 void dvmDumpAllThreadsEx(const DebugOutputTarget* target, bool grabLock)
3358 {
3359 Thread* thread;
3360
3361 dvmPrintDebugMessage(target, "DALVIK THREADS:\n");
3362
3363 if (grabLock)
3364 dvmLockThreadList(dvmThreadSelf());
3365
3366 thread = gDvm.threadList;
3367 while (thread != NULL) {
3368 dvmDumpThreadEx(target, thread, false);
3369
3370 /* verify link */
3371 assert(thread->next == NULL || thread->next->prev == thread);
3372
3373 thread = thread->next;
3374 }
3375
3376 if (grabLock)
3377 dvmUnlockThreadList();
3378 }
3379
3380 #ifdef WITH_MONITOR_TRACKING
3381 /*
3382 * Count up the #of locked objects in the current thread.
3383 */
getThreadObjectCount(const Thread * self)3384 static int getThreadObjectCount(const Thread* self)
3385 {
3386 LockedObjectData* lod;
3387 int count = 0;
3388
3389 lod = self->pLockedObjects;
3390 while (lod != NULL) {
3391 count++;
3392 lod = lod->next;
3393 }
3394 return count;
3395 }
3396
3397 /*
3398 * Add the object to the thread's locked object list if it doesn't already
3399 * exist. The most recently added object is the most likely to be released
3400 * next, so we insert at the head of the list.
3401 *
3402 * If it already exists, we increase the recursive lock count.
3403 *
3404 * The object's lock may be thin or fat.
3405 */
dvmAddToMonitorList(Thread * self,Object * obj,bool withTrace)3406 void dvmAddToMonitorList(Thread* self, Object* obj, bool withTrace)
3407 {
3408 LockedObjectData* newLod;
3409 LockedObjectData* lod;
3410 int* trace;
3411 int depth;
3412
3413 lod = self->pLockedObjects;
3414 while (lod != NULL) {
3415 if (lod->obj == obj) {
3416 lod->recursionCount++;
3417 LOGV("+++ +recursive lock %p -> %d\n", obj, lod->recursionCount);
3418 return;
3419 }
3420 lod = lod->next;
3421 }
3422
3423 newLod = (LockedObjectData*) calloc(1, sizeof(LockedObjectData));
3424 if (newLod == NULL) {
3425 LOGE("malloc failed on %d bytes\n", sizeof(LockedObjectData));
3426 return;
3427 }
3428 newLod->obj = obj;
3429 newLod->recursionCount = 0;
3430
3431 if (withTrace) {
3432 trace = dvmFillInStackTraceRaw(self, &depth);
3433 newLod->rawStackTrace = trace;
3434 newLod->stackDepth = depth;
3435 }
3436
3437 newLod->next = self->pLockedObjects;
3438 self->pLockedObjects = newLod;
3439
3440 LOGV("+++ threadid=%d: added %p, now %d\n",
3441 self->threadId, newLod, getThreadObjectCount(self));
3442 }
3443
3444 /*
3445 * Remove the object from the thread's locked object list. If the entry
3446 * has a nonzero recursion count, we just decrement the count instead.
3447 */
dvmRemoveFromMonitorList(Thread * self,Object * obj)3448 void dvmRemoveFromMonitorList(Thread* self, Object* obj)
3449 {
3450 LockedObjectData* lod;
3451 LockedObjectData* prevLod;
3452
3453 lod = self->pLockedObjects;
3454 prevLod = NULL;
3455 while (lod != NULL) {
3456 if (lod->obj == obj) {
3457 if (lod->recursionCount > 0) {
3458 lod->recursionCount--;
3459 LOGV("+++ -recursive lock %p -> %d\n",
3460 obj, lod->recursionCount);
3461 return;
3462 } else {
3463 break;
3464 }
3465 }
3466 prevLod = lod;
3467 lod = lod->next;
3468 }
3469
3470 if (lod == NULL) {
3471 LOGW("BUG: object %p not found in thread's lock list\n", obj);
3472 return;
3473 }
3474 if (prevLod == NULL) {
3475 /* first item in list */
3476 assert(self->pLockedObjects == lod);
3477 self->pLockedObjects = lod->next;
3478 } else {
3479 /* middle/end of list */
3480 prevLod->next = lod->next;
3481 }
3482
3483 LOGV("+++ threadid=%d: removed %p, now %d\n",
3484 self->threadId, lod, getThreadObjectCount(self));
3485 free(lod->rawStackTrace);
3486 free(lod);
3487 }
3488
3489 /*
3490 * If the specified object is already in the thread's locked object list,
3491 * return the LockedObjectData struct. Otherwise return NULL.
3492 */
dvmFindInMonitorList(const Thread * self,const Object * obj)3493 LockedObjectData* dvmFindInMonitorList(const Thread* self, const Object* obj)
3494 {
3495 LockedObjectData* lod;
3496
3497 lod = self->pLockedObjects;
3498 while (lod != NULL) {
3499 if (lod->obj == obj)
3500 return lod;
3501 lod = lod->next;
3502 }
3503 return NULL;
3504 }
3505 #endif /*WITH_MONITOR_TRACKING*/
3506
3507
3508 /*
3509 * GC helper functions
3510 */
3511
3512 /*
3513 * Add the contents of the registers from the interpreted call stack.
3514 */
gcScanInterpStackReferences(Thread * thread)3515 static void gcScanInterpStackReferences(Thread *thread)
3516 {
3517 const u4 *framePtr;
3518 #if WITH_EXTRA_GC_CHECKS > 1
3519 bool first = true;
3520 #endif
3521
3522 framePtr = (const u4 *)thread->curFrame;
3523 while (framePtr != NULL) {
3524 const StackSaveArea *saveArea;
3525 const Method *method;
3526
3527 saveArea = SAVEAREA_FROM_FP(framePtr);
3528 method = saveArea->method;
3529 if (method != NULL && !dvmIsNativeMethod(method)) {
3530 #ifdef COUNT_PRECISE_METHODS
3531 /* the GC is running, so no lock required */
3532 if (dvmPointerSetAddEntry(gDvm.preciseMethods, method))
3533 LOGI("PGC: added %s.%s %p\n",
3534 method->clazz->descriptor, method->name, method);
3535 #endif
3536 #if WITH_EXTRA_GC_CHECKS > 1
3537 /*
3538 * May also want to enable the memset() in the "invokeMethod"
3539 * goto target in the portable interpreter. That sets the stack
3540 * to a pattern that makes referring to uninitialized data
3541 * very obvious.
3542 */
3543
3544 if (first) {
3545 /*
3546 * First frame, isn't native, check the "alternate" saved PC
3547 * as a sanity check.
3548 *
3549 * It seems like we could check the second frame if the first
3550 * is native, since the PCs should be the same. It turns out
3551 * this doesn't always work. The problem is that we could
3552 * have calls in the sequence:
3553 * interp method #2
3554 * native method
3555 * interp method #1
3556 *
3557 * and then GC while in the native method after returning
3558 * from interp method #2. The currentPc on the stack is
3559 * for interp method #1, but thread->currentPc2 is still
3560 * set for the last thing interp method #2 did.
3561 *
3562 * This can also happen in normal execution:
3563 * - sget-object on not-yet-loaded class
3564 * - class init updates currentPc2
3565 * - static field init is handled by parsing annotations;
3566 * static String init requires creation of a String object,
3567 * which can cause a GC
3568 *
3569 * Essentially, any pattern that involves executing
3570 * interpreted code and then causes an allocation without
3571 * executing instructions in the original method will hit
3572 * this. These are rare enough that the test still has
3573 * some value.
3574 */
3575 if (saveArea->xtra.currentPc != thread->currentPc2) {
3576 LOGW("PGC: savedPC(%p) != current PC(%p), %s.%s ins=%p\n",
3577 saveArea->xtra.currentPc, thread->currentPc2,
3578 method->clazz->descriptor, method->name, method->insns);
3579 if (saveArea->xtra.currentPc != NULL)
3580 LOGE(" pc inst = 0x%04x\n", *saveArea->xtra.currentPc);
3581 if (thread->currentPc2 != NULL)
3582 LOGE(" pc2 inst = 0x%04x\n", *thread->currentPc2);
3583 dvmDumpThread(thread, false);
3584 }
3585 } else {
3586 /*
3587 * It's unusual, but not impossible, for a non-first frame
3588 * to be at something other than a method invocation. For
3589 * example, if we do a new-instance on a nonexistent class,
3590 * we'll have a lot of class loader activity on the stack
3591 * above the frame with the "new" operation. Could also
3592 * happen while we initialize a Throwable when an instruction
3593 * fails.
3594 *
3595 * So there's not much we can do here to verify the PC,
3596 * except to verify that it's a GC point.
3597 */
3598 }
3599 assert(saveArea->xtra.currentPc != NULL);
3600 #endif
3601
3602 const RegisterMap* pMap;
3603 const u1* regVector;
3604 int i;
3605
3606 Method* nonConstMethod = (Method*) method; // quiet gcc
3607 pMap = dvmGetExpandedRegisterMap(nonConstMethod);
3608 if (pMap != NULL) {
3609 /* found map, get registers for this address */
3610 int addr = saveArea->xtra.currentPc - method->insns;
3611 regVector = dvmRegisterMapGetLine(pMap, addr);
3612 if (regVector == NULL) {
3613 LOGW("PGC: map but no entry for %s.%s addr=0x%04x\n",
3614 method->clazz->descriptor, method->name, addr);
3615 } else {
3616 LOGV("PGC: found map for %s.%s 0x%04x (t=%d)\n",
3617 method->clazz->descriptor, method->name, addr,
3618 thread->threadId);
3619 }
3620 } else {
3621 /*
3622 * No map found. If precise GC is disabled this is
3623 * expected -- we don't create pointers to the map data even
3624 * if it's present -- but if it's enabled it means we're
3625 * unexpectedly falling back on a conservative scan, so it's
3626 * worth yelling a little.
3627 */
3628 if (gDvm.preciseGc) {
3629 LOGVV("PGC: no map for %s.%s\n",
3630 method->clazz->descriptor, method->name);
3631 }
3632 regVector = NULL;
3633 }
3634
3635 if (regVector == NULL) {
3636 /* conservative scan */
3637 for (i = method->registersSize - 1; i >= 0; i--) {
3638 u4 rval = *framePtr++;
3639 if (rval != 0 && (rval & 0x3) == 0) {
3640 dvmMarkIfObject((Object *)rval);
3641 }
3642 }
3643 } else {
3644 /*
3645 * Precise scan. v0 is at the lowest address on the
3646 * interpreted stack, and is the first bit in the register
3647 * vector, so we can walk through the register map and
3648 * memory in the same direction.
3649 *
3650 * A '1' bit indicates a live reference.
3651 */
3652 u2 bits = 1 << 1;
3653 for (i = method->registersSize - 1; i >= 0; i--) {
3654 u4 rval = *framePtr++;
3655
3656 bits >>= 1;
3657 if (bits == 1) {
3658 /* set bit 9 so we can tell when we're empty */
3659 bits = *regVector++ | 0x0100;
3660 LOGVV("loaded bits: 0x%02x\n", bits & 0xff);
3661 }
3662
3663 if (rval != 0 && (bits & 0x01) != 0) {
3664 /*
3665 * Non-null, register marked as live reference. This
3666 * should always be a valid object.
3667 */
3668 #if WITH_EXTRA_GC_CHECKS > 0
3669 if ((rval & 0x3) != 0 ||
3670 !dvmIsValidObject((Object*) rval))
3671 {
3672 /* this is very bad */
3673 LOGE("PGC: invalid ref in reg %d: 0x%08x\n",
3674 method->registersSize-1 - i, rval);
3675 } else
3676 #endif
3677 {
3678 dvmMarkObjectNonNull((Object *)rval);
3679 }
3680 } else {
3681 /*
3682 * Null or non-reference, do nothing at all.
3683 */
3684 #if WITH_EXTRA_GC_CHECKS > 1
3685 if (dvmIsValidObject((Object*) rval)) {
3686 /* this is normal, but we feel chatty */
3687 LOGD("PGC: ignoring valid ref in reg %d: 0x%08x\n",
3688 method->registersSize-1 - i, rval);
3689 }
3690 #endif
3691 }
3692 }
3693 dvmReleaseRegisterMapLine(pMap, regVector);
3694 }
3695 }
3696 /* else this is a break frame and there is nothing to mark, or
3697 * this is a native method and the registers are just the "ins",
3698 * copied from various registers in the caller's set.
3699 */
3700
3701 #if WITH_EXTRA_GC_CHECKS > 1
3702 first = false;
3703 #endif
3704
3705 /* Don't fall into an infinite loop if things get corrupted.
3706 */
3707 assert((uintptr_t)saveArea->prevFrame > (uintptr_t)framePtr ||
3708 saveArea->prevFrame == NULL);
3709 framePtr = saveArea->prevFrame;
3710 }
3711 }
3712
gcScanReferenceTable(ReferenceTable * refTable)3713 static void gcScanReferenceTable(ReferenceTable *refTable)
3714 {
3715 Object **op;
3716
3717 //TODO: these asserts are overkill; turn them off when things stablize.
3718 assert(refTable != NULL);
3719 assert(refTable->table != NULL);
3720 assert(refTable->nextEntry != NULL);
3721 assert((uintptr_t)refTable->nextEntry >= (uintptr_t)refTable->table);
3722 assert(refTable->nextEntry - refTable->table <= refTable->maxEntries);
3723
3724 op = refTable->table;
3725 while ((uintptr_t)op < (uintptr_t)refTable->nextEntry) {
3726 dvmMarkObjectNonNull(*(op++));
3727 }
3728 }
3729
gcScanIndirectRefTable(IndirectRefTable * pRefTable)3730 static void gcScanIndirectRefTable(IndirectRefTable* pRefTable)
3731 {
3732 Object** op = pRefTable->table;
3733 int numEntries = dvmIndirectRefTableEntries(pRefTable);
3734 int i;
3735
3736 for (i = 0; i < numEntries; i++) {
3737 Object* obj = *op;
3738 if (obj != NULL)
3739 dvmMarkObjectNonNull(obj);
3740 op++;
3741 }
3742 }
3743
3744 /*
3745 * Scan a Thread and mark any objects it references.
3746 */
gcScanThread(Thread * thread)3747 static void gcScanThread(Thread *thread)
3748 {
3749 assert(thread != NULL);
3750
3751 /*
3752 * The target thread must be suspended or in a state where it can't do
3753 * any harm (e.g. in Object.wait()). The only exception is the current
3754 * thread, which will still be active and in the "running" state.
3755 *
3756 * (Newly-created threads shouldn't be able to shift themselves to
3757 * RUNNING without a suspend-pending check, so this shouldn't cause
3758 * a false-positive.)
3759 */
3760 assert(thread->status != THREAD_RUNNING || thread->isSuspended ||
3761 thread == dvmThreadSelf());
3762
3763 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_THREAD_OBJECT, thread->threadId);
3764
3765 dvmMarkObject(thread->threadObj); // could be NULL, when constructing
3766
3767 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_NATIVE_STACK, thread->threadId);
3768
3769 dvmMarkObject(thread->exception); // usually NULL
3770 gcScanReferenceTable(&thread->internalLocalRefTable);
3771
3772 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_LOCAL, thread->threadId);
3773
3774 #ifdef USE_INDIRECT_REF
3775 gcScanIndirectRefTable(&thread->jniLocalRefTable);
3776 #else
3777 gcScanReferenceTable(&thread->jniLocalRefTable);
3778 #endif
3779
3780 if (thread->jniMonitorRefTable.table != NULL) {
3781 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_MONITOR, thread->threadId);
3782
3783 gcScanReferenceTable(&thread->jniMonitorRefTable);
3784 }
3785
3786 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JAVA_FRAME, thread->threadId);
3787
3788 gcScanInterpStackReferences(thread);
3789
3790 HPROF_CLEAR_GC_SCAN_STATE();
3791 }
3792
gcScanAllThreads()3793 static void gcScanAllThreads()
3794 {
3795 Thread *thread;
3796
3797 /* Lock the thread list so we can safely use the
3798 * next/prev pointers.
3799 */
3800 dvmLockThreadList(dvmThreadSelf());
3801
3802 for (thread = gDvm.threadList; thread != NULL;
3803 thread = thread->next)
3804 {
3805 /* We need to scan our own stack, so don't special-case
3806 * the current thread.
3807 */
3808 gcScanThread(thread);
3809 }
3810
3811 dvmUnlockThreadList();
3812 }
3813
dvmGcScanRootThreadGroups()3814 void dvmGcScanRootThreadGroups()
3815 {
3816 /* We scan the VM's list of threads instead of going
3817 * through the actual ThreadGroups, but it should be
3818 * equivalent.
3819 *
3820 * This assumes that the ThreadGroup class object is in
3821 * the root set, which should always be true; it's
3822 * loaded by the built-in class loader, which is part
3823 * of the root set.
3824 */
3825 gcScanAllThreads();
3826 }
3827