blob: 6a1e9aab8ad65539cee011f487447e5bf5cbc74f [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 *
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800983 * Most threads won't use jniMonitorRefTable, so we clear out the
984 * structure but don't call the init function (which allocs storage).
985 */
Andy McFaddend5ab7262009-08-25 07:19:34 -0700986#ifdef USE_INDIRECT_REF
987 if (!dvmInitIndirectRefTable(&thread->jniLocalRefTable,
988 kJniLocalRefMin, kJniLocalRefMax, kIndirectKindLocal))
989 return false;
990#else
991 /*
992 * The JNI local ref table *must* be fixed-size because we keep pointers
993 * into the table in our stack frames.
994 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800995 if (!dvmInitReferenceTable(&thread->jniLocalRefTable,
996 kJniLocalRefMax, kJniLocalRefMax))
997 return false;
Andy McFaddend5ab7262009-08-25 07:19:34 -0700998#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800999 if (!dvmInitReferenceTable(&thread->internalLocalRefTable,
1000 kInternalRefDefault, kInternalRefMax))
1001 return false;
1002
1003 memset(&thread->jniMonitorRefTable, 0, sizeof(thread->jniMonitorRefTable));
1004
1005 return true;
1006}
1007
1008/*
1009 * Remove a thread from the internal list.
1010 * Clear out the links to make it obvious that the thread is
1011 * no longer on the list. Caller must hold gDvm.threadListLock.
1012 */
1013static void unlinkThread(Thread* thread)
1014{
1015 LOG_THREAD("threadid=%d: removing from list\n", thread->threadId);
1016 if (thread == gDvm.threadList) {
1017 assert(thread->prev == NULL);
1018 gDvm.threadList = thread->next;
1019 } else {
1020 assert(thread->prev != NULL);
1021 thread->prev->next = thread->next;
1022 }
1023 if (thread->next != NULL)
1024 thread->next->prev = thread->prev;
1025 thread->prev = thread->next = NULL;
1026}
1027
1028/*
1029 * Free a Thread struct, and all the stuff allocated within.
1030 */
1031static void freeThread(Thread* thread)
1032{
1033 if (thread == NULL)
1034 return;
1035
1036 /* thread->threadId is zero at this point */
1037 LOGVV("threadid=%d: freeing\n", thread->threadId);
1038
1039 if (thread->interpStackStart != NULL) {
1040 u1* interpStackBottom;
1041
1042 interpStackBottom = thread->interpStackStart;
1043 interpStackBottom -= thread->interpStackSize;
1044#ifdef MALLOC_INTERP_STACK
1045 free(interpStackBottom);
1046#else
1047 if (munmap(interpStackBottom, thread->interpStackSize) != 0)
1048 LOGW("munmap(thread stack) failed\n");
1049#endif
1050 }
1051
Andy McFaddend5ab7262009-08-25 07:19:34 -07001052#ifdef USE_INDIRECT_REF
1053 dvmClearIndirectRefTable(&thread->jniLocalRefTable);
1054#else
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001055 dvmClearReferenceTable(&thread->jniLocalRefTable);
Andy McFaddend5ab7262009-08-25 07:19:34 -07001056#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001057 dvmClearReferenceTable(&thread->internalLocalRefTable);
1058 if (&thread->jniMonitorRefTable.table != NULL)
1059 dvmClearReferenceTable(&thread->jniMonitorRefTable);
1060
1061 free(thread);
1062}
1063
1064/*
1065 * Like pthread_self(), but on a Thread*.
1066 */
1067Thread* dvmThreadSelf(void)
1068{
1069 return (Thread*) pthread_getspecific(gDvm.pthreadKeySelf);
1070}
1071
1072/*
1073 * Explore our sense of self. Stuffs the thread pointer into TLS.
1074 */
1075static void setThreadSelf(Thread* thread)
1076{
1077 int cc;
1078
1079 cc = pthread_setspecific(gDvm.pthreadKeySelf, thread);
1080 if (cc != 0) {
1081 /*
1082 * Sometimes this fails under Bionic with EINVAL during shutdown.
1083 * This can happen if the timing is just right, e.g. a thread
1084 * fails to attach during shutdown, but the "fail" path calls
1085 * here to ensure we clean up after ourselves.
1086 */
1087 if (thread != NULL) {
1088 LOGE("pthread_setspecific(%p) failed, err=%d\n", thread, cc);
1089 dvmAbort(); /* the world is fundamentally hosed */
1090 }
1091 }
1092}
1093
1094/*
1095 * This is associated with the pthreadKeySelf key. It's called by the
1096 * pthread library when a thread is exiting and the "self" pointer in TLS
1097 * is non-NULL, meaning the VM hasn't had a chance to clean up. In normal
1098 * operation this should never be called.
1099 *
1100 * This is mainly of use to ensure that we don't leak resources if, for
1101 * example, a thread attaches itself to us with AttachCurrentThread and
1102 * then exits without notifying the VM.
Andy McFadden34e25bb2009-04-15 13:27:12 -07001103 *
1104 * We could do the detach here instead of aborting, but this will lead to
1105 * portability problems. Other implementations do not do this check and
1106 * will simply be unaware that the thread has exited, leading to resource
1107 * leaks (and, if this is a non-daemon thread, an infinite hang when the
1108 * VM tries to shut down).
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001109 */
1110static void threadExitCheck(void* arg)
1111{
1112 Thread* thread = (Thread*) arg;
1113
1114 LOGI("In threadExitCheck %p\n", arg);
1115 assert(thread != NULL);
1116
1117 if (thread->status != THREAD_ZOMBIE) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001118 LOGE("Native thread exited without telling us\n");
1119 dvmAbort();
1120 }
1121}
1122
1123
1124/*
1125 * Assign the threadId. This needs to be a small integer so that our
1126 * "thin" locks fit in a small number of bits.
1127 *
1128 * We reserve zero for use as an invalid ID.
1129 *
1130 * This must be called with threadListLock held (unless we're still
1131 * initializing the system).
1132 */
1133static void assignThreadId(Thread* thread)
1134{
1135 /* Find a small unique integer. threadIdMap is a vector of
1136 * kMaxThreadId bits; dvmAllocBit() returns the index of a
1137 * bit, meaning that it will always be < kMaxThreadId.
1138 *
1139 * The thin locking magic requires that the low bit is always
1140 * set, so we do it once, here.
1141 */
1142 int num = dvmAllocBit(gDvm.threadIdMap);
1143 if (num < 0) {
1144 LOGE("Ran out of thread IDs\n");
1145 dvmAbort(); // TODO: make this a non-fatal error result
1146 }
1147
1148 thread->threadId = ((num + 1) << 1) | 1;
1149
1150 assert(thread->threadId != 0);
1151 assert(thread->threadId != DVM_LOCK_INITIAL_THIN_VALUE);
1152}
1153
1154/*
1155 * Give back the thread ID.
1156 */
1157static void releaseThreadId(Thread* thread)
1158{
1159 assert(thread->threadId > 0);
1160 dvmClearBit(gDvm.threadIdMap, (thread->threadId >> 1) - 1);
1161 thread->threadId = 0;
1162}
1163
1164
1165/*
1166 * Add a stack frame that makes it look like the native code in the main
1167 * thread was originally invoked from interpreted code. This gives us a
1168 * place to hang JNI local references. The VM spec says (v2 5.2) that the
1169 * VM begins by executing "main" in a class, so in a way this brings us
1170 * closer to the spec.
1171 */
1172static bool createFakeEntryFrame(Thread* thread)
1173{
1174 assert(thread->threadId == kMainThreadId); // main thread only
1175
1176 /* find the method on first use */
1177 if (gDvm.methFakeNativeEntry == NULL) {
1178 ClassObject* nativeStart;
1179 Method* mainMeth;
1180
1181 nativeStart = dvmFindSystemClassNoInit(
1182 "Ldalvik/system/NativeStart;");
1183 if (nativeStart == NULL) {
1184 LOGE("Unable to find dalvik.system.NativeStart class\n");
1185 return false;
1186 }
1187
1188 /*
1189 * Because we are creating a frame that represents application code, we
1190 * want to stuff the application class loader into the method's class
1191 * loader field, even though we're using the system class loader to
1192 * load it. This makes life easier over in JNI FindClass (though it
1193 * could bite us in other ways).
1194 *
1195 * Unfortunately this is occurring too early in the initialization,
1196 * of necessity coming before JNI is initialized, and we're not quite
1197 * ready to set up the application class loader.
1198 *
1199 * So we save a pointer to the method in gDvm.methFakeNativeEntry
1200 * and check it in FindClass. The method is private so nobody else
1201 * can call it.
1202 */
1203 //nativeStart->classLoader = dvmGetSystemClassLoader();
1204
1205 mainMeth = dvmFindDirectMethodByDescriptor(nativeStart,
1206 "main", "([Ljava/lang/String;)V");
1207 if (mainMeth == NULL) {
1208 LOGE("Unable to find 'main' in dalvik.system.NativeStart\n");
1209 return false;
1210 }
1211
1212 gDvm.methFakeNativeEntry = mainMeth;
1213 }
1214
1215 return dvmPushJNIFrame(thread, gDvm.methFakeNativeEntry);
1216}
1217
1218
1219/*
1220 * Add a stack frame that makes it look like the native thread has been
1221 * executing interpreted code. This gives us a place to hang JNI local
1222 * references.
1223 */
1224static bool createFakeRunFrame(Thread* thread)
1225{
1226 ClassObject* nativeStart;
1227 Method* runMeth;
1228
1229 assert(thread->threadId != 1); // not for main thread
1230
1231 nativeStart =
1232 dvmFindSystemClassNoInit("Ldalvik/system/NativeStart;");
1233 if (nativeStart == NULL) {
1234 LOGE("Unable to find dalvik.system.NativeStart class\n");
1235 return false;
1236 }
1237
1238 runMeth = dvmFindVirtualMethodByDescriptor(nativeStart, "run", "()V");
1239 if (runMeth == NULL) {
1240 LOGE("Unable to find 'run' in dalvik.system.NativeStart\n");
1241 return false;
1242 }
1243
1244 return dvmPushJNIFrame(thread, runMeth);
1245}
1246
1247/*
1248 * Helper function to set the name of the current thread
1249 */
1250static void setThreadName(const char *threadName)
1251{
1252#if defined(HAVE_PRCTL)
1253 int hasAt = 0;
1254 int hasDot = 0;
1255 const char *s = threadName;
1256 while (*s) {
1257 if (*s == '.') hasDot = 1;
1258 else if (*s == '@') hasAt = 1;
1259 s++;
1260 }
1261 int len = s - threadName;
1262 if (len < 15 || hasAt || !hasDot) {
1263 s = threadName;
1264 } else {
1265 s = threadName + len - 15;
1266 }
1267 prctl(PR_SET_NAME, (unsigned long) s, 0, 0, 0);
1268#endif
1269}
1270
1271/*
1272 * Create a thread as a result of java.lang.Thread.start().
1273 *
1274 * We do have to worry about some concurrency problems, e.g. programs
1275 * that try to call Thread.start() on the same object from multiple threads.
1276 * (This will fail for all but one, but we have to make sure that it succeeds
1277 * for exactly one.)
1278 *
1279 * Some of the complexity here arises from our desire to mimic the
1280 * Thread vs. VMThread class decomposition we inherited. We've been given
1281 * a Thread, and now we need to create a VMThread and then populate both
1282 * objects. We also need to create one of our internal Thread objects.
1283 *
1284 * Pass in a stack size of 0 to get the default.
1285 */
1286bool dvmCreateInterpThread(Object* threadObj, int reqStackSize)
1287{
1288 pthread_attr_t threadAttr;
1289 pthread_t threadHandle;
1290 Thread* self;
1291 Thread* newThread = NULL;
1292 Object* vmThreadObj = NULL;
1293 int stackSize;
1294
1295 assert(threadObj != NULL);
1296
1297 if(gDvm.zygote) {
1298 dvmThrowException("Ljava/lang/IllegalStateException;",
1299 "No new threads in -Xzygote mode");
1300
1301 goto fail;
1302 }
1303
1304 self = dvmThreadSelf();
1305 if (reqStackSize == 0)
1306 stackSize = gDvm.stackSize;
1307 else if (reqStackSize < kMinStackSize)
1308 stackSize = kMinStackSize;
1309 else if (reqStackSize > kMaxStackSize)
1310 stackSize = kMaxStackSize;
1311 else
1312 stackSize = reqStackSize;
1313
1314 pthread_attr_init(&threadAttr);
1315 pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
1316
1317 /*
1318 * To minimize the time spent in the critical section, we allocate the
1319 * vmThread object here.
1320 */
1321 vmThreadObj = dvmAllocObject(gDvm.classJavaLangVMThread, ALLOC_DEFAULT);
1322 if (vmThreadObj == NULL)
1323 goto fail;
1324
1325 newThread = allocThread(stackSize);
1326 if (newThread == NULL)
1327 goto fail;
1328 newThread->threadObj = threadObj;
1329
1330 assert(newThread->status == THREAD_INITIALIZING);
1331
1332 /*
1333 * We need to lock out other threads while we test and set the
1334 * "vmThread" field in java.lang.Thread, because we use that to determine
1335 * if this thread has been started before. We use the thread list lock
1336 * because it's handy and we're going to need to grab it again soon
1337 * anyway.
1338 */
1339 dvmLockThreadList(self);
1340
1341 if (dvmGetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread) != NULL) {
1342 dvmUnlockThreadList();
1343 dvmThrowException("Ljava/lang/IllegalThreadStateException;",
1344 "thread has already been started");
1345 goto fail;
1346 }
1347
1348 /*
1349 * There are actually three data structures: Thread (object), VMThread
1350 * (object), and Thread (C struct). All of them point to at least one
1351 * other.
1352 *
1353 * As soon as "VMThread.vmData" is assigned, other threads can start
1354 * making calls into us (e.g. setPriority).
1355 */
1356 dvmSetFieldInt(vmThreadObj, gDvm.offJavaLangVMThread_vmData, (u4)newThread);
1357 dvmSetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread, vmThreadObj);
1358
1359 /*
1360 * Thread creation might take a while, so release the lock.
1361 */
1362 dvmUnlockThreadList();
1363
Andy McFadden2aa43612009-06-17 16:29:30 -07001364 int cc, oldStatus;
1365 oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
1366 cc = pthread_create(&threadHandle, &threadAttr, interpThreadStart,
1367 newThread);
1368 oldStatus = dvmChangeStatus(self, oldStatus);
1369
1370 if (cc != 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001371 /*
1372 * Failure generally indicates that we have exceeded system
1373 * resource limits. VirtualMachineError is probably too severe,
1374 * so use OutOfMemoryError.
1375 */
1376 LOGE("Thread creation failed (err=%s)\n", strerror(errno));
1377
1378 dvmSetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread, NULL);
1379
1380 dvmThrowException("Ljava/lang/OutOfMemoryError;",
1381 "thread creation failed");
1382 goto fail;
1383 }
1384
1385 /*
1386 * We need to wait for the thread to start. Otherwise, depending on
1387 * the whims of the OS scheduler, we could return and the code in our
1388 * thread could try to do operations on the new thread before it had
1389 * finished starting.
1390 *
1391 * The new thread will lock the thread list, change its state to
1392 * THREAD_STARTING, broadcast to gDvm.threadStartCond, and then sleep
1393 * on gDvm.threadStartCond (which uses the thread list lock). This
1394 * thread (the parent) will either see that the thread is already ready
1395 * after we grab the thread list lock, or will be awakened from the
1396 * condition variable on the broadcast.
1397 *
1398 * We don't want to stall the rest of the VM while the new thread
1399 * starts, which can happen if the GC wakes up at the wrong moment.
1400 * So, we change our own status to VMWAIT, and self-suspend if
1401 * necessary after we finish adding the new thread.
1402 *
1403 *
1404 * We have to deal with an odd race with the GC/debugger suspension
1405 * mechanism when creating a new thread. The information about whether
1406 * or not a thread should be suspended is contained entirely within
1407 * the Thread struct; this is usually cleaner to deal with than having
1408 * one or more globally-visible suspension flags. The trouble is that
1409 * we could create the thread while the VM is trying to suspend all
1410 * threads. The suspend-count won't be nonzero for the new thread,
1411 * so dvmChangeStatus(THREAD_RUNNING) won't cause a suspension.
1412 *
1413 * The easiest way to deal with this is to prevent the new thread from
1414 * running until the parent says it's okay. This results in the
Andy McFadden2aa43612009-06-17 16:29:30 -07001415 * following (correct) sequence of events for a "badly timed" GC
1416 * (where '-' is us, 'o' is the child, and '+' is some other thread):
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001417 *
1418 * - call pthread_create()
1419 * - lock thread list
1420 * - put self into THREAD_VMWAIT so GC doesn't wait for us
1421 * - sleep on condition var (mutex = thread list lock) until child starts
1422 * + GC triggered by another thread
1423 * + thread list locked; suspend counts updated; thread list unlocked
1424 * + loop waiting for all runnable threads to suspend
1425 * + success, start GC
1426 * o child thread wakes, signals condition var to wake parent
1427 * o child waits for parent ack on condition variable
1428 * - we wake up, locking thread list
1429 * - add child to thread list
1430 * - unlock thread list
1431 * - change our state back to THREAD_RUNNING; GC causes us to suspend
1432 * + GC finishes; all threads in thread list are resumed
1433 * - lock thread list
1434 * - set child to THREAD_VMWAIT, and signal it to start
1435 * - unlock thread list
1436 * o child resumes
1437 * o child changes state to THREAD_RUNNING
1438 *
1439 * The above shows the GC starting up during thread creation, but if
1440 * it starts anywhere after VMThread.create() is called it will
1441 * produce the same series of events.
1442 *
1443 * Once the child is in the thread list, it will be suspended and
1444 * resumed like any other thread. In the above scenario the resume-all
1445 * code will try to resume the new thread, which was never actually
1446 * suspended, and try to decrement the child's thread suspend count to -1.
1447 * We can catch this in the resume-all code.
1448 *
1449 * Bouncing back and forth between threads like this adds a small amount
1450 * of scheduler overhead to thread startup.
1451 *
1452 * One alternative to having the child wait for the parent would be
1453 * to have the child inherit the parents' suspension count. This
1454 * would work for a GC, since we can safely assume that the parent
1455 * thread didn't cause it, but we must only do so if the parent suspension
1456 * was caused by a suspend-all. If the parent was being asked to
1457 * suspend singly by the debugger, the child should not inherit the value.
1458 *
1459 * We could also have a global "new thread suspend count" that gets
1460 * picked up by new threads before changing state to THREAD_RUNNING.
1461 * This would be protected by the thread list lock and set by a
1462 * suspend-all.
1463 */
1464 dvmLockThreadList(self);
1465 assert(self->status == THREAD_RUNNING);
1466 self->status = THREAD_VMWAIT;
1467 while (newThread->status != THREAD_STARTING)
1468 pthread_cond_wait(&gDvm.threadStartCond, &gDvm.threadListLock);
1469
1470 LOG_THREAD("threadid=%d: adding to list\n", newThread->threadId);
1471 newThread->next = gDvm.threadList->next;
1472 if (newThread->next != NULL)
1473 newThread->next->prev = newThread;
1474 newThread->prev = gDvm.threadList;
1475 gDvm.threadList->next = newThread;
1476
1477 if (!dvmGetFieldBoolean(threadObj, gDvm.offJavaLangThread_daemon))
1478 gDvm.nonDaemonThreadCount++; // guarded by thread list lock
1479
1480 dvmUnlockThreadList();
1481
1482 /* change status back to RUNNING, self-suspending if necessary */
1483 dvmChangeStatus(self, THREAD_RUNNING);
1484
1485 /*
1486 * Tell the new thread to start.
1487 *
1488 * We must hold the thread list lock before messing with another thread.
1489 * In the general case we would also need to verify that newThread was
1490 * still in the thread list, but in our case the thread has not started
1491 * executing user code and therefore has not had a chance to exit.
1492 *
1493 * We move it to VMWAIT, and it then shifts itself to RUNNING, which
1494 * comes with a suspend-pending check.
1495 */
1496 dvmLockThreadList(self);
1497
1498 assert(newThread->status == THREAD_STARTING);
1499 newThread->status = THREAD_VMWAIT;
1500 pthread_cond_broadcast(&gDvm.threadStartCond);
1501
1502 dvmUnlockThreadList();
1503
1504 dvmReleaseTrackedAlloc(vmThreadObj, NULL);
1505 return true;
1506
1507fail:
1508 freeThread(newThread);
1509 dvmReleaseTrackedAlloc(vmThreadObj, NULL);
1510 return false;
1511}
1512
1513/*
1514 * pthread entry function for threads started from interpreted code.
1515 */
1516static void* interpThreadStart(void* arg)
1517{
1518 Thread* self = (Thread*) arg;
1519
1520 char *threadName = dvmGetThreadName(self);
1521 setThreadName(threadName);
1522 free(threadName);
1523
1524 /*
1525 * Finish initializing the Thread struct.
1526 */
1527 prepareThread(self);
1528
1529 LOG_THREAD("threadid=%d: created from interp\n", self->threadId);
1530
1531 /*
1532 * Change our status and wake our parent, who will add us to the
1533 * thread list and advance our state to VMWAIT.
1534 */
1535 dvmLockThreadList(self);
1536 self->status = THREAD_STARTING;
1537 pthread_cond_broadcast(&gDvm.threadStartCond);
1538
1539 /*
1540 * Wait until the parent says we can go. Assuming there wasn't a
1541 * suspend pending, this will happen immediately. When it completes,
1542 * we're full-fledged citizens of the VM.
1543 *
1544 * We have to use THREAD_VMWAIT here rather than THREAD_RUNNING
1545 * because the pthread_cond_wait below needs to reacquire a lock that
1546 * suspend-all is also interested in. If we get unlucky, the parent could
1547 * change us to THREAD_RUNNING, then a GC could start before we get
1548 * signaled, and suspend-all will grab the thread list lock and then
1549 * wait for us to suspend. We'll be in the tail end of pthread_cond_wait
1550 * trying to get the lock.
1551 */
1552 while (self->status != THREAD_VMWAIT)
1553 pthread_cond_wait(&gDvm.threadStartCond, &gDvm.threadListLock);
1554
1555 dvmUnlockThreadList();
1556
1557 /*
1558 * Add a JNI context.
1559 */
1560 self->jniEnv = dvmCreateJNIEnv(self);
1561
1562 /*
1563 * Change our state so the GC will wait for us from now on. If a GC is
1564 * in progress this call will suspend us.
1565 */
1566 dvmChangeStatus(self, THREAD_RUNNING);
1567
1568 /*
1569 * Notify the debugger & DDM. The debugger notification may cause
1570 * us to suspend ourselves (and others).
1571 */
1572 if (gDvm.debuggerConnected)
1573 dvmDbgPostThreadStart(self);
1574
1575 /*
1576 * Set the system thread priority according to the Thread object's
1577 * priority level. We don't usually need to do this, because both the
1578 * Thread object and system thread priorities inherit from parents. The
1579 * tricky case is when somebody creates a Thread object, calls
1580 * setPriority(), and then starts the thread. We could manage this with
1581 * a "needs priority update" flag to avoid the redundant call.
1582 */
Andy McFadden4879df92009-08-07 14:49:40 -07001583 int priority = dvmGetFieldInt(self->threadObj,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001584 gDvm.offJavaLangThread_priority);
1585 dvmChangeThreadPriority(self, priority);
1586
1587 /*
1588 * Execute the "run" method.
1589 *
1590 * At this point our stack is empty, so somebody who comes looking for
1591 * stack traces right now won't have much to look at. This is normal.
1592 */
1593 Method* run = self->threadObj->clazz->vtable[gDvm.voffJavaLangThread_run];
1594 JValue unused;
1595
1596 LOGV("threadid=%d: calling run()\n", self->threadId);
1597 assert(strcmp(run->name, "run") == 0);
1598 dvmCallMethod(self, run, self->threadObj, &unused);
1599 LOGV("threadid=%d: exiting\n", self->threadId);
1600
1601 /*
1602 * Remove the thread from various lists, report its death, and free
1603 * its resources.
1604 */
1605 dvmDetachCurrentThread();
1606
1607 return NULL;
1608}
1609
1610/*
1611 * The current thread is exiting with an uncaught exception. The
1612 * Java programming language allows the application to provide a
1613 * thread-exit-uncaught-exception handler for the VM, for a specific
1614 * Thread, and for all threads in a ThreadGroup.
1615 *
1616 * Version 1.5 added the per-thread handler. We need to call
1617 * "uncaughtException" in the handler object, which is either the
1618 * ThreadGroup object or the Thread-specific handler.
1619 */
1620static void threadExitUncaughtException(Thread* self, Object* group)
1621{
1622 Object* exception;
1623 Object* handlerObj;
1624 ClassObject* throwable;
1625 Method* uncaughtHandler = NULL;
1626 InstField* threadHandler;
1627
1628 LOGW("threadid=%d: thread exiting with uncaught exception (group=%p)\n",
1629 self->threadId, group);
1630 assert(group != NULL);
1631
1632 /*
1633 * Get a pointer to the exception, then clear out the one in the
1634 * thread. We don't want to have it set when executing interpreted code.
1635 */
1636 exception = dvmGetException(self);
1637 dvmAddTrackedAlloc(exception, self);
1638 dvmClearException(self);
1639
1640 /*
1641 * Get the Thread's "uncaughtHandler" object. Use it if non-NULL;
1642 * else use "group" (which is an instance of UncaughtExceptionHandler).
1643 */
1644 threadHandler = dvmFindInstanceField(gDvm.classJavaLangThread,
1645 "uncaughtHandler", "Ljava/lang/Thread$UncaughtExceptionHandler;");
1646 if (threadHandler == NULL) {
1647 LOGW("WARNING: no 'uncaughtHandler' field in java/lang/Thread\n");
1648 goto bail;
1649 }
1650 handlerObj = dvmGetFieldObject(self->threadObj, threadHandler->byteOffset);
1651 if (handlerObj == NULL)
1652 handlerObj = group;
1653
1654 /*
1655 * Find the "uncaughtHandler" field in this object.
1656 */
1657 uncaughtHandler = dvmFindVirtualMethodHierByDescriptor(handlerObj->clazz,
1658 "uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
1659
1660 if (uncaughtHandler != NULL) {
1661 //LOGI("+++ calling %s.uncaughtException\n",
1662 // handlerObj->clazz->descriptor);
1663 JValue unused;
1664 dvmCallMethod(self, uncaughtHandler, handlerObj, &unused,
1665 self->threadObj, exception);
1666 } else {
1667 /* restore it and dump a stack trace */
1668 LOGW("WARNING: no 'uncaughtException' method in class %s\n",
1669 handlerObj->clazz->descriptor);
1670 dvmSetException(self, exception);
1671 dvmLogExceptionStackTrace();
1672 }
1673
1674bail:
Bill Buzbee46cd5b62009-06-05 15:36:06 -07001675#if defined(WITH_JIT)
1676 /* Remove this thread's suspendCount from global suspendCount sum */
1677 lockThreadSuspendCount();
1678 dvmAddToThreadSuspendCount(&self->suspendCount, -self->suspendCount);
1679 unlockThreadSuspendCount();
1680#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001681 dvmReleaseTrackedAlloc(exception, self);
1682}
1683
1684
1685/*
1686 * Create an internal VM thread, for things like JDWP and finalizers.
1687 *
1688 * The easiest way to do this is create a new thread and then use the
1689 * JNI AttachCurrentThread implementation.
1690 *
1691 * This does not return until after the new thread has begun executing.
1692 */
1693bool dvmCreateInternalThread(pthread_t* pHandle, const char* name,
1694 InternalThreadStart func, void* funcArg)
1695{
1696 InternalStartArgs* pArgs;
1697 Object* systemGroup;
1698 pthread_attr_t threadAttr;
1699 volatile Thread* newThread = NULL;
1700 volatile int createStatus = 0;
1701
1702 systemGroup = dvmGetSystemThreadGroup();
1703 if (systemGroup == NULL)
1704 return false;
1705
1706 pArgs = (InternalStartArgs*) malloc(sizeof(*pArgs));
1707 pArgs->func = func;
1708 pArgs->funcArg = funcArg;
1709 pArgs->name = strdup(name); // storage will be owned by new thread
1710 pArgs->group = systemGroup;
1711 pArgs->isDaemon = true;
1712 pArgs->pThread = &newThread;
1713 pArgs->pCreateStatus = &createStatus;
1714
1715 pthread_attr_init(&threadAttr);
1716 //pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
1717
1718 if (pthread_create(pHandle, &threadAttr, internalThreadStart,
1719 pArgs) != 0)
1720 {
1721 LOGE("internal thread creation failed\n");
1722 free(pArgs->name);
1723 free(pArgs);
1724 return false;
1725 }
1726
1727 /*
1728 * Wait for the child to start. This gives us an opportunity to make
1729 * sure that the thread started correctly, and allows our caller to
1730 * assume that the thread has started running.
1731 *
1732 * Because we aren't holding a lock across the thread creation, it's
1733 * possible that the child will already have completed its
1734 * initialization. Because the child only adjusts "createStatus" while
1735 * holding the thread list lock, the initial condition on the "while"
1736 * loop will correctly avoid the wait if this occurs.
1737 *
1738 * It's also possible that we'll have to wait for the thread to finish
1739 * being created, and as part of allocating a Thread object it might
1740 * need to initiate a GC. We switch to VMWAIT while we pause.
1741 */
1742 Thread* self = dvmThreadSelf();
1743 int oldStatus = dvmChangeStatus(self, THREAD_VMWAIT);
1744 dvmLockThreadList(self);
1745 while (createStatus == 0)
1746 pthread_cond_wait(&gDvm.threadStartCond, &gDvm.threadListLock);
1747
1748 if (newThread == NULL) {
1749 LOGW("internal thread create failed (createStatus=%d)\n", createStatus);
1750 assert(createStatus < 0);
1751 /* don't free pArgs -- if pthread_create succeeded, child owns it */
1752 dvmUnlockThreadList();
1753 dvmChangeStatus(self, oldStatus);
1754 return false;
1755 }
1756
1757 /* thread could be in any state now (except early init states) */
1758 //assert(newThread->status == THREAD_RUNNING);
1759
1760 dvmUnlockThreadList();
1761 dvmChangeStatus(self, oldStatus);
1762
1763 return true;
1764}
1765
1766/*
1767 * pthread entry function for internally-created threads.
1768 *
1769 * We are expected to free "arg" and its contents. If we're a daemon
1770 * thread, and we get cancelled abruptly when the VM shuts down, the
1771 * storage won't be freed. If this becomes a concern we can make a copy
1772 * on the stack.
1773 */
1774static void* internalThreadStart(void* arg)
1775{
1776 InternalStartArgs* pArgs = (InternalStartArgs*) arg;
1777 JavaVMAttachArgs jniArgs;
1778
1779 jniArgs.version = JNI_VERSION_1_2;
1780 jniArgs.name = pArgs->name;
1781 jniArgs.group = pArgs->group;
1782
1783 setThreadName(pArgs->name);
1784
1785 /* use local jniArgs as stack top */
1786 if (dvmAttachCurrentThread(&jniArgs, pArgs->isDaemon)) {
1787 /*
1788 * Tell the parent of our success.
1789 *
1790 * threadListLock is the mutex for threadStartCond.
1791 */
1792 dvmLockThreadList(dvmThreadSelf());
1793 *pArgs->pCreateStatus = 1;
1794 *pArgs->pThread = dvmThreadSelf();
1795 pthread_cond_broadcast(&gDvm.threadStartCond);
1796 dvmUnlockThreadList();
1797
1798 LOG_THREAD("threadid=%d: internal '%s'\n",
1799 dvmThreadSelf()->threadId, pArgs->name);
1800
1801 /* execute */
1802 (*pArgs->func)(pArgs->funcArg);
1803
1804 /* detach ourselves */
1805 dvmDetachCurrentThread();
1806 } else {
1807 /*
1808 * Tell the parent of our failure. We don't have a Thread struct,
1809 * so we can't be suspended, so we don't need to enter a critical
1810 * section.
1811 */
1812 dvmLockThreadList(dvmThreadSelf());
1813 *pArgs->pCreateStatus = -1;
1814 assert(*pArgs->pThread == NULL);
1815 pthread_cond_broadcast(&gDvm.threadStartCond);
1816 dvmUnlockThreadList();
1817
1818 assert(*pArgs->pThread == NULL);
1819 }
1820
1821 free(pArgs->name);
1822 free(pArgs);
1823 return NULL;
1824}
1825
1826/*
1827 * Attach the current thread to the VM.
1828 *
1829 * Used for internally-created threads and JNI's AttachCurrentThread.
1830 */
1831bool dvmAttachCurrentThread(const JavaVMAttachArgs* pArgs, bool isDaemon)
1832{
1833 Thread* self = NULL;
1834 Object* threadObj = NULL;
1835 Object* vmThreadObj = NULL;
1836 StringObject* threadNameStr = NULL;
1837 Method* init;
1838 bool ok, ret;
1839
1840 /* establish a basic sense of self */
1841 self = allocThread(gDvm.stackSize);
1842 if (self == NULL)
1843 goto fail;
1844 setThreadSelf(self);
1845
1846 /*
1847 * Create Thread and VMThread objects. We have to use ALLOC_NO_GC
1848 * because this thread is not yet visible to the VM. We could also
1849 * just grab the GC lock earlier, but that leaves us executing
1850 * interpreted code with the lock held, which is not prudent.
1851 *
1852 * The alloc calls will block if a GC is in progress, so we don't need
1853 * to check for global suspension here.
1854 *
1855 * It's also possible for the allocation calls to *cause* a GC.
1856 */
1857 //BUG: deadlock if a GC happens here during HeapWorker creation
1858 threadObj = dvmAllocObject(gDvm.classJavaLangThread, ALLOC_NO_GC);
1859 if (threadObj == NULL)
1860 goto fail;
1861 vmThreadObj = dvmAllocObject(gDvm.classJavaLangVMThread, ALLOC_NO_GC);
1862 if (vmThreadObj == NULL)
1863 goto fail;
1864
1865 self->threadObj = threadObj;
1866 dvmSetFieldInt(vmThreadObj, gDvm.offJavaLangVMThread_vmData, (u4)self);
1867
1868 /*
1869 * Do some java.lang.Thread constructor prep before we lock stuff down.
1870 */
1871 if (pArgs->name != NULL) {
1872 threadNameStr = dvmCreateStringFromCstr(pArgs->name, ALLOC_NO_GC);
1873 if (threadNameStr == NULL) {
1874 assert(dvmCheckException(dvmThreadSelf()));
1875 goto fail;
1876 }
1877 }
1878
1879 init = dvmFindDirectMethodByDescriptor(gDvm.classJavaLangThread, "<init>",
1880 "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
1881 if (init == NULL) {
1882 assert(dvmCheckException(dvmThreadSelf()));
1883 goto fail;
1884 }
1885
1886 /*
1887 * Finish our thread prep. We need to do this before invoking any
1888 * interpreted code. prepareThread() requires that we hold the thread
1889 * list lock.
1890 */
1891 dvmLockThreadList(self);
1892 ok = prepareThread(self);
1893 dvmUnlockThreadList();
1894 if (!ok)
1895 goto fail;
1896
1897 self->jniEnv = dvmCreateJNIEnv(self);
1898 if (self->jniEnv == NULL)
1899 goto fail;
1900
1901 /*
1902 * Create a "fake" JNI frame at the top of the main thread interp stack.
1903 * It isn't really necessary for the internal threads, but it gives
1904 * the debugger something to show. It is essential for the JNI-attached
1905 * threads.
1906 */
1907 if (!createFakeRunFrame(self))
1908 goto fail;
1909
1910 /*
1911 * The native side of the thread is ready; add it to the list.
1912 */
1913 LOG_THREAD("threadid=%d: adding to list (attached)\n", self->threadId);
1914
1915 /* Start off in VMWAIT, because we may be about to block
1916 * on the heap lock, and we don't want any suspensions
1917 * to wait for us.
1918 */
1919 self->status = THREAD_VMWAIT;
1920
1921 /*
1922 * Add ourselves to the thread list. Once we finish here we are
1923 * visible to the debugger and the GC.
1924 */
1925 dvmLockThreadList(self);
1926
1927 self->next = gDvm.threadList->next;
1928 if (self->next != NULL)
1929 self->next->prev = self;
1930 self->prev = gDvm.threadList;
1931 gDvm.threadList->next = self;
1932 if (!isDaemon)
1933 gDvm.nonDaemonThreadCount++;
1934
1935 dvmUnlockThreadList();
1936
1937 /*
1938 * It's possible that a GC is currently running. Our thread
1939 * wasn't in the list when the GC started, so it's not properly
1940 * suspended in that case. Synchronize on the heap lock (held
1941 * when a GC is happening) to guarantee that any GCs from here
1942 * on will see this thread in the list.
1943 */
1944 dvmLockMutex(&gDvm.gcHeapLock);
1945 dvmUnlockMutex(&gDvm.gcHeapLock);
1946
1947 /*
1948 * Switch to the running state now that we're ready for
1949 * suspensions. This call may suspend.
1950 */
1951 dvmChangeStatus(self, THREAD_RUNNING);
1952
1953 /*
1954 * Now we're ready to run some interpreted code.
1955 *
1956 * We need to construct the Thread object and set the VMThread field.
1957 * Setting VMThread tells interpreted code that we're alive.
1958 *
1959 * Call the (group, name, priority, daemon) constructor on the Thread.
1960 * This sets the thread's name and adds it to the specified group, and
1961 * provides values for priority and daemon (which are normally inherited
1962 * from the current thread).
1963 */
1964 JValue unused;
1965 dvmCallMethod(self, init, threadObj, &unused, (Object*)pArgs->group,
1966 threadNameStr, getThreadPriorityFromSystem(), isDaemon);
1967 if (dvmCheckException(self)) {
1968 LOGE("exception thrown while constructing attached thread object\n");
1969 goto fail_unlink;
1970 }
1971 //if (isDaemon)
1972 // dvmSetFieldBoolean(threadObj, gDvm.offJavaLangThread_daemon, true);
1973
1974 /*
1975 * Set the VMThread field, which tells interpreted code that we're alive.
1976 *
1977 * The risk of a thread start collision here is very low; somebody
1978 * would have to be deliberately polling the ThreadGroup list and
1979 * trying to start threads against anything it sees, which would
1980 * generally cause problems for all thread creation. However, for
1981 * correctness we test "vmThread" before setting it.
1982 */
1983 if (dvmGetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread) != NULL) {
1984 dvmThrowException("Ljava/lang/IllegalThreadStateException;",
1985 "thread has already been started");
1986 /* We don't want to free anything associated with the thread
1987 * because someone is obviously interested in it. Just let
1988 * it go and hope it will clean itself up when its finished.
1989 * This case should never happen anyway.
1990 *
1991 * Since we're letting it live, we need to finish setting it up.
1992 * We just have to let the caller know that the intended operation
1993 * has failed.
1994 *
1995 * [ This seems strange -- stepping on the vmThread object that's
1996 * already present seems like a bad idea. TODO: figure this out. ]
1997 */
1998 ret = false;
1999 } else
2000 ret = true;
2001 dvmSetFieldObject(threadObj, gDvm.offJavaLangThread_vmThread, vmThreadObj);
2002
2003 /* These are now reachable from the thread groups. */
2004 dvmClearAllocFlags(threadObj, ALLOC_NO_GC);
2005 dvmClearAllocFlags(vmThreadObj, ALLOC_NO_GC);
2006
2007 /*
2008 * The thread is ready to go; let the debugger see it.
2009 */
2010 self->threadObj = threadObj;
2011
2012 LOG_THREAD("threadid=%d: attached from native, name=%s\n",
2013 self->threadId, pArgs->name);
2014
2015 /* tell the debugger & DDM */
2016 if (gDvm.debuggerConnected)
2017 dvmDbgPostThreadStart(self);
2018
2019 return ret;
2020
2021fail_unlink:
2022 dvmLockThreadList(self);
2023 unlinkThread(self);
2024 if (!isDaemon)
2025 gDvm.nonDaemonThreadCount--;
2026 dvmUnlockThreadList();
2027 /* fall through to "fail" */
2028fail:
2029 dvmClearAllocFlags(threadObj, ALLOC_NO_GC);
2030 dvmClearAllocFlags(vmThreadObj, ALLOC_NO_GC);
2031 if (self != NULL) {
2032 if (self->jniEnv != NULL) {
2033 dvmDestroyJNIEnv(self->jniEnv);
2034 self->jniEnv = NULL;
2035 }
2036 freeThread(self);
2037 }
2038 setThreadSelf(NULL);
2039 return false;
2040}
2041
2042/*
2043 * Detach the thread from the various data structures, notify other threads
2044 * that are waiting to "join" it, and free up all heap-allocated storage.
2045 *
2046 * Used for all threads.
2047 *
2048 * When we get here the interpreted stack should be empty. The JNI 1.6 spec
2049 * requires us to enforce this for the DetachCurrentThread call, probably
2050 * because it also says that DetachCurrentThread causes all monitors
2051 * associated with the thread to be released. (Because the stack is empty,
2052 * we only have to worry about explicit JNI calls to MonitorEnter.)
2053 *
2054 * THOUGHT:
2055 * We might want to avoid freeing our internal Thread structure until the
2056 * associated Thread/VMThread objects get GCed. Our Thread is impossible to
2057 * get to once the thread shuts down, but there is a small possibility of
2058 * an operation starting in another thread before this thread halts, and
2059 * finishing much later (perhaps the thread got stalled by a weird OS bug).
2060 * We don't want something like Thread.isInterrupted() crawling through
2061 * freed storage. Can do with a Thread finalizer, or by creating a
2062 * dedicated ThreadObject class for java/lang/Thread and moving all of our
2063 * state into that.
2064 */
2065void dvmDetachCurrentThread(void)
2066{
2067 Thread* self = dvmThreadSelf();
2068 Object* vmThread;
2069 Object* group;
2070
2071 /*
2072 * Make sure we're not detaching a thread that's still running. (This
2073 * could happen with an explicit JNI detach call.)
2074 *
2075 * A thread created by interpreted code will finish with a depth of
2076 * zero, while a JNI-attached thread will have the synthetic "stack
2077 * starter" native method at the top.
2078 */
2079 int curDepth = dvmComputeExactFrameDepth(self->curFrame);
2080 if (curDepth != 0) {
2081 bool topIsNative = false;
2082
2083 if (curDepth == 1) {
2084 /* not expecting a lingering break frame; just look at curFrame */
2085 assert(!dvmIsBreakFrame(self->curFrame));
2086 StackSaveArea* ssa = SAVEAREA_FROM_FP(self->curFrame);
2087 if (dvmIsNativeMethod(ssa->method))
2088 topIsNative = true;
2089 }
2090
2091 if (!topIsNative) {
2092 LOGE("ERROR: detaching thread with interp frames (count=%d)\n",
2093 curDepth);
2094 dvmDumpThread(self, false);
2095 dvmAbort();
2096 }
2097 }
2098
2099 group = dvmGetFieldObject(self->threadObj, gDvm.offJavaLangThread_group);
2100 LOG_THREAD("threadid=%d: detach (group=%p)\n", self->threadId, group);
2101
2102 /*
2103 * Release any held monitors. Since there are no interpreted stack
2104 * frames, the only thing left are the monitors held by JNI MonitorEnter
2105 * calls.
2106 */
2107 dvmReleaseJniMonitors(self);
2108
2109 /*
2110 * Do some thread-exit uncaught exception processing if necessary.
2111 */
2112 if (dvmCheckException(self))
2113 threadExitUncaughtException(self, group);
2114
2115 /*
2116 * Remove the thread from the thread group.
2117 */
2118 if (group != NULL) {
2119 Method* removeThread =
2120 group->clazz->vtable[gDvm.voffJavaLangThreadGroup_removeThread];
2121 JValue unused;
2122 dvmCallMethod(self, removeThread, group, &unused, self->threadObj);
2123 }
2124
2125 /*
2126 * Clear the vmThread reference in the Thread object. Interpreted code
2127 * will now see that this Thread is not running. As this may be the
2128 * only reference to the VMThread object that the VM knows about, we
2129 * have to create an internal reference to it first.
2130 */
2131 vmThread = dvmGetFieldObject(self->threadObj,
2132 gDvm.offJavaLangThread_vmThread);
2133 dvmAddTrackedAlloc(vmThread, self);
2134 dvmSetFieldObject(self->threadObj, gDvm.offJavaLangThread_vmThread, NULL);
2135
2136 /* clear out our struct Thread pointer, since it's going away */
2137 dvmSetFieldObject(vmThread, gDvm.offJavaLangVMThread_vmData, NULL);
2138
2139 /*
2140 * Tell the debugger & DDM. This may cause the current thread or all
2141 * threads to suspend.
2142 *
2143 * The JDWP spec is somewhat vague about when this happens, other than
2144 * that it's issued by the dying thread, which may still appear in
2145 * an "all threads" listing.
2146 */
2147 if (gDvm.debuggerConnected)
2148 dvmDbgPostThreadDeath(self);
2149
2150 /*
2151 * Thread.join() is implemented as an Object.wait() on the VMThread
2152 * object. Signal anyone who is waiting.
2153 */
2154 dvmLockObject(self, vmThread);
2155 dvmObjectNotifyAll(self, vmThread);
2156 dvmUnlockObject(self, vmThread);
2157
2158 dvmReleaseTrackedAlloc(vmThread, self);
2159 vmThread = NULL;
2160
2161 /*
2162 * We're done manipulating objects, so it's okay if the GC runs in
2163 * parallel with us from here out. It's important to do this if
2164 * profiling is enabled, since we can wait indefinitely.
2165 */
2166 self->status = THREAD_VMWAIT;
2167
2168#ifdef WITH_PROFILER
2169 /*
2170 * If we're doing method trace profiling, we don't want threads to exit,
2171 * because if they do we'll end up reusing thread IDs. This complicates
2172 * analysis and makes it impossible to have reasonable output in the
2173 * "threads" section of the "key" file.
2174 *
2175 * We need to do this after Thread.join() completes, or other threads
2176 * could get wedged. Since self->threadObj is still valid, the Thread
2177 * object will not get GCed even though we're no longer in the ThreadGroup
2178 * list (which is important since the profiling thread needs to get
2179 * the thread's name).
2180 */
2181 MethodTraceState* traceState = &gDvm.methodTrace;
2182
2183 dvmLockMutex(&traceState->startStopLock);
2184 if (traceState->traceEnabled) {
2185 LOGI("threadid=%d: waiting for method trace to finish\n",
2186 self->threadId);
2187 while (traceState->traceEnabled) {
2188 int cc;
2189 cc = pthread_cond_wait(&traceState->threadExitCond,
2190 &traceState->startStopLock);
2191 assert(cc == 0);
2192 }
2193 }
2194 dvmUnlockMutex(&traceState->startStopLock);
2195#endif
2196
2197 dvmLockThreadList(self);
2198
2199 /*
2200 * Lose the JNI context.
2201 */
2202 dvmDestroyJNIEnv(self->jniEnv);
2203 self->jniEnv = NULL;
2204
2205 self->status = THREAD_ZOMBIE;
2206
2207 /*
2208 * Remove ourselves from the internal thread list.
2209 */
2210 unlinkThread(self);
2211
2212 /*
2213 * If we're the last one standing, signal anybody waiting in
2214 * DestroyJavaVM that it's okay to exit.
2215 */
2216 if (!dvmGetFieldBoolean(self->threadObj, gDvm.offJavaLangThread_daemon)) {
2217 gDvm.nonDaemonThreadCount--; // guarded by thread list lock
2218
2219 if (gDvm.nonDaemonThreadCount == 0) {
2220 int cc;
2221
2222 LOGV("threadid=%d: last non-daemon thread\n", self->threadId);
2223 //dvmDumpAllThreads(false);
2224 // cond var guarded by threadListLock, which we already hold
2225 cc = pthread_cond_signal(&gDvm.vmExitCond);
2226 assert(cc == 0);
2227 }
2228 }
2229
2230 LOGV("threadid=%d: bye!\n", self->threadId);
2231 releaseThreadId(self);
2232 dvmUnlockThreadList();
2233
2234 setThreadSelf(NULL);
2235 freeThread(self);
2236}
2237
2238
2239/*
2240 * Suspend a single thread. Do not use to suspend yourself.
2241 *
2242 * This is used primarily for debugger/DDMS activity. Does not return
2243 * until the thread has suspended or is in a "safe" state (e.g. executing
2244 * native code outside the VM).
2245 *
2246 * The thread list lock should be held before calling here -- it's not
2247 * entirely safe to hang on to a Thread* from another thread otherwise.
2248 * (We'd need to grab it here anyway to avoid clashing with a suspend-all.)
2249 */
2250void dvmSuspendThread(Thread* thread)
2251{
2252 assert(thread != NULL);
2253 assert(thread != dvmThreadSelf());
2254 //assert(thread->handle != dvmJdwpGetDebugThread(gDvm.jdwpState));
2255
2256 lockThreadSuspendCount();
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002257 dvmAddToThreadSuspendCount(&thread->suspendCount, 1);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002258 thread->dbgSuspendCount++;
2259
2260 LOG_THREAD("threadid=%d: suspend++, now=%d\n",
2261 thread->threadId, thread->suspendCount);
2262 unlockThreadSuspendCount();
2263
2264 waitForThreadSuspend(dvmThreadSelf(), thread);
2265}
2266
2267/*
2268 * Reduce the suspend count of a thread. If it hits zero, tell it to
2269 * resume.
2270 *
2271 * Used primarily for debugger/DDMS activity. The thread in question
2272 * might have been suspended singly or as part of a suspend-all operation.
2273 *
2274 * The thread list lock should be held before calling here -- it's not
2275 * entirely safe to hang on to a Thread* from another thread otherwise.
2276 * (We'd need to grab it here anyway to avoid clashing with a suspend-all.)
2277 */
2278void dvmResumeThread(Thread* thread)
2279{
2280 assert(thread != NULL);
2281 assert(thread != dvmThreadSelf());
2282 //assert(thread->handle != dvmJdwpGetDebugThread(gDvm.jdwpState));
2283
2284 lockThreadSuspendCount();
2285 if (thread->suspendCount > 0) {
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002286 dvmAddToThreadSuspendCount(&thread->suspendCount, -1);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002287 thread->dbgSuspendCount--;
2288 } else {
2289 LOG_THREAD("threadid=%d: suspendCount already zero\n",
2290 thread->threadId);
2291 }
2292
2293 LOG_THREAD("threadid=%d: suspend--, now=%d\n",
2294 thread->threadId, thread->suspendCount);
2295
2296 if (thread->suspendCount == 0) {
2297 int cc = pthread_cond_broadcast(&gDvm.threadSuspendCountCond);
2298 assert(cc == 0);
2299 }
2300
2301 unlockThreadSuspendCount();
2302}
2303
2304/*
2305 * Suspend yourself, as a result of debugger activity.
2306 */
2307void dvmSuspendSelf(bool jdwpActivity)
2308{
2309 Thread* self = dvmThreadSelf();
2310
2311 /* debugger thread may not suspend itself due to debugger activity! */
2312 assert(gDvm.jdwpState != NULL);
2313 if (self->handle == dvmJdwpGetDebugThread(gDvm.jdwpState)) {
2314 assert(false);
2315 return;
2316 }
2317
2318 /*
2319 * Collisions with other suspends aren't really interesting. We want
2320 * to ensure that we're the only one fiddling with the suspend count
2321 * though.
2322 */
2323 lockThreadSuspendCount();
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002324 dvmAddToThreadSuspendCount(&self->suspendCount, 1);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002325 self->dbgSuspendCount++;
2326
2327 /*
2328 * Suspend ourselves.
2329 */
2330 assert(self->suspendCount > 0);
2331 self->isSuspended = true;
2332 LOG_THREAD("threadid=%d: self-suspending (dbg)\n", self->threadId);
2333
2334 /*
2335 * Tell JDWP that we've completed suspension. The JDWP thread can't
2336 * tell us to resume before we're fully asleep because we hold the
2337 * suspend count lock.
2338 *
2339 * If we got here via waitForDebugger(), don't do this part.
2340 */
2341 if (jdwpActivity) {
2342 //LOGI("threadid=%d: clearing wait-for-event (my handle=%08x)\n",
2343 // self->threadId, (int) self->handle);
2344 dvmJdwpClearWaitForEventThread(gDvm.jdwpState);
2345 }
2346
2347 while (self->suspendCount != 0) {
2348 int cc;
2349 cc = pthread_cond_wait(&gDvm.threadSuspendCountCond,
2350 &gDvm.threadSuspendCountLock);
2351 assert(cc == 0);
2352 if (self->suspendCount != 0) {
The Android Open Source Project99409882009-03-18 22:20:24 -07002353 /*
2354 * The condition was signaled but we're still suspended. This
2355 * can happen if the debugger lets go while a SIGQUIT thread
2356 * dump event is pending (assuming SignalCatcher was resumed for
2357 * just long enough to try to grab the thread-suspend lock).
2358 */
2359 LOGD("threadid=%d: still suspended after undo (sc=%d dc=%d s=%c)\n",
2360 self->threadId, self->suspendCount, self->dbgSuspendCount,
2361 self->isSuspended ? 'Y' : 'N');
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002362 }
2363 }
2364 assert(self->suspendCount == 0 && self->dbgSuspendCount == 0);
2365 self->isSuspended = false;
2366 LOG_THREAD("threadid=%d: self-reviving (dbg), status=%d\n",
2367 self->threadId, self->status);
2368
2369 unlockThreadSuspendCount();
2370}
2371
2372
2373#ifdef HAVE_GLIBC
2374# define NUM_FRAMES 20
2375# include <execinfo.h>
2376/*
2377 * glibc-only stack dump function. Requires link with "--export-dynamic".
2378 *
2379 * TODO: move this into libs/cutils and make it work for all platforms.
2380 */
2381static void printBackTrace(void)
2382{
2383 void* array[NUM_FRAMES];
2384 size_t size;
2385 char** strings;
2386 size_t i;
2387
2388 size = backtrace(array, NUM_FRAMES);
2389 strings = backtrace_symbols(array, size);
2390
2391 LOGW("Obtained %zd stack frames.\n", size);
2392
2393 for (i = 0; i < size; i++)
2394 LOGW("%s\n", strings[i]);
2395
2396 free(strings);
2397}
2398#else
2399static void printBackTrace(void) {}
2400#endif
2401
2402/*
2403 * Dump the state of the current thread and that of another thread that
2404 * we think is wedged.
2405 */
2406static void dumpWedgedThread(Thread* thread)
2407{
2408 char exePath[1024];
2409
2410 /*
2411 * The "executablepath" function in libutils is host-side only.
2412 */
2413 strcpy(exePath, "-");
2414#ifdef HAVE_GLIBC
2415 {
2416 char proc[100];
2417 sprintf(proc, "/proc/%d/exe", getpid());
2418 int len;
2419
2420 len = readlink(proc, exePath, sizeof(exePath)-1);
2421 exePath[len] = '\0';
2422 }
2423#endif
2424
2425 LOGW("dumping state: process %s %d\n", exePath, getpid());
2426 dvmDumpThread(dvmThreadSelf(), false);
2427 printBackTrace();
2428
2429 // dumping a running thread is risky, but could be useful
2430 dvmDumpThread(thread, true);
2431
2432
2433 // stop now and get a core dump
2434 //abort();
2435}
2436
2437
2438/*
2439 * Wait for another thread to see the pending suspension and stop running.
2440 * It can either suspend itself or go into a non-running state such as
2441 * VMWAIT or NATIVE in which it cannot interact with the GC.
2442 *
2443 * If we're running at a higher priority, sched_yield() may not do anything,
2444 * so we need to sleep for "long enough" to guarantee that the other
2445 * thread has a chance to finish what it's doing. Sleeping for too short
2446 * a period (e.g. less than the resolution of the sleep clock) might cause
2447 * the scheduler to return immediately, so we want to start with a
2448 * "reasonable" value and expand.
2449 *
2450 * This does not return until the other thread has stopped running.
2451 * Eventually we time out and the VM aborts.
2452 *
2453 * This does not try to detect the situation where two threads are
2454 * waiting for each other to suspend. In normal use this is part of a
2455 * suspend-all, which implies that the suspend-all lock is held, or as
2456 * part of a debugger action in which the JDWP thread is always the one
2457 * doing the suspending. (We may need to re-evaluate this now that
2458 * getThreadStackTrace is implemented as suspend-snapshot-resume.)
2459 *
2460 * TODO: track basic stats about time required to suspend VM.
2461 */
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002462#define FIRST_SLEEP (250*1000) /* 0.25s */
2463#define MORE_SLEEP (750*1000) /* 0.75s */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002464static void waitForThreadSuspend(Thread* self, Thread* thread)
2465{
2466 const int kMaxRetries = 10;
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002467 int spinSleepTime = FIRST_SLEEP;
Andy McFadden2aa43612009-06-17 16:29:30 -07002468 bool complained = false;
Andy McFadden7ce9bd72009-08-07 11:41:35 -07002469 bool needPriorityReset = false;
2470 int savedThreadPrio = -500;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002471
2472 int sleepIter = 0;
2473 int retryCount = 0;
2474 u8 startWhen = 0; // init req'd to placate gcc
Andy McFadden7ce9bd72009-08-07 11:41:35 -07002475 u8 firstStartWhen = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002476
2477 while (thread->status == THREAD_RUNNING && !thread->isSuspended) {
Andy McFadden7ce9bd72009-08-07 11:41:35 -07002478 if (sleepIter == 0) { // get current time on first iteration
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002479 startWhen = dvmGetRelativeTimeUsec();
Andy McFadden7ce9bd72009-08-07 11:41:35 -07002480 if (firstStartWhen == 0) // first iteration of first attempt
2481 firstStartWhen = startWhen;
2482
2483 /*
2484 * After waiting for a bit, check to see if the target thread is
2485 * running at a reduced priority. If so, bump it up temporarily
2486 * to give it more CPU time.
2487 *
2488 * getpriority() returns the "nice" value, so larger numbers
2489 * indicate lower priority.
2490 *
2491 * (Not currently changing the cgroup. Wasn't necessary in some
2492 * simple experiments.)
2493 */
2494 if (retryCount == 2) {
2495 assert(thread->systemTid != 0);
2496 errno = 0;
2497 int threadPrio = getpriority(PRIO_PROCESS, thread->systemTid);
2498 if (errno == 0 && threadPrio > 0) {
2499 const int kHigher = 0;
2500 if (setpriority(PRIO_PROCESS, thread->systemTid, kHigher) < 0)
2501 {
2502 LOGW("Couldn't raise priority on tid %d to %d\n",
2503 thread->systemTid, kHigher);
2504 } else {
2505 savedThreadPrio = threadPrio;
2506 needPriorityReset = true;
2507 LOGD("Temporarily raising priority on tid %d (%d -> %d)\n",
2508 thread->systemTid, threadPrio, kHigher);
2509 }
2510 }
2511 }
2512 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002513
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002514#if defined (WITH_JIT)
2515 /*
2516 * If we're still waiting after the first timeout,
2517 * unchain all translations.
2518 */
2519 if (gDvmJit.pJitEntryTable && retryCount > 0) {
2520 LOGD("JIT unchain all attempt #%d",retryCount);
2521 dvmJitUnchainAll();
2522 }
2523#endif
2524
Andy McFadden7ce9bd72009-08-07 11:41:35 -07002525 /*
2526 * Sleep briefly. This returns false if we've exceeded the total
2527 * time limit for this round of sleeping.
2528 */
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002529 if (!dvmIterativeSleep(sleepIter++, spinSleepTime, startWhen)) {
Andy McFadden7ce9bd72009-08-07 11:41:35 -07002530 LOGW("threadid=%d: spin on suspend #%d threadid=%d (h=%d)\n",
2531 self->threadId, retryCount,
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002532 thread->threadId, (int)thread->handle);
2533 dumpWedgedThread(thread);
Andy McFadden2aa43612009-06-17 16:29:30 -07002534 complained = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002535
2536 // keep going; could be slow due to valgrind
2537 sleepIter = 0;
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002538 spinSleepTime = MORE_SLEEP;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002539
2540 if (retryCount++ == kMaxRetries) {
2541 LOGE("threadid=%d: stuck on threadid=%d, giving up\n",
2542 self->threadId, thread->threadId);
2543 dvmDumpAllThreads(false);
2544 dvmAbort();
2545 }
2546 }
2547 }
Andy McFadden2aa43612009-06-17 16:29:30 -07002548
2549 if (complained) {
Andy McFadden7ce9bd72009-08-07 11:41:35 -07002550 LOGW("threadid=%d: spin on suspend resolved in %lld msec\n",
2551 self->threadId,
2552 (dvmGetRelativeTimeUsec() - firstStartWhen) / 1000);
Andy McFadden2aa43612009-06-17 16:29:30 -07002553 //dvmDumpThread(thread, false); /* suspended, so dump is safe */
2554 }
Andy McFadden7ce9bd72009-08-07 11:41:35 -07002555 if (needPriorityReset) {
2556 if (setpriority(PRIO_PROCESS, thread->systemTid, savedThreadPrio) < 0) {
2557 LOGW("NOTE: couldn't reset priority on thread %d to %d\n",
2558 thread->systemTid, savedThreadPrio);
2559 } else {
2560 LOGV("Restored priority on %d to %d\n",
2561 thread->systemTid, savedThreadPrio);
2562 }
2563 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002564}
2565
2566/*
2567 * Suspend all threads except the current one. This is used by the GC,
2568 * the debugger, and by any thread that hits a "suspend all threads"
2569 * debugger event (e.g. breakpoint or exception).
2570 *
2571 * If thread N hits a "suspend all threads" breakpoint, we don't want it
2572 * to suspend the JDWP thread. For the GC, we do, because the debugger can
2573 * create objects and even execute arbitrary code. The "why" argument
2574 * allows the caller to say why the suspension is taking place.
2575 *
2576 * This can be called when a global suspend has already happened, due to
2577 * various debugger gymnastics, so keeping an "everybody is suspended" flag
2578 * doesn't work.
2579 *
2580 * DO NOT grab any locks before calling here. We grab & release the thread
2581 * lock and suspend lock here (and we're not using recursive threads), and
2582 * we might have to self-suspend if somebody else beats us here.
2583 *
2584 * The current thread may not be attached to the VM. This can happen if
2585 * we happen to GC as the result of an allocation of a Thread object.
2586 */
2587void dvmSuspendAllThreads(SuspendCause why)
2588{
2589 Thread* self = dvmThreadSelf();
2590 Thread* thread;
2591
2592 assert(why != 0);
2593
2594 /*
2595 * Start by grabbing the thread suspend lock. If we can't get it, most
2596 * likely somebody else is in the process of performing a suspend or
2597 * resume, so lockThreadSuspend() will cause us to self-suspend.
2598 *
2599 * We keep the lock until all other threads are suspended.
2600 */
2601 lockThreadSuspend("susp-all", why);
2602
2603 LOG_THREAD("threadid=%d: SuspendAll starting\n", self->threadId);
2604
2605 /*
2606 * This is possible if the current thread was in VMWAIT mode when a
2607 * suspend-all happened, and then decided to do its own suspend-all.
2608 * This can happen when a couple of threads have simultaneous events
2609 * of interest to the debugger.
2610 */
2611 //assert(self->suspendCount == 0);
2612
2613 /*
2614 * Increment everybody's suspend count (except our own).
2615 */
2616 dvmLockThreadList(self);
2617
2618 lockThreadSuspendCount();
2619 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2620 if (thread == self)
2621 continue;
2622
2623 /* debugger events don't suspend JDWP thread */
2624 if ((why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT) &&
2625 thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState))
2626 continue;
2627
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002628 dvmAddToThreadSuspendCount(&thread->suspendCount, 1);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002629 if (why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT)
2630 thread->dbgSuspendCount++;
2631 }
2632 unlockThreadSuspendCount();
2633
2634 /*
2635 * Wait for everybody in THREAD_RUNNING state to stop. Other states
2636 * indicate the code is either running natively or sleeping quietly.
2637 * Any attempt to transition back to THREAD_RUNNING will cause a check
2638 * for suspension, so it should be impossible for anything to execute
2639 * interpreted code or modify objects (assuming native code plays nicely).
2640 *
2641 * It's also okay if the thread transitions to a non-RUNNING state.
2642 *
2643 * Note we released the threadSuspendCountLock before getting here,
2644 * so if another thread is fiddling with its suspend count (perhaps
2645 * self-suspending for the debugger) it won't block while we're waiting
2646 * in here.
2647 */
2648 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2649 if (thread == self)
2650 continue;
2651
2652 /* debugger events don't suspend JDWP thread */
2653 if ((why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT) &&
2654 thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState))
2655 continue;
2656
2657 /* wait for the other thread to see the pending suspend */
2658 waitForThreadSuspend(self, thread);
2659
2660 LOG_THREAD("threadid=%d: threadid=%d status=%d c=%d dc=%d isSusp=%d\n",
2661 self->threadId,
2662 thread->threadId, thread->status, thread->suspendCount,
2663 thread->dbgSuspendCount, thread->isSuspended);
2664 }
2665
2666 dvmUnlockThreadList();
2667 unlockThreadSuspend();
2668
2669 LOG_THREAD("threadid=%d: SuspendAll complete\n", self->threadId);
2670}
2671
2672/*
2673 * Resume all threads that are currently suspended.
2674 *
2675 * The "why" must match with the previous suspend.
2676 */
2677void dvmResumeAllThreads(SuspendCause why)
2678{
2679 Thread* self = dvmThreadSelf();
2680 Thread* thread;
2681 int cc;
2682
2683 lockThreadSuspend("res-all", why); /* one suspend/resume at a time */
2684 LOG_THREAD("threadid=%d: ResumeAll starting\n", self->threadId);
2685
2686 /*
2687 * Decrement the suspend counts for all threads. No need for atomic
2688 * writes, since nobody should be moving until we decrement the count.
2689 * We do need to hold the thread list because of JNI attaches.
2690 */
2691 dvmLockThreadList(self);
2692 lockThreadSuspendCount();
2693 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2694 if (thread == self)
2695 continue;
2696
2697 /* debugger events don't suspend JDWP thread */
2698 if ((why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT) &&
2699 thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState))
Andy McFadden2aa43612009-06-17 16:29:30 -07002700 {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002701 continue;
Andy McFadden2aa43612009-06-17 16:29:30 -07002702 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002703
2704 if (thread->suspendCount > 0) {
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002705 dvmAddToThreadSuspendCount(&thread->suspendCount, -1);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002706 if (why == SUSPEND_FOR_DEBUG || why == SUSPEND_FOR_DEBUG_EVENT)
2707 thread->dbgSuspendCount--;
2708 } else {
2709 LOG_THREAD("threadid=%d: suspendCount already zero\n",
2710 thread->threadId);
2711 }
2712 }
2713 unlockThreadSuspendCount();
2714 dvmUnlockThreadList();
2715
2716 /*
Andy McFadden2aa43612009-06-17 16:29:30 -07002717 * In some ways it makes sense to continue to hold the thread-suspend
2718 * lock while we issue the wakeup broadcast. It allows us to complete
2719 * one operation before moving on to the next, which simplifies the
2720 * thread activity debug traces.
2721 *
2722 * This approach caused us some difficulty under Linux, because the
2723 * condition variable broadcast not only made the threads runnable,
2724 * but actually caused them to execute, and it was a while before
2725 * the thread performing the wakeup had an opportunity to release the
2726 * thread-suspend lock.
2727 *
2728 * This is a problem because, when a thread tries to acquire that
2729 * lock, it times out after 3 seconds. If at some point the thread
2730 * is told to suspend, the clock resets; but since the VM is still
2731 * theoretically mid-resume, there's no suspend pending. If, for
2732 * example, the GC was waking threads up while the SIGQUIT handler
2733 * was trying to acquire the lock, we would occasionally time out on
2734 * a busy system and SignalCatcher would abort.
2735 *
2736 * We now perform the unlock before the wakeup broadcast. The next
2737 * suspend can't actually start until the broadcast completes and
2738 * returns, because we're holding the thread-suspend-count lock, but the
2739 * suspending thread is now able to make progress and we avoid the abort.
2740 *
2741 * (Technically there is a narrow window between when we release
2742 * the thread-suspend lock and grab the thread-suspend-count lock.
2743 * This could cause us to send a broadcast to threads with nonzero
2744 * suspend counts, but this is expected and they'll all just fall
2745 * right back to sleep. It's probably safe to grab the suspend-count
2746 * lock before releasing thread-suspend, since we're still following
2747 * the correct order of acquisition, but it feels weird.)
2748 */
2749
2750 LOG_THREAD("threadid=%d: ResumeAll waking others\n", self->threadId);
2751 unlockThreadSuspend();
2752
2753 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002754 * Broadcast a notification to all suspended threads, some or all of
2755 * which may choose to wake up. No need to wait for them.
2756 */
2757 lockThreadSuspendCount();
2758 cc = pthread_cond_broadcast(&gDvm.threadSuspendCountCond);
2759 assert(cc == 0);
2760 unlockThreadSuspendCount();
2761
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002762 LOG_THREAD("threadid=%d: ResumeAll complete\n", self->threadId);
2763}
2764
2765/*
2766 * Undo any debugger suspensions. This is called when the debugger
2767 * disconnects.
2768 */
2769void dvmUndoDebuggerSuspensions(void)
2770{
2771 Thread* self = dvmThreadSelf();
2772 Thread* thread;
2773 int cc;
2774
2775 lockThreadSuspend("undo", SUSPEND_FOR_DEBUG);
2776 LOG_THREAD("threadid=%d: UndoDebuggerSusp starting\n", self->threadId);
2777
2778 /*
2779 * Decrement the suspend counts for all threads. No need for atomic
2780 * writes, since nobody should be moving until we decrement the count.
2781 * We do need to hold the thread list because of JNI attaches.
2782 */
2783 dvmLockThreadList(self);
2784 lockThreadSuspendCount();
2785 for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
2786 if (thread == self)
2787 continue;
2788
2789 /* debugger events don't suspend JDWP thread */
2790 if (thread->handle == dvmJdwpGetDebugThread(gDvm.jdwpState)) {
2791 assert(thread->dbgSuspendCount == 0);
2792 continue;
2793 }
2794
2795 assert(thread->suspendCount >= thread->dbgSuspendCount);
Bill Buzbee46cd5b62009-06-05 15:36:06 -07002796 dvmAddToThreadSuspendCount(&thread->suspendCount,
2797 -thread->dbgSuspendCount);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002798 thread->dbgSuspendCount = 0;
2799 }
2800 unlockThreadSuspendCount();
2801 dvmUnlockThreadList();
2802
2803 /*
2804 * Broadcast a notification to all suspended threads, some or all of
2805 * which may choose to wake up. No need to wait for them.
2806 */
2807 lockThreadSuspendCount();
2808 cc = pthread_cond_broadcast(&gDvm.threadSuspendCountCond);
2809 assert(cc == 0);
2810 unlockThreadSuspendCount();
2811
2812 unlockThreadSuspend();
2813
2814 LOG_THREAD("threadid=%d: UndoDebuggerSusp complete\n", self->threadId);
2815}
2816
2817/*
2818 * Determine if a thread is suspended.
2819 *
2820 * As with all operations on foreign threads, the caller should hold
2821 * the thread list lock before calling.
2822 */
2823bool dvmIsSuspended(Thread* thread)
2824{
2825 /*
2826 * The thread could be:
2827 * (1) Running happily. status is RUNNING, isSuspended is false,
2828 * suspendCount is zero. Return "false".
2829 * (2) Pending suspend. status is RUNNING, isSuspended is false,
2830 * suspendCount is nonzero. Return "false".
2831 * (3) Suspended. suspendCount is nonzero, and either (status is
2832 * RUNNING and isSuspended is true) OR (status is !RUNNING).
2833 * Return "true".
2834 * (4) Waking up. suspendCount is zero, status is RUNNING and
2835 * isSuspended is true. Return "false" (since it could change
2836 * out from under us, unless we hold suspendCountLock).
2837 */
2838
2839 return (thread->suspendCount != 0 &&
2840 ((thread->status == THREAD_RUNNING && thread->isSuspended) ||
2841 (thread->status != THREAD_RUNNING)));
2842}
2843
2844/*
2845 * Wait until another thread self-suspends. This is specifically for
2846 * synchronization between the JDWP thread and a thread that has decided
2847 * to suspend itself after sending an event to the debugger.
2848 *
2849 * Threads that encounter "suspend all" events work as well -- the thread
2850 * in question suspends everybody else and then itself.
2851 *
2852 * We can't hold a thread lock here or in the caller, because we could
2853 * get here just before the to-be-waited-for-thread issues a "suspend all".
2854 * There's an opportunity for badness if the thread we're waiting for exits
2855 * and gets cleaned up, but since the thread in question is processing a
2856 * debugger event, that's not really a possibility. (To avoid deadlock,
2857 * it's important that we not be in THREAD_RUNNING while we wait.)
2858 */
2859void dvmWaitForSuspend(Thread* thread)
2860{
2861 Thread* self = dvmThreadSelf();
2862
2863 LOG_THREAD("threadid=%d: waiting for threadid=%d to sleep\n",
2864 self->threadId, thread->threadId);
2865
2866 assert(thread->handle != dvmJdwpGetDebugThread(gDvm.jdwpState));
2867 assert(thread != self);
2868 assert(self->status != THREAD_RUNNING);
2869
2870 waitForThreadSuspend(self, thread);
2871
2872 LOG_THREAD("threadid=%d: threadid=%d is now asleep\n",
2873 self->threadId, thread->threadId);
2874}
2875
2876/*
2877 * Check to see if we need to suspend ourselves. If so, go to sleep on
2878 * a condition variable.
2879 *
2880 * Takes "self" as an argument as an optimization. Pass in NULL to have
2881 * it do the lookup.
2882 *
2883 * Returns "true" if we suspended ourselves.
2884 */
2885bool dvmCheckSuspendPending(Thread* self)
2886{
2887 bool didSuspend;
2888
2889 if (self == NULL)
2890 self = dvmThreadSelf();
2891
2892 /* fast path: if count is zero, bail immediately */
2893 if (self->suspendCount == 0)
2894 return false;
2895
2896 lockThreadSuspendCount(); /* grab gDvm.threadSuspendCountLock */
2897
2898 assert(self->suspendCount >= 0); /* XXX: valid? useful? */
2899
2900 didSuspend = (self->suspendCount != 0);
2901 self->isSuspended = true;
2902 LOG_THREAD("threadid=%d: self-suspending\n", self->threadId);
2903 while (self->suspendCount != 0) {
2904 /* wait for wakeup signal; releases lock */
2905 int cc;
2906 cc = pthread_cond_wait(&gDvm.threadSuspendCountCond,
2907 &gDvm.threadSuspendCountLock);
2908 assert(cc == 0);
2909 }
2910 assert(self->suspendCount == 0 && self->dbgSuspendCount == 0);
2911 self->isSuspended = false;
2912 LOG_THREAD("threadid=%d: self-reviving, status=%d\n",
2913 self->threadId, self->status);
2914
2915 unlockThreadSuspendCount();
2916
2917 return didSuspend;
2918}
2919
2920/*
2921 * Update our status.
2922 *
2923 * The "self" argument, which may be NULL, is accepted as an optimization.
2924 *
2925 * Returns the old status.
2926 */
2927ThreadStatus dvmChangeStatus(Thread* self, ThreadStatus newStatus)
2928{
2929 ThreadStatus oldStatus;
2930
2931 if (self == NULL)
2932 self = dvmThreadSelf();
2933
2934 LOGVV("threadid=%d: (status %d -> %d)\n",
2935 self->threadId, self->status, newStatus);
2936
2937 oldStatus = self->status;
2938
2939 if (newStatus == THREAD_RUNNING) {
2940 /*
2941 * Change our status to THREAD_RUNNING. The transition requires
2942 * that we check for pending suspension, because the VM considers
2943 * us to be "asleep" in all other states.
2944 *
2945 * We need to do the "suspend pending" check FIRST, because it grabs
2946 * a lock that could be held by something that wants us to suspend.
2947 * If we're in RUNNING it will wait for us, and we'll be waiting
2948 * for the lock it holds.
2949 */
2950 assert(self->status != THREAD_RUNNING);
2951
2952 dvmCheckSuspendPending(self);
2953 self->status = THREAD_RUNNING;
2954 } else {
2955 /*
2956 * Change from one state to another, neither of which is
2957 * THREAD_RUNNING. This is most common during system or thread
2958 * initialization.
2959 */
2960 self->status = newStatus;
2961 }
2962
2963 return oldStatus;
2964}
2965
2966/*
2967 * Get a statically defined thread group from a field in the ThreadGroup
2968 * Class object. Expected arguments are "mMain" and "mSystem".
2969 */
2970static Object* getStaticThreadGroup(const char* fieldName)
2971{
2972 StaticField* groupField;
2973 Object* groupObj;
2974
2975 groupField = dvmFindStaticField(gDvm.classJavaLangThreadGroup,
2976 fieldName, "Ljava/lang/ThreadGroup;");
2977 if (groupField == NULL) {
2978 LOGE("java.lang.ThreadGroup does not have an '%s' field\n", fieldName);
2979 dvmThrowException("Ljava/lang/IncompatibleClassChangeError;", NULL);
2980 return NULL;
2981 }
2982 groupObj = dvmGetStaticFieldObject(groupField);
2983 if (groupObj == NULL) {
2984 LOGE("java.lang.ThreadGroup.%s not initialized\n", fieldName);
2985 dvmThrowException("Ljava/lang/InternalError;", NULL);
2986 return NULL;
2987 }
2988
2989 return groupObj;
2990}
2991Object* dvmGetSystemThreadGroup(void)
2992{
2993 return getStaticThreadGroup("mSystem");
2994}
2995Object* dvmGetMainThreadGroup(void)
2996{
2997 return getStaticThreadGroup("mMain");
2998}
2999
3000/*
3001 * Given a VMThread object, return the associated Thread*.
3002 *
3003 * NOTE: if the thread detaches, the struct Thread will disappear, and
3004 * we will be touching invalid data. For safety, lock the thread list
3005 * before calling this.
3006 */
3007Thread* dvmGetThreadFromThreadObject(Object* vmThreadObj)
3008{
3009 int vmData;
3010
3011 vmData = dvmGetFieldInt(vmThreadObj, gDvm.offJavaLangVMThread_vmData);
Andy McFadden44860362009-08-06 17:56:14 -07003012
3013 if (false) {
3014 Thread* thread = gDvm.threadList;
3015 while (thread != NULL) {
3016 if ((Thread*)vmData == thread)
3017 break;
3018
3019 thread = thread->next;
3020 }
3021
3022 if (thread == NULL) {
3023 LOGW("WARNING: vmThreadObj=%p has thread=%p, not in thread list\n",
3024 vmThreadObj, (Thread*)vmData);
3025 vmData = 0;
3026 }
3027 }
3028
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003029 return (Thread*) vmData;
3030}
3031
3032
3033/*
3034 * Conversion map for "nice" values.
3035 *
3036 * We use Android thread priority constants to be consistent with the rest
3037 * of the system. In some cases adjacent entries may overlap.
3038 */
3039static const int kNiceValues[10] = {
3040 ANDROID_PRIORITY_LOWEST, /* 1 (MIN_PRIORITY) */
3041 ANDROID_PRIORITY_BACKGROUND + 6,
3042 ANDROID_PRIORITY_BACKGROUND + 3,
3043 ANDROID_PRIORITY_BACKGROUND,
3044 ANDROID_PRIORITY_NORMAL, /* 5 (NORM_PRIORITY) */
3045 ANDROID_PRIORITY_NORMAL - 2,
3046 ANDROID_PRIORITY_NORMAL - 4,
3047 ANDROID_PRIORITY_URGENT_DISPLAY + 3,
3048 ANDROID_PRIORITY_URGENT_DISPLAY + 2,
3049 ANDROID_PRIORITY_URGENT_DISPLAY /* 10 (MAX_PRIORITY) */
3050};
3051
3052/*
Andy McFaddend62c0b52009-08-04 15:02:12 -07003053 * Change the scheduler cgroup of the current thread.
3054 *
3055 * Returns 0 on success.
San Mehat256fc152009-04-21 14:03:06 -07003056 */
3057int dvmChangeThreadSchedulerGroup(const char *cgroup)
3058{
3059#ifdef HAVE_ANDROID_OS
Andy McFaddend62c0b52009-08-04 15:02:12 -07003060 int fd;
San Mehat256fc152009-04-21 14:03:06 -07003061 char path[255];
San Mehat256fc152009-04-21 14:03:06 -07003062
Andy McFaddend62c0b52009-08-04 15:02:12 -07003063 snprintf(path, sizeof(path), "/dev/cpuctl/%s/tasks", (cgroup ? cgroup :""));
San Mehat256fc152009-04-21 14:03:06 -07003064
Andy McFaddend62c0b52009-08-04 15:02:12 -07003065 if ((fd = open(path, O_WRONLY)) < 0) {
3066 int err = errno;
San Mehat256fc152009-04-21 14:03:06 -07003067#if ENABLE_CGROUP_ERR_LOGGING
Andy McFaddend62c0b52009-08-04 15:02:12 -07003068 LOGW("Unable to open %s (%s)\n", path, strerror(err));
San Mehat256fc152009-04-21 14:03:06 -07003069#endif
Andy McFaddend62c0b52009-08-04 15:02:12 -07003070 return -err;
San Mehat256fc152009-04-21 14:03:06 -07003071 }
3072
Andy McFaddend62c0b52009-08-04 15:02:12 -07003073 if (write(fd, "0", 1) < 0) {
3074 int err = errno;
San Mehat256fc152009-04-21 14:03:06 -07003075#if ENABLE_CGROUP_ERR_LOGGING
Andy McFaddend62c0b52009-08-04 15:02:12 -07003076 LOGW("Unable to move tid %d to cgroup %s (%s)\n",
3077 dvmThreadSelf()->systemTid,
3078 (cgroup ? cgroup : "<default>"), strerror(err));
San Mehat256fc152009-04-21 14:03:06 -07003079#endif
Andy McFaddend62c0b52009-08-04 15:02:12 -07003080 close(fd);
3081 return -err;
San Mehat256fc152009-04-21 14:03:06 -07003082 }
Andy McFaddend62c0b52009-08-04 15:02:12 -07003083 close(fd);
San Mehat256fc152009-04-21 14:03:06 -07003084
Andy McFaddend62c0b52009-08-04 15:02:12 -07003085 return 0;
3086
San Mehat256fc152009-04-21 14:03:06 -07003087#else // HAVE_ANDROID_OS
3088 return 0;
3089#endif
3090}
3091
3092/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003093 * Change the priority of a system thread to match that of the Thread object.
3094 *
3095 * We map a priority value from 1-10 to Linux "nice" values, where lower
3096 * numbers indicate higher priority.
3097 */
3098void dvmChangeThreadPriority(Thread* thread, int newPriority)
3099{
3100 pid_t pid = thread->systemTid;
3101 int newNice;
3102
3103 if (newPriority < 1 || newPriority > 10) {
3104 LOGW("bad priority %d\n", newPriority);
3105 newPriority = 5;
3106 }
3107 newNice = kNiceValues[newPriority-1];
3108
Andy McFaddend62c0b52009-08-04 15:02:12 -07003109 if (newNice >= ANDROID_PRIORITY_BACKGROUND) {
San Mehat256fc152009-04-21 14:03:06 -07003110 dvmChangeThreadSchedulerGroup("bg_non_interactive");
San Mehat3e371e22009-06-26 08:36:16 -07003111 } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
San Mehat256fc152009-04-21 14:03:06 -07003112 dvmChangeThreadSchedulerGroup(NULL);
3113 }
3114
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003115 if (setpriority(PRIO_PROCESS, pid, newNice) != 0) {
3116 char* str = dvmGetThreadName(thread);
3117 LOGI("setPriority(%d) '%s' to prio=%d(n=%d) failed: %s\n",
3118 pid, str, newPriority, newNice, strerror(errno));
3119 free(str);
3120 } else {
3121 LOGV("setPriority(%d) to prio=%d(n=%d)\n",
3122 pid, newPriority, newNice);
3123 }
3124}
3125
3126/*
3127 * Get the thread priority for the current thread by querying the system.
3128 * This is useful when attaching a thread through JNI.
3129 *
3130 * Returns a value from 1 to 10 (compatible with java.lang.Thread values).
3131 */
3132static int getThreadPriorityFromSystem(void)
3133{
3134 int i, sysprio, jprio;
3135
3136 errno = 0;
3137 sysprio = getpriority(PRIO_PROCESS, 0);
3138 if (sysprio == -1 && errno != 0) {
3139 LOGW("getpriority() failed: %s\n", strerror(errno));
3140 return THREAD_NORM_PRIORITY;
3141 }
3142
3143 jprio = THREAD_MIN_PRIORITY;
3144 for (i = 0; i < NELEM(kNiceValues); i++) {
3145 if (sysprio >= kNiceValues[i])
3146 break;
3147 jprio++;
3148 }
3149 if (jprio > THREAD_MAX_PRIORITY)
3150 jprio = THREAD_MAX_PRIORITY;
3151
3152 return jprio;
3153}
3154
3155
3156/*
3157 * Return true if the thread is on gDvm.threadList.
3158 * Caller should not hold gDvm.threadListLock.
3159 */
3160bool dvmIsOnThreadList(const Thread* thread)
3161{
3162 bool ret = false;
3163
3164 dvmLockThreadList(NULL);
3165 if (thread == gDvm.threadList) {
3166 ret = true;
3167 } else {
3168 ret = thread->prev != NULL || thread->next != NULL;
3169 }
3170 dvmUnlockThreadList();
3171
3172 return ret;
3173}
3174
3175/*
3176 * Dump a thread to the log file -- just calls dvmDumpThreadEx() with an
3177 * output target.
3178 */
3179void dvmDumpThread(Thread* thread, bool isRunning)
3180{
3181 DebugOutputTarget target;
3182
3183 dvmCreateLogOutputTarget(&target, ANDROID_LOG_INFO, LOG_TAG);
3184 dvmDumpThreadEx(&target, thread, isRunning);
3185}
3186
3187/*
Andy McFaddend62c0b52009-08-04 15:02:12 -07003188 * Try to get the scheduler group.
3189 *
3190 * The data from /proc/<pid>/cgroup looks like:
3191 * 2:cpu:/bg_non_interactive
3192 *
3193 * We return the part after the "/", which will be an empty string for
3194 * the default cgroup. If the string is longer than "bufLen", the string
3195 * will be truncated.
3196 */
3197static bool getSchedulerGroup(Thread* thread, char* buf, size_t bufLen)
3198{
3199#ifdef HAVE_ANDROID_OS
3200 char pathBuf[32];
3201 char readBuf[256];
3202 ssize_t count;
3203 int fd;
3204
3205 snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", thread->systemTid);
3206 if ((fd = open(pathBuf, O_RDONLY)) < 0) {
3207 LOGV("open(%s) failed: %s\n", pathBuf, strerror(errno));
3208 return false;
3209 }
3210
3211 count = read(fd, readBuf, sizeof(readBuf));
3212 if (count <= 0) {
3213 LOGV("read(%s) failed (%d): %s\n",
3214 pathBuf, (int) count, strerror(errno));
3215 close(fd);
3216 return false;
3217 }
3218 close(fd);
3219
3220 readBuf[--count] = '\0'; /* remove the '\n', now count==strlen */
3221
3222 char* cp = strchr(readBuf, '/');
3223 if (cp == NULL) {
3224 readBuf[sizeof(readBuf)-1] = '\0';
3225 LOGV("no '/' in '%s' (file=%s count=%d)\n",
3226 readBuf, pathBuf, (int) count);
3227 return false;
3228 }
3229
3230 memcpy(buf, cp+1, count); /* count-1 for cp+1, count+1 for NUL */
3231 return true;
3232#else
3233 return false;
3234#endif
3235}
3236
3237/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003238 * Print information about the specified thread.
3239 *
3240 * Works best when the thread in question is "self" or has been suspended.
3241 * When dumping a separate thread that's still running, set "isRunning" to
3242 * use a more cautious thread dump function.
3243 */
3244void dvmDumpThreadEx(const DebugOutputTarget* target, Thread* thread,
3245 bool isRunning)
3246{
3247 /* tied to ThreadStatus enum */
3248 static const char* kStatusNames[] = {
3249 "ZOMBIE", "RUNNABLE", "TIMED_WAIT", "MONITOR", "WAIT",
3250 "INITIALIZING", "STARTING", "NATIVE", "VMWAIT"
3251 };
3252 Object* threadObj;
3253 Object* groupObj;
3254 StringObject* nameStr;
3255 char* threadName = NULL;
3256 char* groupName = NULL;
Andy McFaddend62c0b52009-08-04 15:02:12 -07003257 char schedulerGroupBuf[32];
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003258 bool isDaemon;
3259 int priority; // java.lang.Thread priority
3260 int policy; // pthread policy
3261 struct sched_param sp; // pthread scheduling parameters
3262
3263 threadObj = thread->threadObj;
3264 if (threadObj == NULL) {
3265 LOGW("Can't dump thread %d: threadObj not set\n", thread->threadId);
3266 return;
3267 }
3268 nameStr = (StringObject*) dvmGetFieldObject(threadObj,
3269 gDvm.offJavaLangThread_name);
3270 threadName = dvmCreateCstrFromString(nameStr);
3271
3272 priority = dvmGetFieldInt(threadObj, gDvm.offJavaLangThread_priority);
3273 isDaemon = dvmGetFieldBoolean(threadObj, gDvm.offJavaLangThread_daemon);
3274
3275 if (pthread_getschedparam(pthread_self(), &policy, &sp) != 0) {
3276 LOGW("Warning: pthread_getschedparam failed\n");
3277 policy = -1;
3278 sp.sched_priority = -1;
3279 }
Andy McFaddend62c0b52009-08-04 15:02:12 -07003280 if (!getSchedulerGroup(thread, schedulerGroupBuf,sizeof(schedulerGroupBuf)))
3281 {
3282 strcpy(schedulerGroupBuf, "unknown");
3283 } else if (schedulerGroupBuf[0] == '\0') {
3284 strcpy(schedulerGroupBuf, "default");
3285 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003286
3287 /* a null value for group is not expected, but deal with it anyway */
3288 groupObj = (Object*) dvmGetFieldObject(threadObj,
3289 gDvm.offJavaLangThread_group);
3290 if (groupObj != NULL) {
3291 int offset = dvmFindFieldOffset(gDvm.classJavaLangThreadGroup,
3292 "name", "Ljava/lang/String;");
3293 if (offset < 0) {
3294 LOGW("Unable to find 'name' field in ThreadGroup\n");
3295 } else {
3296 nameStr = (StringObject*) dvmGetFieldObject(groupObj, offset);
3297 groupName = dvmCreateCstrFromString(nameStr);
3298 }
3299 }
3300 if (groupName == NULL)
3301 groupName = strdup("(BOGUS GROUP)");
3302
3303 assert(thread->status < NELEM(kStatusNames));
3304 dvmPrintDebugMessage(target,
3305 "\"%s\"%s prio=%d tid=%d %s\n",
3306 threadName, isDaemon ? " daemon" : "",
3307 priority, thread->threadId, kStatusNames[thread->status]);
3308 dvmPrintDebugMessage(target,
Andy McFadden2aa43612009-06-17 16:29:30 -07003309 " | group=\"%s\" sCount=%d dsCount=%d s=%c obj=%p self=%p\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003310 groupName, thread->suspendCount, thread->dbgSuspendCount,
Andy McFadden2aa43612009-06-17 16:29:30 -07003311 thread->isSuspended ? 'Y' : 'N', thread->threadObj, thread);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003312 dvmPrintDebugMessage(target,
Andy McFaddend62c0b52009-08-04 15:02:12 -07003313 " | sysTid=%d nice=%d sched=%d/%d cgrp=%s handle=%d\n",
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003314 thread->systemTid, getpriority(PRIO_PROCESS, thread->systemTid),
Andy McFaddend62c0b52009-08-04 15:02:12 -07003315 policy, sp.sched_priority, schedulerGroupBuf, (int)thread->handle);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003316
3317#ifdef WITH_MONITOR_TRACKING
3318 if (!isRunning) {
3319 LockedObjectData* lod = thread->pLockedObjects;
3320 if (lod != NULL)
3321 dvmPrintDebugMessage(target, " | monitors held:\n");
3322 else
3323 dvmPrintDebugMessage(target, " | monitors held: <none>\n");
3324 while (lod != NULL) {
3325 dvmPrintDebugMessage(target, " > %p[%d] (%s)\n",
3326 lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
3327 lod = lod->next;
3328 }
3329 }
3330#endif
3331
3332 if (isRunning)
3333 dvmDumpRunningThreadStack(target, thread);
3334 else
3335 dvmDumpThreadStack(target, thread);
3336
3337 free(threadName);
3338 free(groupName);
3339
3340}
3341
3342/*
3343 * Get the name of a thread.
3344 *
3345 * For correctness, the caller should hold the thread list lock to ensure
3346 * that the thread doesn't go away mid-call.
3347 *
3348 * Returns a newly-allocated string, or NULL if the Thread doesn't have a name.
3349 */
3350char* dvmGetThreadName(Thread* thread)
3351{
3352 StringObject* nameObj;
3353
3354 if (thread->threadObj == NULL) {
3355 LOGW("threadObj is NULL, name not available\n");
3356 return strdup("-unknown-");
3357 }
3358
3359 nameObj = (StringObject*)
3360 dvmGetFieldObject(thread->threadObj, gDvm.offJavaLangThread_name);
3361 return dvmCreateCstrFromString(nameObj);
3362}
3363
3364/*
3365 * Dump all threads to the log file -- just calls dvmDumpAllThreadsEx() with
3366 * an output target.
3367 */
3368void dvmDumpAllThreads(bool grabLock)
3369{
3370 DebugOutputTarget target;
3371
3372 dvmCreateLogOutputTarget(&target, ANDROID_LOG_INFO, LOG_TAG);
3373 dvmDumpAllThreadsEx(&target, grabLock);
3374}
3375
3376/*
3377 * Print information about all known threads. Assumes they have been
3378 * suspended (or are in a non-interpreting state, e.g. WAIT or NATIVE).
3379 *
3380 * If "grabLock" is true, we grab the thread lock list. This is important
3381 * to do unless the caller already holds the lock.
3382 */
3383void dvmDumpAllThreadsEx(const DebugOutputTarget* target, bool grabLock)
3384{
3385 Thread* thread;
3386
3387 dvmPrintDebugMessage(target, "DALVIK THREADS:\n");
3388
3389 if (grabLock)
3390 dvmLockThreadList(dvmThreadSelf());
3391
3392 thread = gDvm.threadList;
3393 while (thread != NULL) {
3394 dvmDumpThreadEx(target, thread, false);
3395
3396 /* verify link */
3397 assert(thread->next == NULL || thread->next->prev == thread);
3398
3399 thread = thread->next;
3400 }
3401
3402 if (grabLock)
3403 dvmUnlockThreadList();
3404}
3405
3406#ifdef WITH_MONITOR_TRACKING
3407/*
3408 * Count up the #of locked objects in the current thread.
3409 */
3410static int getThreadObjectCount(const Thread* self)
3411{
3412 LockedObjectData* lod;
3413 int count = 0;
3414
3415 lod = self->pLockedObjects;
3416 while (lod != NULL) {
3417 count++;
3418 lod = lod->next;
3419 }
3420 return count;
3421}
3422
3423/*
3424 * Add the object to the thread's locked object list if it doesn't already
3425 * exist. The most recently added object is the most likely to be released
3426 * next, so we insert at the head of the list.
3427 *
3428 * If it already exists, we increase the recursive lock count.
3429 *
3430 * The object's lock may be thin or fat.
3431 */
3432void dvmAddToMonitorList(Thread* self, Object* obj, bool withTrace)
3433{
3434 LockedObjectData* newLod;
3435 LockedObjectData* lod;
3436 int* trace;
3437 int depth;
3438
3439 lod = self->pLockedObjects;
3440 while (lod != NULL) {
3441 if (lod->obj == obj) {
3442 lod->recursionCount++;
3443 LOGV("+++ +recursive lock %p -> %d\n", obj, lod->recursionCount);
3444 return;
3445 }
3446 lod = lod->next;
3447 }
3448
3449 newLod = (LockedObjectData*) calloc(1, sizeof(LockedObjectData));
3450 if (newLod == NULL) {
3451 LOGE("malloc failed on %d bytes\n", sizeof(LockedObjectData));
3452 return;
3453 }
3454 newLod->obj = obj;
3455 newLod->recursionCount = 0;
3456
3457 if (withTrace) {
3458 trace = dvmFillInStackTraceRaw(self, &depth);
3459 newLod->rawStackTrace = trace;
3460 newLod->stackDepth = depth;
3461 }
3462
3463 newLod->next = self->pLockedObjects;
3464 self->pLockedObjects = newLod;
3465
3466 LOGV("+++ threadid=%d: added %p, now %d\n",
3467 self->threadId, newLod, getThreadObjectCount(self));
3468}
3469
3470/*
3471 * Remove the object from the thread's locked object list. If the entry
3472 * has a nonzero recursion count, we just decrement the count instead.
3473 */
3474void dvmRemoveFromMonitorList(Thread* self, Object* obj)
3475{
3476 LockedObjectData* lod;
3477 LockedObjectData* prevLod;
3478
3479 lod = self->pLockedObjects;
3480 prevLod = NULL;
3481 while (lod != NULL) {
3482 if (lod->obj == obj) {
3483 if (lod->recursionCount > 0) {
3484 lod->recursionCount--;
3485 LOGV("+++ -recursive lock %p -> %d\n",
3486 obj, lod->recursionCount);
3487 return;
3488 } else {
3489 break;
3490 }
3491 }
3492 prevLod = lod;
3493 lod = lod->next;
3494 }
3495
3496 if (lod == NULL) {
3497 LOGW("BUG: object %p not found in thread's lock list\n", obj);
3498 return;
3499 }
3500 if (prevLod == NULL) {
3501 /* first item in list */
3502 assert(self->pLockedObjects == lod);
3503 self->pLockedObjects = lod->next;
3504 } else {
3505 /* middle/end of list */
3506 prevLod->next = lod->next;
3507 }
3508
3509 LOGV("+++ threadid=%d: removed %p, now %d\n",
3510 self->threadId, lod, getThreadObjectCount(self));
3511 free(lod->rawStackTrace);
3512 free(lod);
3513}
3514
3515/*
3516 * If the specified object is already in the thread's locked object list,
3517 * return the LockedObjectData struct. Otherwise return NULL.
3518 */
3519LockedObjectData* dvmFindInMonitorList(const Thread* self, const Object* obj)
3520{
3521 LockedObjectData* lod;
3522
3523 lod = self->pLockedObjects;
3524 while (lod != NULL) {
3525 if (lod->obj == obj)
3526 return lod;
3527 lod = lod->next;
3528 }
3529 return NULL;
3530}
3531#endif /*WITH_MONITOR_TRACKING*/
3532
3533
3534/*
3535 * GC helper functions
3536 */
3537
The Android Open Source Project99409882009-03-18 22:20:24 -07003538/*
3539 * Add the contents of the registers from the interpreted call stack.
3540 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003541static void gcScanInterpStackReferences(Thread *thread)
3542{
3543 const u4 *framePtr;
The Android Open Source Project99409882009-03-18 22:20:24 -07003544#if WITH_EXTRA_GC_CHECKS > 1
3545 bool first = true;
3546#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003547
3548 framePtr = (const u4 *)thread->curFrame;
3549 while (framePtr != NULL) {
3550 const StackSaveArea *saveArea;
3551 const Method *method;
3552
3553 saveArea = SAVEAREA_FROM_FP(framePtr);
3554 method = saveArea->method;
The Android Open Source Project99409882009-03-18 22:20:24 -07003555 if (method != NULL && !dvmIsNativeMethod(method)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003556#ifdef COUNT_PRECISE_METHODS
3557 /* the GC is running, so no lock required */
The Android Open Source Project99409882009-03-18 22:20:24 -07003558 if (dvmPointerSetAddEntry(gDvm.preciseMethods, method))
3559 LOGI("PGC: added %s.%s %p\n",
3560 method->clazz->descriptor, method->name, method);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003561#endif
The Android Open Source Project99409882009-03-18 22:20:24 -07003562#if WITH_EXTRA_GC_CHECKS > 1
3563 /*
3564 * May also want to enable the memset() in the "invokeMethod"
3565 * goto target in the portable interpreter. That sets the stack
3566 * to a pattern that makes referring to uninitialized data
3567 * very obvious.
3568 */
3569
3570 if (first) {
3571 /*
3572 * First frame, isn't native, check the "alternate" saved PC
3573 * as a sanity check.
3574 *
3575 * It seems like we could check the second frame if the first
3576 * is native, since the PCs should be the same. It turns out
3577 * this doesn't always work. The problem is that we could
3578 * have calls in the sequence:
3579 * interp method #2
3580 * native method
3581 * interp method #1
3582 *
3583 * and then GC while in the native method after returning
3584 * from interp method #2. The currentPc on the stack is
3585 * for interp method #1, but thread->currentPc2 is still
3586 * set for the last thing interp method #2 did.
3587 *
3588 * This can also happen in normal execution:
3589 * - sget-object on not-yet-loaded class
3590 * - class init updates currentPc2
3591 * - static field init is handled by parsing annotations;
3592 * static String init requires creation of a String object,
3593 * which can cause a GC
3594 *
3595 * Essentially, any pattern that involves executing
3596 * interpreted code and then causes an allocation without
3597 * executing instructions in the original method will hit
3598 * this. These are rare enough that the test still has
3599 * some value.
3600 */
3601 if (saveArea->xtra.currentPc != thread->currentPc2) {
3602 LOGW("PGC: savedPC(%p) != current PC(%p), %s.%s ins=%p\n",
3603 saveArea->xtra.currentPc, thread->currentPc2,
3604 method->clazz->descriptor, method->name, method->insns);
3605 if (saveArea->xtra.currentPc != NULL)
3606 LOGE(" pc inst = 0x%04x\n", *saveArea->xtra.currentPc);
3607 if (thread->currentPc2 != NULL)
3608 LOGE(" pc2 inst = 0x%04x\n", *thread->currentPc2);
3609 dvmDumpThread(thread, false);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003610 }
The Android Open Source Project99409882009-03-18 22:20:24 -07003611 } else {
3612 /*
3613 * It's unusual, but not impossible, for a non-first frame
3614 * to be at something other than a method invocation. For
3615 * example, if we do a new-instance on a nonexistent class,
3616 * we'll have a lot of class loader activity on the stack
3617 * above the frame with the "new" operation. Could also
3618 * happen while we initialize a Throwable when an instruction
3619 * fails.
3620 *
3621 * So there's not much we can do here to verify the PC,
3622 * except to verify that it's a GC point.
3623 */
3624 }
3625 assert(saveArea->xtra.currentPc != NULL);
3626#endif
3627
3628 const RegisterMap* pMap;
3629 const u1* regVector;
3630 int i;
3631
Andy McFaddencf8b55c2009-04-13 15:26:03 -07003632 Method* nonConstMethod = (Method*) method; // quiet gcc
3633 pMap = dvmGetExpandedRegisterMap(nonConstMethod);
The Android Open Source Project99409882009-03-18 22:20:24 -07003634 if (pMap != NULL) {
3635 /* found map, get registers for this address */
3636 int addr = saveArea->xtra.currentPc - method->insns;
Andy McFaddend45a8872009-03-24 20:41:52 -07003637 regVector = dvmRegisterMapGetLine(pMap, addr);
The Android Open Source Project99409882009-03-18 22:20:24 -07003638 if (regVector == NULL) {
3639 LOGW("PGC: map but no entry for %s.%s addr=0x%04x\n",
3640 method->clazz->descriptor, method->name, addr);
3641 } else {
3642 LOGV("PGC: found map for %s.%s 0x%04x (t=%d)\n",
3643 method->clazz->descriptor, method->name, addr,
3644 thread->threadId);
3645 }
3646 } else {
3647 /*
3648 * No map found. If precise GC is disabled this is
3649 * expected -- we don't create pointers to the map data even
3650 * if it's present -- but if it's enabled it means we're
3651 * unexpectedly falling back on a conservative scan, so it's
3652 * worth yelling a little.
The Android Open Source Project99409882009-03-18 22:20:24 -07003653 */
3654 if (gDvm.preciseGc) {
Andy McFaddena66a01a2009-08-18 15:11:35 -07003655 LOGVV("PGC: no map for %s.%s\n",
The Android Open Source Project99409882009-03-18 22:20:24 -07003656 method->clazz->descriptor, method->name);
3657 }
3658 regVector = NULL;
3659 }
3660
3661 if (regVector == NULL) {
3662 /* conservative scan */
3663 for (i = method->registersSize - 1; i >= 0; i--) {
3664 u4 rval = *framePtr++;
3665 if (rval != 0 && (rval & 0x3) == 0) {
3666 dvmMarkIfObject((Object *)rval);
3667 }
3668 }
3669 } else {
3670 /*
3671 * Precise scan. v0 is at the lowest address on the
3672 * interpreted stack, and is the first bit in the register
3673 * vector, so we can walk through the register map and
3674 * memory in the same direction.
3675 *
3676 * A '1' bit indicates a live reference.
3677 */
3678 u2 bits = 1 << 1;
3679 for (i = method->registersSize - 1; i >= 0; i--) {
3680 u4 rval = *framePtr++;
3681
3682 bits >>= 1;
3683 if (bits == 1) {
3684 /* set bit 9 so we can tell when we're empty */
3685 bits = *regVector++ | 0x0100;
3686 LOGVV("loaded bits: 0x%02x\n", bits & 0xff);
3687 }
3688
3689 if (rval != 0 && (bits & 0x01) != 0) {
3690 /*
3691 * Non-null, register marked as live reference. This
3692 * should always be a valid object.
3693 */
3694#if WITH_EXTRA_GC_CHECKS > 0
3695 if ((rval & 0x3) != 0 ||
3696 !dvmIsValidObject((Object*) rval))
3697 {
3698 /* this is very bad */
3699 LOGE("PGC: invalid ref in reg %d: 0x%08x\n",
3700 method->registersSize-1 - i, rval);
3701 } else
3702#endif
3703 {
3704 dvmMarkObjectNonNull((Object *)rval);
3705 }
3706 } else {
3707 /*
3708 * Null or non-reference, do nothing at all.
3709 */
3710#if WITH_EXTRA_GC_CHECKS > 1
3711 if (dvmIsValidObject((Object*) rval)) {
3712 /* this is normal, but we feel chatty */
3713 LOGD("PGC: ignoring valid ref in reg %d: 0x%08x\n",
3714 method->registersSize-1 - i, rval);
3715 }
3716#endif
3717 }
3718 }
3719 dvmReleaseRegisterMapLine(pMap, regVector);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003720 }
3721 }
The Android Open Source Project99409882009-03-18 22:20:24 -07003722 /* else this is a break frame and there is nothing to mark, or
3723 * this is a native method and the registers are just the "ins",
3724 * copied from various registers in the caller's set.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003725 */
3726
The Android Open Source Project99409882009-03-18 22:20:24 -07003727#if WITH_EXTRA_GC_CHECKS > 1
3728 first = false;
3729#endif
3730
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003731 /* Don't fall into an infinite loop if things get corrupted.
3732 */
3733 assert((uintptr_t)saveArea->prevFrame > (uintptr_t)framePtr ||
3734 saveArea->prevFrame == NULL);
3735 framePtr = saveArea->prevFrame;
3736 }
3737}
3738
3739static void gcScanReferenceTable(ReferenceTable *refTable)
3740{
3741 Object **op;
3742
3743 //TODO: these asserts are overkill; turn them off when things stablize.
3744 assert(refTable != NULL);
3745 assert(refTable->table != NULL);
3746 assert(refTable->nextEntry != NULL);
3747 assert((uintptr_t)refTable->nextEntry >= (uintptr_t)refTable->table);
3748 assert(refTable->nextEntry - refTable->table <= refTable->maxEntries);
3749
3750 op = refTable->table;
3751 while ((uintptr_t)op < (uintptr_t)refTable->nextEntry) {
3752 dvmMarkObjectNonNull(*(op++));
3753 }
3754}
3755
Andy McFaddend5ab7262009-08-25 07:19:34 -07003756static void gcScanIndirectRefTable(IndirectRefTable* pRefTable)
3757{
3758 Object** op = pRefTable->table;
3759 int numEntries = dvmIndirectRefTableEntries(pRefTable);
3760 int i;
3761
3762 for (i = 0; i < numEntries; i++) {
3763 Object* obj = *op;
3764 if (obj != NULL)
3765 dvmMarkObjectNonNull(obj);
3766 op++;
3767 }
3768}
3769
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003770/*
3771 * Scan a Thread and mark any objects it references.
3772 */
3773static void gcScanThread(Thread *thread)
3774{
3775 assert(thread != NULL);
3776
3777 /*
3778 * The target thread must be suspended or in a state where it can't do
3779 * any harm (e.g. in Object.wait()). The only exception is the current
3780 * thread, which will still be active and in the "running" state.
3781 *
3782 * (Newly-created threads shouldn't be able to shift themselves to
3783 * RUNNING without a suspend-pending check, so this shouldn't cause
3784 * a false-positive.)
3785 */
3786 assert(thread->status != THREAD_RUNNING || thread->isSuspended ||
3787 thread == dvmThreadSelf());
3788
3789 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_THREAD_OBJECT, thread->threadId);
3790
3791 dvmMarkObject(thread->threadObj); // could be NULL, when constructing
3792
3793 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_NATIVE_STACK, thread->threadId);
3794
3795 dvmMarkObject(thread->exception); // usually NULL
3796 gcScanReferenceTable(&thread->internalLocalRefTable);
3797
3798 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_LOCAL, thread->threadId);
3799
Andy McFaddend5ab7262009-08-25 07:19:34 -07003800#ifdef USE_INDIRECT_REF
3801 gcScanIndirectRefTable(&thread->jniLocalRefTable);
3802#else
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003803 gcScanReferenceTable(&thread->jniLocalRefTable);
Andy McFaddend5ab7262009-08-25 07:19:34 -07003804#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08003805
3806 if (thread->jniMonitorRefTable.table != NULL) {
3807 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JNI_MONITOR, thread->threadId);
3808
3809 gcScanReferenceTable(&thread->jniMonitorRefTable);
3810 }
3811
3812 HPROF_SET_GC_SCAN_STATE(HPROF_ROOT_JAVA_FRAME, thread->threadId);
3813
3814 gcScanInterpStackReferences(thread);
3815
3816 HPROF_CLEAR_GC_SCAN_STATE();
3817}
3818
3819static void gcScanAllThreads()
3820{
3821 Thread *thread;
3822
3823 /* Lock the thread list so we can safely use the
3824 * next/prev pointers.
3825 */
3826 dvmLockThreadList(dvmThreadSelf());
3827
3828 for (thread = gDvm.threadList; thread != NULL;
3829 thread = thread->next)
3830 {
3831 /* We need to scan our own stack, so don't special-case
3832 * the current thread.
3833 */
3834 gcScanThread(thread);
3835 }
3836
3837 dvmUnlockThreadList();
3838}
3839
3840void dvmGcScanRootThreadGroups()
3841{
3842 /* We scan the VM's list of threads instead of going
3843 * through the actual ThreadGroups, but it should be
3844 * equivalent.
3845 *
3846 * This assumes that the ThreadGroup class object is in
3847 * the root set, which should always be true; it's
3848 * loaded by the built-in class loader, which is part
3849 * of the root set.
3850 */
3851 gcScanAllThreads();
3852}