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