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