blob: 24e3917dd70cd874504f74690a1be146522656c5 [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 */
Andy McFadden581bed72009-10-15 11:24:54 -070016
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080017/*
18 * Fundamental synchronization mechanisms.
19 *
20 * The top part of the file has operations on "monitor" structs; the
21 * next part has the native calls on objects.
22 *
23 * The current implementation uses "thin locking" to avoid allocating
24 * an Object's full Monitor struct until absolutely necessary (i.e.,
25 * during contention or a call to wait()).
26 *
27 * TODO: make improvements to thin locking
28 * We may be able to improve performance and reduce memory requirements by:
29 * - reverting to a thin lock once the Monitor is no longer necessary
30 * - using a pool of monitor objects, with some sort of recycling scheme
31 *
32 * TODO: recycle native-level monitors when objects are garbage collected.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080033 */
34#include "Dalvik.h"
35
36#include <stdlib.h>
37#include <unistd.h>
38#include <pthread.h>
39#include <time.h>
40#include <sys/time.h>
41#include <errno.h>
42
43#define LOG_THIN LOGV
44
45#ifdef WITH_DEADLOCK_PREDICTION /* fwd */
46static const char* kStartBanner =
47 "<-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#";
48static const char* kEndBanner =
49 "#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#->";
50
51/*
52 * Unsorted, expanding list of objects.
53 *
54 * This is very similar to PointerSet (which came into existence after this),
55 * but these are unsorted, uniqueness is not enforced by the "add" function,
56 * and the base object isn't allocated on the heap.
57 */
58typedef struct ExpandingObjectList {
59 u2 alloc;
60 u2 count;
61 Object** list;
62} ExpandingObjectList;
63
64/* fwd */
65static void updateDeadlockPrediction(Thread* self, Object* obj);
66static void removeCollectedObject(Object* obj);
67static void expandObjClear(ExpandingObjectList* pList);
68#endif
69
70/*
71 * Every Object has a monitor associated with it, but not every Object is
72 * actually locked. Even the ones that are locked do not need a
73 * full-fledged monitor until a) there is actual contention or b) wait()
74 * is called on the Object.
75 *
76 * For Dalvik, we have implemented a scheme similar to the one described
77 * in Bacon et al.'s "Thin locks: featherweight synchronization for Java"
78 * (ACM 1998). Things are even easier for us, though, because we have
79 * a full 32 bits to work with.
80 *
Carl Shapiro94338aa2009-12-21 11:42:59 -080081 * The two states of an Object's lock are referred to as "thin" and
82 * "fat". A lock may transition from the "thin" state to the "fat"
83 * state and this transition is referred to as inflation. Once a lock
84 * has been inflated it remains in the "fat" state indefinitely.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080085 *
Carl Shapiro77f52eb2009-12-24 19:56:53 -080086 * The lock value itself is stored in Object.lock. The LSB of the
87 * lock encodes its state. When cleared, the lock is in the "thin"
88 * state and its bits are formatted as follows:
Carl Shapiro71938022009-12-22 13:49:53 -080089 *
Carl Shapiro94338aa2009-12-21 11:42:59 -080090 * [31 ---- 19] [18 ---- 3] [2 ---- 1] [0]
91 * lock count thread id hash state 0
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080092 *
Carl Shapiro77f52eb2009-12-24 19:56:53 -080093 * When set, the lock is in the "fat" state and its bits are formatted
Carl Shapiro94338aa2009-12-21 11:42:59 -080094 * as follows:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080095 *
Carl Shapiro94338aa2009-12-21 11:42:59 -080096 * [31 ---- 3] [2 ---- 1] [0]
97 * pointer hash state 1
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080098 *
99 * For an in-depth description of the mechanics of thin-vs-fat locking,
100 * read the paper referred to above.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800101 */
102
103/*
104 * Monitors provide:
105 * - mutually exclusive access to resources
106 * - a way for multiple threads to wait for notification
107 *
108 * In effect, they fill the role of both mutexes and condition variables.
109 *
110 * Only one thread can own the monitor at any time. There may be several
111 * threads waiting on it (the wait call unlocks it). One or more waiting
112 * threads may be getting interrupted or notified at any given time.
113 */
114struct Monitor {
115 Thread* owner; /* which thread currently owns the lock? */
116 int lockCount; /* owner's recursive lock depth */
117 Object* obj; /* what object are we part of [debug only] */
118
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800119 Thread* waitSet; /* threads currently waiting on this monitor */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800120
121 pthread_mutex_t lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800122
123 Monitor* next;
124
125#ifdef WITH_DEADLOCK_PREDICTION
126 /*
127 * Objects that have been locked immediately after this one in the
128 * past. We use an expanding flat array, allocated on first use, to
129 * minimize allocations. Deletions from the list, expected to be
130 * infrequent, are crunched down.
131 */
132 ExpandingObjectList historyChildren;
133
134 /*
135 * We also track parents. This isn't strictly necessary, but it makes
136 * the cleanup at GC time significantly faster.
137 */
138 ExpandingObjectList historyParents;
139
140 /* used during cycle detection */
141 bool historyMark;
142
143 /* stack trace, established the first time we locked the object */
144 int historyStackDepth;
145 int* historyRawStackTrace;
146#endif
147};
148
149
150/*
151 * Create and initialize a monitor.
152 */
153Monitor* dvmCreateMonitor(Object* obj)
154{
155 Monitor* mon;
156
157 mon = (Monitor*) calloc(1, sizeof(Monitor));
158 if (mon == NULL) {
159 LOGE("Unable to allocate monitor\n");
160 dvmAbort();
161 }
Carl Shapiro94338aa2009-12-21 11:42:59 -0800162 if (((u4)mon & 7) != 0) {
163 LOGE("Misaligned monitor: %p\n", mon);
164 dvmAbort();
165 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800166 mon->obj = obj;
167 dvmInitMutex(&mon->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800168
169 /* replace the head of the list with the new monitor */
170 do {
171 mon->next = gDvm.monitorList;
172 } while (!ATOMIC_CMP_SWAP((int32_t*)(void*)&gDvm.monitorList,
173 (int32_t)mon->next, (int32_t)mon));
174
175 return mon;
176}
177
178/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800179 * Free the monitor list. Only used when shutting the VM down.
180 */
181void dvmFreeMonitorList(void)
182{
183 Monitor* mon;
184 Monitor* nextMon;
185
186 mon = gDvm.monitorList;
187 while (mon != NULL) {
188 nextMon = mon->next;
189
190#ifdef WITH_DEADLOCK_PREDICTION
191 expandObjClear(&mon->historyChildren);
192 expandObjClear(&mon->historyParents);
193 free(mon->historyRawStackTrace);
194#endif
195 free(mon);
196 mon = nextMon;
197 }
198}
199
200/*
201 * Log some info about our monitors.
202 */
203void dvmDumpMonitorInfo(const char* msg)
204{
205#if QUIET_ZYGOTE_MONITOR
206 if (gDvm.zygote) {
207 return;
208 }
209#endif
210
211 int totalCount;
212 int liveCount;
213
214 totalCount = liveCount = 0;
215 Monitor* mon = gDvm.monitorList;
216 while (mon != NULL) {
217 totalCount++;
218 if (mon->obj != NULL)
219 liveCount++;
220 mon = mon->next;
221 }
222
223 LOGD("%s: monitor list has %d entries (%d live)\n",
224 msg, totalCount, liveCount);
225}
226
227/*
228 * Get the object that a monitor is part of.
229 */
230Object* dvmGetMonitorObject(Monitor* mon)
231{
232 if (mon == NULL)
233 return NULL;
234 else
235 return mon->obj;
236}
237
238/*
239 * Checks whether the given thread holds the given
240 * objects's lock.
241 */
242bool dvmHoldsLock(Thread* thread, Object* obj)
243{
Carl Shapiro94338aa2009-12-21 11:42:59 -0800244 u4 thin;
245
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800246 if (thread == NULL || obj == NULL) {
247 return false;
248 }
249
250 /* Since we're reading the lock value multiple times,
251 * latch it so that it doesn't change out from under
252 * us if we get preempted.
253 */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800254 thin = obj->lock;
Carl Shapiro94338aa2009-12-21 11:42:59 -0800255 if (LW_SHAPE(thin) == LW_SHAPE_FAT) {
256 return thread == LW_MONITOR(thin)->owner;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800257 } else {
Carl Shapiro94338aa2009-12-21 11:42:59 -0800258 return thread->threadId == LW_LOCK_OWNER(thin);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800259 }
260}
261
262/*
263 * Free the monitor associated with an object and make the object's lock
264 * thin again. This is called during garbage collection.
265 */
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800266static void freeObjectMonitor(Object* obj)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800267{
268 Monitor *mon;
269
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800270 assert(LW_SHAPE(obj->lock) == LW_SHAPE_FAT);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800271
272#ifdef WITH_DEADLOCK_PREDICTION
273 if (gDvm.deadlockPredictMode != kDPOff)
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800274 removeCollectedObject(obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800275#endif
276
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800277 mon = LW_MONITOR(obj->lock);
278 obj->lock = DVM_LOCK_INITIAL_THIN_VALUE;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800279
280 /* This lock is associated with an object
281 * that's being swept. The only possible way
282 * anyone could be holding this lock would be
283 * if some JNI code locked but didn't unlock
284 * the object, in which case we've got some bad
285 * native code somewhere.
286 */
287 assert(pthread_mutex_trylock(&mon->lock) == 0);
288 pthread_mutex_destroy(&mon->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800289#ifdef WITH_DEADLOCK_PREDICTION
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800290 expandObjClear(&mon->historyChildren);
291 expandObjClear(&mon->historyParents);
292 free(mon->historyRawStackTrace);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800293#endif
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800294 free(mon);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800295}
296
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800297/*
298 * Frees monitor objects belonging to unmarked objects.
299 */
300void dvmSweepMonitorList(Monitor** mon, int (*isUnmarkedObject)(void*))
301{
302 Monitor handle;
303 Monitor *prev, *curr;
304 Object *obj;
305
306 assert(mon != NULL);
307 assert(*mon != NULL);
308 assert(isUnmarkedObject != NULL);
309 prev = &handle;
310 prev->next = curr = *mon;
311 while (curr != NULL) {
312 obj = curr->obj;
313 if (obj != NULL && (*isUnmarkedObject)(obj) != 0) {
314 prev->next = curr = curr->next;
315 freeObjectMonitor(obj);
316 } else {
317 prev = curr;
318 curr = curr->next;
319 }
320 }
321 *mon = handle.next;
322}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800323
324/*
325 * Lock a monitor.
326 */
327static void lockMonitor(Thread* self, Monitor* mon)
328{
329 int cc;
330
331 if (mon->owner == self) {
332 mon->lockCount++;
333 } else {
334 ThreadStatus oldStatus;
335
336 if (pthread_mutex_trylock(&mon->lock) != 0) {
337 /* mutex is locked, switch to wait status and sleep on it */
338 oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
339 cc = pthread_mutex_lock(&mon->lock);
340 assert(cc == 0);
341 dvmChangeStatus(self, oldStatus);
342 }
343
344 mon->owner = self;
345 assert(mon->lockCount == 0);
346
347 /*
348 * "waiting", "notifying", and "interrupting" could all be nonzero
349 * if we're locking an object on which other threads are waiting.
350 * Nothing worth assert()ing about here.
351 */
352 }
353}
354
355/*
356 * Try to lock a monitor.
357 *
358 * Returns "true" on success.
359 */
360static bool tryLockMonitor(Thread* self, Monitor* mon)
361{
362 int cc;
363
364 if (mon->owner == self) {
365 mon->lockCount++;
366 return true;
367 } else {
368 cc = pthread_mutex_trylock(&mon->lock);
369 if (cc == 0) {
370 mon->owner = self;
371 assert(mon->lockCount == 0);
372 return true;
373 } else {
374 return false;
375 }
376 }
377}
378
379
380/*
381 * Unlock a monitor.
382 *
383 * Returns true if the unlock succeeded.
384 * If the unlock failed, an exception will be pending.
385 */
386static bool unlockMonitor(Thread* self, Monitor* mon)
387{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800388 assert(self != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800389 assert(mon != NULL); // can this happen?
390
391 if (mon->owner == self) {
392 /*
393 * We own the monitor, so nobody else can be in here.
394 */
395 if (mon->lockCount == 0) {
396 int cc;
397 mon->owner = NULL;
398 cc = pthread_mutex_unlock(&mon->lock);
399 assert(cc == 0);
400 } else {
401 mon->lockCount--;
402 }
403 } else {
404 /*
405 * We don't own this, so we're not allowed to unlock it.
406 * The JNI spec says that we should throw IllegalMonitorStateException
407 * in this case.
408 */
409 if (mon->owner == NULL) {
410 //LOGW("Unlock fat %p: not owned\n", mon->obj);
411 } else {
412 //LOGW("Unlock fat %p: id %d vs %d\n",
413 // mon->obj, mon->owner->threadId, self->threadId);
414 }
415 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
416 "unlock of unowned monitor");
417 return false;
418 }
419 return true;
420}
421
422/*
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800423 * Checks the wait set for circular structure. Returns 0 if the list
Carl Shapirob4539192010-01-04 16:50:00 -0800424 * is not circular. Otherwise, returns 1. Used only by asserts.
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800425 */
426static int waitSetCheck(Monitor *mon)
427{
428 Thread *fast, *slow;
429 size_t n;
430
431 assert(mon != NULL);
432 fast = slow = mon->waitSet;
433 n = 0;
434 for (;;) {
435 if (fast == NULL) return 0;
436 if (fast->waitNext == NULL) return 0;
Carl Shapiro5f56e672010-01-05 20:38:03 -0800437 if (fast == slow && n > 0) return 1;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800438 n += 2;
439 fast = fast->waitNext->waitNext;
440 slow = slow->waitNext;
441 }
442}
443
444/*
445 * Links a thread into a monitor's wait set.
446 */
447static void waitSetAppend(Monitor *mon, Thread *thread)
448{
449 Thread *elt;
450
451 assert(mon != NULL);
452 assert(thread != NULL);
453 assert(thread->waitNext == NULL);
454 assert(waitSetCheck(mon) == 0);
455 if (mon->waitSet == NULL) {
456 mon->waitSet = thread;
457 return;
458 }
459 elt = mon->waitSet;
460 while (elt->waitNext != NULL) {
461 elt = elt->waitNext;
462 }
463 elt->waitNext = thread;
464}
465
466/*
467 * Unlinks a thread from a monitor's wait set.
468 */
469static void waitSetRemove(Monitor *mon, Thread *thread)
470{
471 Thread *elt;
472
473 assert(mon != NULL);
474 assert(thread != NULL);
475 assert(waitSetCheck(mon) == 0);
476 if (mon->waitSet == NULL) {
477 return;
478 }
479 if (mon->waitSet == thread) {
480 mon->waitSet = thread->waitNext;
481 thread->waitNext = NULL;
482 return;
483 }
484 elt = mon->waitSet;
485 while (elt->waitNext != NULL) {
486 if (elt->waitNext == thread) {
487 elt->waitNext = thread->waitNext;
488 thread->waitNext = NULL;
489 return;
490 }
491 elt = elt->waitNext;
492 }
493}
494
Carl Shapirob4539192010-01-04 16:50:00 -0800495/*
496 * Converts the given relative waiting time into an absolute time.
497 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800498static void absoluteTime(s8 msec, s4 nsec, struct timespec *ts)
499{
500 s8 endSec;
501
502#ifdef HAVE_TIMEDWAIT_MONOTONIC
503 clock_gettime(CLOCK_MONOTONIC, ts);
504#else
505 {
506 struct timeval tv;
507 gettimeofday(&tv, NULL);
508 ts->tv_sec = tv.tv_sec;
509 ts->tv_nsec = tv.tv_usec * 1000;
510 }
511#endif
512 endSec = ts->tv_sec + msec / 1000;
513 if (endSec >= 0x7fffffff) {
514 LOGV("NOTE: end time exceeds epoch\n");
515 endSec = 0x7ffffffe;
516 }
517 ts->tv_sec = endSec;
518 ts->tv_nsec = (ts->tv_nsec + (msec % 1000) * 1000000) + nsec;
519
520 /* catch rollover */
521 if (ts->tv_nsec >= 1000000000L) {
522 ts->tv_sec++;
523 ts->tv_nsec -= 1000000000L;
524 }
525}
526
527/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800528 * Wait on a monitor until timeout, interrupt, or notification. Used for
529 * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join().
530 *
531 * If another thread calls Thread.interrupt(), we throw InterruptedException
532 * and return immediately if one of the following are true:
533 * - blocked in wait(), wait(long), or wait(long, int) methods of Object
534 * - blocked in join(), join(long), or join(long, int) methods of Thread
535 * - blocked in sleep(long), or sleep(long, int) methods of Thread
536 * Otherwise, we set the "interrupted" flag.
537 *
538 * Checks to make sure that "nsec" is in the range 0-999999
539 * (i.e. fractions of a millisecond) and throws the appropriate
540 * exception if it isn't.
541 *
542 * The spec allows "spurious wakeups", and recommends that all code using
543 * Object.wait() do so in a loop. This appears to derive from concerns
544 * about pthread_cond_wait() on multiprocessor systems. Some commentary
545 * on the web casts doubt on whether these can/should occur.
546 *
547 * Since we're allowed to wake up "early", we clamp extremely long durations
548 * to return at the end of the 32-bit time epoch.
549 */
550static void waitMonitor(Thread* self, Monitor* mon, s8 msec, s4 nsec,
551 bool interruptShouldThrow)
552{
553 struct timespec ts;
554 bool wasInterrupted = false;
555 bool timed;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800556 int ret;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800557
Carl Shapiro71938022009-12-22 13:49:53 -0800558 assert(self != NULL);
559 assert(mon != NULL);
560
Carl Shapiro94338aa2009-12-21 11:42:59 -0800561 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800562 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800563 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
564 "object not locked by thread before wait()");
565 return;
566 }
567
568 /*
569 * Enforce the timeout range.
570 */
571 if (msec < 0 || nsec < 0 || nsec > 999999) {
572 dvmThrowException("Ljava/lang/IllegalArgumentException;",
573 "timeout arguments out of range");
574 return;
575 }
576
577 /*
578 * Compute absolute wakeup time, if necessary.
579 */
580 if (msec == 0 && nsec == 0) {
581 timed = false;
582 } else {
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800583 absoluteTime(msec, nsec, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800584 timed = true;
585 }
586
587 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800588 * Add ourselves to the set of threads waiting on this monitor, and
589 * release our hold. We need to let it go even if we're a few levels
590 * deep in a recursive lock, and we need to restore that later.
591 *
592 * The order of operations here isn't significant, because we still
593 * hold the pthread mutex.
594 */
595 int prevLockCount;
596
597 prevLockCount = mon->lockCount;
598 mon->lockCount = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800599 mon->owner = NULL;
600
601 /*
602 * Update thread status. If the GC wakes up, it'll ignore us, knowing
603 * that we won't touch any references in this state, and we'll check
604 * our suspend mode before we transition out.
605 */
606 if (timed)
607 dvmChangeStatus(self, THREAD_TIMED_WAIT);
608 else
609 dvmChangeStatus(self, THREAD_WAIT);
610
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800611 ret = pthread_mutex_lock(&self->waitMutex);
612 assert(ret == 0);
613
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800614 /*
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800615 * Set waitMonitor to the monitor object we will be waiting on.
616 * When waitMonitor is non-NULL a notifying or interrupting thread
617 * must signal the thread's waitCond to wake it up.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800618 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800619 assert(self->waitMonitor == NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800620 self->waitMonitor = mon;
621
622 /*
623 * Handle the case where the thread was interrupted before we called
624 * wait().
625 */
626 if (self->interrupted) {
627 wasInterrupted = true;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800628 self->waitMonitor = NULL;
629 pthread_mutex_unlock(&self->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800630 goto done;
631 }
632
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800633 waitSetAppend(mon, self);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800634
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800635 /*
636 * Release the monitor lock and wait for a notification or
637 * a timeout to occur.
638 */
639 pthread_mutex_unlock(&mon->lock);
640
641 if (!timed) {
642 ret = pthread_cond_wait(&self->waitCond, &self->waitMutex);
643 assert(ret == 0);
644 } else {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800645#ifdef HAVE_TIMEDWAIT_MONOTONIC
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800646 ret = pthread_cond_timedwait_monotonic(&self->waitCond, &self->waitMutex, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800647#else
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800648 ret = pthread_cond_timedwait(&self->waitCond, &self->waitMutex, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800649#endif
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800650 assert(ret == 0 || ret == ETIMEDOUT);
651 }
652 if (self->interrupted) {
653 wasInterrupted = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800654 }
655
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800656 self->interrupted = false;
657 self->waitMonitor = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800658
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800659 pthread_mutex_unlock(&self->waitMutex);
660
661 /* Reaquire the monitor lock. */
662 lockMonitor(self, mon);
663
664 waitSetRemove(mon, self);
665
666done:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800667 /*
668 * Put everything back. Again, we hold the pthread mutex, so the order
669 * here isn't significant.
670 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800671 mon->owner = self;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800672 mon->lockCount = prevLockCount;
673
674 /* set self->status back to THREAD_RUNNING, and self-suspend if needed */
675 dvmChangeStatus(self, THREAD_RUNNING);
676
677 if (wasInterrupted) {
678 /*
679 * We were interrupted while waiting, or somebody interrupted an
680 * un-interruptable thread earlier and we're bailing out immediately.
681 *
682 * The doc sayeth: "The interrupted status of the current thread is
683 * cleared when this exception is thrown."
684 */
685 self->interrupted = false;
686 if (interruptShouldThrow)
687 dvmThrowException("Ljava/lang/InterruptedException;", NULL);
688 }
689}
690
691/*
692 * Notify one thread waiting on this monitor.
693 */
694static void notifyMonitor(Thread* self, Monitor* mon)
695{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800696 Thread* thread;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800697
Carl Shapiro71938022009-12-22 13:49:53 -0800698 assert(self != NULL);
699 assert(mon != NULL);
700
Carl Shapiro94338aa2009-12-21 11:42:59 -0800701 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800702 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800703 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
704 "object not locked by thread before notify()");
705 return;
706 }
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800707 /* Signal the first thread in the wait set. */
708 if (mon->waitSet != NULL) {
709 thread = mon->waitSet;
710 mon->waitSet = thread->waitNext;
711 thread->waitNext = NULL;
712 pthread_mutex_lock(&thread->waitMutex);
713 /* Check to see if the thread is still waiting. */
714 if (thread->waitMonitor != NULL) {
715 pthread_cond_signal(&thread->waitCond);
716 }
717 pthread_mutex_unlock(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800718 }
719}
720
721/*
722 * Notify all threads waiting on this monitor.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800723 */
724static void notifyAllMonitor(Thread* self, Monitor* mon)
725{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800726 Thread* thread;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800727
Carl Shapiro71938022009-12-22 13:49:53 -0800728 assert(self != NULL);
729 assert(mon != NULL);
730
Carl Shapiro94338aa2009-12-21 11:42:59 -0800731 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800732 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800733 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
734 "object not locked by thread before notifyAll()");
735 return;
736 }
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800737 /* Signal all threads in the wait set. */
738 while (mon->waitSet != NULL) {
739 thread = mon->waitSet;
740 mon->waitSet = thread->waitNext;
741 thread->waitNext = NULL;
742 pthread_mutex_lock(&thread->waitMutex);
743 /* Check to see if the thread is still waiting. */
744 if (thread->waitMonitor != NULL) {
745 pthread_cond_signal(&thread->waitCond);
746 }
747 pthread_mutex_unlock(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800748 }
749}
750
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800751/*
752 * Implements monitorenter for "synchronized" stuff.
753 *
754 * This does not fail or throw an exception (unless deadlock prediction
755 * is enabled and set to "err" mode).
756 */
757void dvmLockObject(Thread* self, Object *obj)
758{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800759 volatile u4 *thinp = &obj->lock;
760 u4 hashState;
Carl Shapiro94338aa2009-12-21 11:42:59 -0800761 u4 thin;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800762 u4 threadId = self->threadId;
Carl Shapiro94338aa2009-12-21 11:42:59 -0800763 Monitor *mon;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800764
765 /* First, try to grab the lock as if it's thin;
766 * this is the common case and will usually succeed.
767 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800768 thin = threadId << LW_LOCK_OWNER_SHIFT;
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800769 thin |= LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800770 if (!ATOMIC_CMP_SWAP((int32_t *)thinp,
771 (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
Carl Shapiro94338aa2009-12-21 11:42:59 -0800772 (int32_t)thin)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800773 /* The lock is either a thin lock held by someone (possibly 'self'),
774 * or a fat lock.
775 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800776 if (LW_LOCK_OWNER(*thinp) == threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800777 /* 'self' is already holding the thin lock; we can just
778 * bump the count. Atomic operations are not necessary
779 * because only the thread holding the lock is allowed
780 * to modify the Lock field.
781 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800782 *thinp += 1 << LW_LOCK_COUNT_SHIFT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800783 } else {
784 /* If this is a thin lock we need to spin on it, if it's fat
785 * we need to acquire the monitor.
786 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800787 if (LW_SHAPE(*thinp) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800788 ThreadStatus oldStatus;
789 static const unsigned long maxSleepDelay = 1 * 1024 * 1024;
790 unsigned long sleepDelay;
791
792 LOG_THIN("(%d) spin on lock 0x%08x: 0x%08x (0x%08x) 0x%08x\n",
793 threadId, (uint)&obj->lock,
Carl Shapiro94338aa2009-12-21 11:42:59 -0800794 DVM_LOCK_INITIAL_THIN_VALUE, *thinp, thin);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800795
796 /* The lock is still thin, but some other thread is
797 * holding it. Let the VM know that we're about
798 * to wait on another thread.
799 */
800 oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
801
802 /* Spin until the other thread lets go.
803 */
804 sleepDelay = 0;
805 do {
806 /* In addition to looking for an unlock,
807 * we need to watch out for some other thread
808 * fattening the lock behind our back.
809 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800810 while (LW_LOCK_OWNER(*thinp) != 0) {
811 if (LW_SHAPE(*thinp) == LW_SHAPE_FAT) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800812 /* The lock has been fattened already.
813 */
814 LOG_THIN("(%d) lock 0x%08x surprise-fattened\n",
815 threadId, (uint)&obj->lock);
816 dvmChangeStatus(self, oldStatus);
817 goto fat_lock;
818 }
819
820 if (sleepDelay == 0) {
821 sched_yield();
822 sleepDelay = 1 * 1000;
823 } else {
824 usleep(sleepDelay);
825 if (sleepDelay < maxSleepDelay / 2) {
826 sleepDelay *= 2;
827 }
828 }
829 }
Carl Shapiro94338aa2009-12-21 11:42:59 -0800830 thin = threadId << LW_LOCK_OWNER_SHIFT;
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800831 thin |= LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800832 } while (!ATOMIC_CMP_SWAP((int32_t *)thinp,
833 (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
Carl Shapiro94338aa2009-12-21 11:42:59 -0800834 (int32_t)thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800835 LOG_THIN("(%d) spin on lock done 0x%08x: "
836 "0x%08x (0x%08x) 0x%08x\n",
837 threadId, (uint)&obj->lock,
Carl Shapiro94338aa2009-12-21 11:42:59 -0800838 DVM_LOCK_INITIAL_THIN_VALUE, *thinp, thin);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800839
840 /* We've got the thin lock; let the VM know that we're
841 * done waiting.
842 */
843 dvmChangeStatus(self, oldStatus);
844
845 /* Fatten the lock. Note this relinquishes ownership.
846 * We could also create the monitor in an "owned" state
847 * to avoid "re-locking" it in fat_lock.
848 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800849 mon = dvmCreateMonitor(obj);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800850 hashState = LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT;
851 obj->lock = (u4)mon | hashState | LW_SHAPE_FAT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800852 LOG_THIN("(%d) lock 0x%08x fattened\n",
853 threadId, (uint)&obj->lock);
854
855 /* Fall through to acquire the newly fat lock.
856 */
857 }
858
859 /* The lock is already fat, which means
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800860 * that obj->lock is a regular (Monitor *).
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800861 */
862 fat_lock:
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800863 assert(LW_MONITOR(obj->lock) != NULL);
864 lockMonitor(self, LW_MONITOR(obj->lock));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800865 }
866 }
867 // else, the lock was acquired with the ATOMIC_CMP_SWAP().
868
869#ifdef WITH_DEADLOCK_PREDICTION
870 /*
871 * See if we were allowed to grab the lock at this time. We do it
872 * *after* acquiring the lock, rather than before, so that we can
873 * freely update the Monitor struct. This seems counter-intuitive,
874 * but our goal is deadlock *prediction* not deadlock *prevention*.
875 * (If we actually deadlock, the situation is easy to diagnose from
876 * a thread dump, so there's no point making a special effort to do
877 * the checks before the lock is held.)
878 *
879 * This needs to happen before we add the object to the thread's
880 * monitor list, so we can tell the difference between first-lock and
881 * re-lock.
882 *
883 * It's also important that we do this while in THREAD_RUNNING, so
884 * that we don't interfere with cleanup operations in the GC.
885 */
886 if (gDvm.deadlockPredictMode != kDPOff) {
887 if (self->status != THREAD_RUNNING) {
888 LOGE("Bad thread status (%d) in DP\n", self->status);
889 dvmDumpThread(self, false);
890 dvmAbort();
891 }
892 assert(!dvmCheckException(self));
893 updateDeadlockPrediction(self, obj);
894 if (dvmCheckException(self)) {
895 /*
896 * If we're throwing an exception here, we need to free the
897 * lock. We add the object to the thread's monitor list so the
898 * "unlock" code can remove it.
899 */
900 dvmAddToMonitorList(self, obj, false);
901 dvmUnlockObject(self, obj);
902 LOGV("--- unlocked, pending is '%s'\n",
903 dvmGetException(self)->clazz->descriptor);
904 }
905 }
906
907 /*
908 * Add the locked object, and the current stack trace, to the list
909 * held by the Thread object. If deadlock prediction isn't on,
910 * don't capture the stack trace.
911 */
912 dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff);
913#elif defined(WITH_MONITOR_TRACKING)
914 /*
915 * Add the locked object to the list held by the Thread object.
916 */
917 dvmAddToMonitorList(self, obj, false);
918#endif
919}
920
921/*
922 * Implements monitorexit for "synchronized" stuff.
923 *
924 * On failure, throws an exception and returns "false".
925 */
926bool dvmUnlockObject(Thread* self, Object *obj)
927{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800928 volatile u4 *thinp = &obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800929 u4 threadId = self->threadId;
Carl Shapiro94338aa2009-12-21 11:42:59 -0800930 u4 thin;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800931
932 /* Check the common case, where 'self' has locked 'obj' once, first.
933 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800934 thin = *thinp;
935 if (LW_LOCK_OWNER(thin) == threadId && LW_LOCK_COUNT(thin) == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800936 /* Unlock 'obj' by clearing our threadId from 'thin'.
937 * The lock protects the lock field itself, so it's
938 * safe to update non-atomically.
939 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800940 *thinp &= (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT);
941 } else if (LW_SHAPE(*thinp) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800942 /* If the object is locked, it had better be locked by us.
943 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800944 if (LW_LOCK_OWNER(*thinp) != threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800945 /* The JNI spec says that we should throw an exception
946 * in this case.
947 */
948 //LOGW("Unlock thin %p: id %d vs %d\n",
949 // obj, (*thinp & 0xfff), threadId);
950 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
951 "unlock of unowned monitor");
952 return false;
953 }
954
955 /* It's a thin lock, but 'self' has locked 'obj'
956 * more than once. Decrement the count.
957 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800958 *thinp -= 1 << LW_LOCK_COUNT_SHIFT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800959 } else {
960 /* It's a fat lock.
961 */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800962 assert(LW_MONITOR(obj->lock) != NULL);
963 if (!unlockMonitor(self, LW_MONITOR(obj->lock))) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800964 /* exception has been raised */
965 return false;
966 }
967 }
968
969#ifdef WITH_MONITOR_TRACKING
970 /*
971 * Remove the object from the Thread's list.
972 */
973 dvmRemoveFromMonitorList(self, obj);
974#endif
975
976 return true;
977}
978
979/*
980 * Object.wait(). Also called for class init.
981 */
982void dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec,
983 bool interruptShouldThrow)
984{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800985 Monitor* mon = LW_MONITOR(obj->lock);
986 u4 hashState;
987 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800988
989 /* If the lock is still thin, we need to fatten it.
990 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800991 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800992 /* Make sure that 'self' holds the lock.
993 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800994 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800995 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
996 "object not locked by thread before wait()");
997 return;
998 }
999
1000 /* This thread holds the lock. We need to fatten the lock
1001 * so 'self' can block on it. Don't update the object lock
1002 * field yet, because 'self' needs to acquire the lock before
1003 * any other thread gets a chance.
1004 */
1005 mon = dvmCreateMonitor(obj);
1006
1007 /* 'self' has actually locked the object one or more times;
1008 * make sure that the monitor reflects this.
1009 */
1010 lockMonitor(self, mon);
Carl Shapiro94338aa2009-12-21 11:42:59 -08001011 mon->lockCount = LW_LOCK_COUNT(thin);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001012 LOG_THIN("(%d) lock 0x%08x fattened by wait() to count %d\n",
1013 self->threadId, (uint)&obj->lock, mon->lockCount);
1014
Andy McFadden581bed72009-10-15 11:24:54 -07001015
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001016 /* Make the monitor public now that it's in the right state.
1017 */
Andy McFadden581bed72009-10-15 11:24:54 -07001018 MEM_BARRIER();
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001019 hashState = LW_HASH_STATE(thin) << LW_HASH_STATE_SHIFT;
1020 obj->lock = (u4)mon | hashState | LW_SHAPE_FAT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001021 }
1022
1023 waitMonitor(self, mon, msec, nsec, interruptShouldThrow);
1024}
1025
1026/*
1027 * Object.notify().
1028 */
1029void dvmObjectNotify(Thread* self, Object *obj)
1030{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001031 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001032
1033 /* If the lock is still thin, there aren't any waiters;
1034 * waiting on an object forces lock fattening.
1035 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001036 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001037 /* Make sure that 'self' holds the lock.
1038 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001039 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001040 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1041 "object not locked by thread before notify()");
1042 return;
1043 }
1044
1045 /* no-op; there are no waiters to notify.
1046 */
1047 } else {
1048 /* It's a fat lock.
1049 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001050 notifyMonitor(self, LW_MONITOR(thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001051 }
1052}
1053
1054/*
1055 * Object.notifyAll().
1056 */
1057void dvmObjectNotifyAll(Thread* self, Object *obj)
1058{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001059 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001060
1061 /* If the lock is still thin, there aren't any waiters;
1062 * waiting on an object forces lock fattening.
1063 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001064 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001065 /* Make sure that 'self' holds the lock.
1066 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001067 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001068 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1069 "object not locked by thread before notifyAll()");
1070 return;
1071 }
1072
1073 /* no-op; there are no waiters to notify.
1074 */
1075 } else {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001076 /* It's a fat lock.
1077 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001078 notifyAllMonitor(self, LW_MONITOR(thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001079 }
1080}
1081
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001082/*
1083 * This implements java.lang.Thread.sleep(long msec, int nsec).
1084 *
1085 * The sleep is interruptible by other threads, which means we can't just
1086 * plop into an OS sleep call. (We probably could if we wanted to send
1087 * signals around and rely on EINTR, but that's inefficient and relies
1088 * on native code respecting our signal mask.)
1089 *
1090 * We have to do all of this stuff for Object.wait() as well, so it's
1091 * easiest to just sleep on a private Monitor.
1092 *
1093 * It appears that we want sleep(0,0) to go through the motions of sleeping
1094 * for a very short duration, rather than just returning.
1095 */
1096void dvmThreadSleep(u8 msec, u4 nsec)
1097{
1098 Thread* self = dvmThreadSelf();
1099 Monitor* mon = gDvm.threadSleepMon;
1100
1101 /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */
1102 if (msec == 0 && nsec == 0)
1103 nsec++;
1104
1105 lockMonitor(self, mon);
1106 waitMonitor(self, mon, msec, nsec, true);
1107 unlockMonitor(self, mon);
1108}
1109
1110/*
1111 * Implement java.lang.Thread.interrupt().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001112 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001113void dvmThreadInterrupt(Thread* thread)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001114{
1115 Monitor* mon;
1116
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001117 assert(thread != NULL);
1118
1119 pthread_mutex_lock(&thread->waitMutex);
1120
1121 /*
1122 * If the interrupted flag is already set no additional action is
1123 * required.
1124 */
1125 if (thread->interrupted == true) {
1126 pthread_mutex_unlock(&thread->waitMutex);
1127 return;
1128 }
1129
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001130 /*
1131 * Raise the "interrupted" flag. This will cause it to bail early out
1132 * of the next wait() attempt, if it's not currently waiting on
1133 * something.
1134 */
1135 thread->interrupted = true;
1136 MEM_BARRIER();
1137
1138 /*
1139 * Is the thread waiting?
1140 *
1141 * Note that fat vs. thin doesn't matter here; waitMonitor
1142 * is only set when a thread actually waits on a monitor,
1143 * which implies that the monitor has already been fattened.
1144 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001145 if (thread->waitMonitor != NULL) {
1146 pthread_cond_signal(&thread->waitCond);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001147 }
1148
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001149 pthread_mutex_unlock(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001150}
1151
Carl Shapiro94338aa2009-12-21 11:42:59 -08001152u4 dvmIdentityHashCode(Object *obj)
1153{
1154 return (u4)obj;
1155}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001156
1157#ifdef WITH_DEADLOCK_PREDICTION
1158/*
1159 * ===========================================================================
1160 * Deadlock prediction
1161 * ===========================================================================
1162 */
1163/*
1164The idea is to predict the possibility of deadlock by recording the order
1165in which monitors are acquired. If we see an attempt to acquire a lock
1166out of order, we can identify the locks and offending code.
1167
1168To make this work, we need to keep track of the locks held by each thread,
1169and create history trees for each lock. When a thread tries to acquire
1170a new lock, we walk through the "history children" of the lock, looking
1171for a match with locks the thread already holds. If we find a match,
1172it means the thread has made a request that could result in a deadlock.
1173
1174To support recursive locks, we always allow re-locking a currently-held
1175lock, and maintain a recursion depth count.
1176
1177An ASCII-art example, where letters represent Objects:
1178
1179 A
1180 /|\
1181 / | \
1182 B | D
1183 \ |
1184 \|
1185 C
1186
1187The above is the tree we'd have after handling Object synchronization
1188sequences "ABC", "AC", "AD". A has three children, {B, C, D}. C is also
1189a child of B. (The lines represent pointers between parent and child.
1190Every node can have multiple parents and multiple children.)
1191
1192If we hold AC, and want to lock B, we recursively search through B's
1193children to see if A or C appears. It does, so we reject the attempt.
1194(A straightforward way to implement it: add a link from C to B, then
1195determine whether the graph starting at B contains a cycle.)
1196
1197If we hold AC and want to lock D, we would succeed, creating a new link
1198from C to D.
1199
1200The lock history and a stack trace is attached to the Object's Monitor
1201struct, which means we need to fatten every Object we lock (thin locking
1202is effectively disabled). If we don't need the stack trace we can
1203avoid fattening the leaf nodes, only fattening objects that need to hold
1204history trees.
1205
1206Updates to Monitor structs are only allowed for the thread that holds
1207the Monitor, so we actually do most of our deadlock prediction work after
1208the lock has been acquired.
1209
1210When an object with a monitor is GCed, we need to remove it from the
1211history trees. There are two basic approaches:
1212 (1) For through the entire set of known monitors, search all child
1213 lists for the object in question. This is rather slow, resulting
1214 in GC passes that take upwards of 10 seconds to complete.
1215 (2) Maintain "parent" pointers in each node. Remove the entries as
1216 required. This requires additional storage and maintenance for
1217 every operation, but is significantly faster at GC time.
1218For each GCed object, we merge all of the object's children into each of
1219the object's parents.
1220*/
1221
1222#if !defined(WITH_MONITOR_TRACKING)
1223# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING"
1224#endif
1225
1226/*
1227 * Clear out the contents of an ExpandingObjectList, freeing any
1228 * dynamic allocations.
1229 */
1230static void expandObjClear(ExpandingObjectList* pList)
1231{
1232 if (pList->list != NULL) {
1233 free(pList->list);
1234 pList->list = NULL;
1235 }
1236 pList->alloc = pList->count = 0;
1237}
1238
1239/*
1240 * Get the number of objects currently stored in the list.
1241 */
1242static inline int expandBufGetCount(const ExpandingObjectList* pList)
1243{
1244 return pList->count;
1245}
1246
1247/*
1248 * Get the Nth entry from the list.
1249 */
1250static inline Object* expandBufGetEntry(const ExpandingObjectList* pList,
1251 int i)
1252{
1253 return pList->list[i];
1254}
1255
1256/*
1257 * Add a new entry to the list.
1258 *
1259 * We don't check for or try to enforce uniqueness. It's expected that
1260 * the higher-level code does this for us.
1261 */
1262static void expandObjAddEntry(ExpandingObjectList* pList, Object* obj)
1263{
1264 if (pList->count == pList->alloc) {
1265 /* time to expand */
1266 Object** newList;
1267
1268 if (pList->alloc == 0)
1269 pList->alloc = 4;
1270 else
1271 pList->alloc *= 2;
1272 LOGVV("expanding %p to %d\n", pList, pList->alloc);
1273 newList = realloc(pList->list, pList->alloc * sizeof(Object*));
1274 if (newList == NULL) {
1275 LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc);
1276 dvmAbort();
1277 }
1278 pList->list = newList;
1279 }
1280
1281 pList->list[pList->count++] = obj;
1282}
1283
1284/*
1285 * Returns "true" if the element was successfully removed.
1286 */
1287static bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj)
1288{
1289 int i;
1290
1291 for (i = pList->count-1; i >= 0; i--) {
1292 if (pList->list[i] == obj)
1293 break;
1294 }
1295 if (i < 0)
1296 return false;
1297
1298 if (i != pList->count-1) {
1299 /*
1300 * The order of elements is not important, so we just copy the
1301 * last entry into the new slot.
1302 */
1303 //memmove(&pList->list[i], &pList->list[i+1],
1304 // (pList->count-1 - i) * sizeof(pList->list[0]));
1305 pList->list[i] = pList->list[pList->count-1];
1306 }
1307
1308 pList->count--;
1309 pList->list[pList->count] = (Object*) 0xdecadead;
1310 return true;
1311}
1312
1313/*
1314 * Returns "true" if "obj" appears in the list.
1315 */
1316static bool expandObjHas(const ExpandingObjectList* pList, Object* obj)
1317{
1318 int i;
1319
1320 for (i = 0; i < pList->count; i++) {
1321 if (pList->list[i] == obj)
1322 return true;
1323 }
1324 return false;
1325}
1326
1327/*
1328 * Print the list contents to stdout. For debugging.
1329 */
1330static void expandObjDump(const ExpandingObjectList* pList)
1331{
1332 int i;
1333 for (i = 0; i < pList->count; i++)
1334 printf(" %p", pList->list[i]);
1335}
1336
1337/*
1338 * Check for duplicate entries. Returns the index of the first instance
1339 * of the duplicated value, or -1 if no duplicates were found.
1340 */
1341static int expandObjCheckForDuplicates(const ExpandingObjectList* pList)
1342{
1343 int i, j;
1344 for (i = 0; i < pList->count-1; i++) {
1345 for (j = i + 1; j < pList->count; j++) {
1346 if (pList->list[i] == pList->list[j]) {
1347 return i;
1348 }
1349 }
1350 }
1351
1352 return -1;
1353}
1354
1355
1356/*
1357 * Determine whether "child" appears in the list of objects associated
1358 * with the Monitor in "parent". If "parent" is a thin lock, we return
1359 * false immediately.
1360 */
1361static bool objectInChildList(const Object* parent, Object* child)
1362{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001363 u4 lock = parent->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001364 if (!IS_LOCK_FAT(&lock)) {
1365 //LOGI("on thin\n");
1366 return false;
1367 }
1368
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001369 return expandObjHas(&LW_MONITOR(lock)->historyChildren, child);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001370}
1371
1372/*
1373 * Print the child list.
1374 */
1375static void dumpKids(Object* parent)
1376{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001377 Monitor* mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001378
1379 printf("Children of %p:", parent);
1380 expandObjDump(&mon->historyChildren);
1381 printf("\n");
1382}
1383
1384/*
1385 * Add "child" to the list of children in "parent", and add "parent" to
1386 * the list of parents in "child".
1387 */
1388static void linkParentToChild(Object* parent, Object* child)
1389{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001390 //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for merge
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001391 assert(IS_LOCK_FAT(&parent->lock));
1392 assert(IS_LOCK_FAT(&child->lock));
1393 assert(parent != child);
1394 Monitor* mon;
1395
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001396 mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001397 assert(!expandObjHas(&mon->historyChildren, child));
1398 expandObjAddEntry(&mon->historyChildren, child);
1399
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001400 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001401 assert(!expandObjHas(&mon->historyParents, parent));
1402 expandObjAddEntry(&mon->historyParents, parent);
1403}
1404
1405
1406/*
1407 * Remove "child" from the list of children in "parent".
1408 */
1409static void unlinkParentFromChild(Object* parent, Object* child)
1410{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001411 //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for GC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001412 assert(IS_LOCK_FAT(&parent->lock));
1413 assert(IS_LOCK_FAT(&child->lock));
1414 assert(parent != child);
1415 Monitor* mon;
1416
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001417 mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001418 if (!expandObjRemoveEntry(&mon->historyChildren, child)) {
1419 LOGW("WARNING: child %p not found in parent %p\n", child, parent);
1420 }
1421 assert(!expandObjHas(&mon->historyChildren, child));
1422 assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0);
1423
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001424 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001425 if (!expandObjRemoveEntry(&mon->historyParents, parent)) {
1426 LOGW("WARNING: parent %p not found in child %p\n", parent, child);
1427 }
1428 assert(!expandObjHas(&mon->historyParents, parent));
1429 assert(expandObjCheckForDuplicates(&mon->historyParents) < 0);
1430}
1431
1432
1433/*
1434 * Log the monitors held by the current thread. This is done as part of
1435 * flagging an error.
1436 */
1437static void logHeldMonitors(Thread* self)
1438{
1439 char* name = NULL;
1440
1441 name = dvmGetThreadName(self);
1442 LOGW("Monitors currently held by thread (threadid=%d '%s')\n",
1443 self->threadId, name);
1444 LOGW("(most-recently-acquired on top):\n");
1445 free(name);
1446
1447 LockedObjectData* lod = self->pLockedObjects;
1448 while (lod != NULL) {
1449 LOGW("--- object %p[%d] (%s)\n",
1450 lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
1451 dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth);
1452
1453 lod = lod->next;
1454 }
1455}
1456
1457/*
1458 * Recursively traverse the object hierarchy starting at "obj". We mark
1459 * ourselves on entry and clear the mark on exit. If we ever encounter
1460 * a marked object, we have a cycle.
1461 *
1462 * Returns "true" if all is well, "false" if we found a cycle.
1463 */
1464static bool traverseTree(Thread* self, const Object* obj)
1465{
1466 assert(IS_LOCK_FAT(&obj->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001467 Monitor* mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001468
1469 /*
1470 * Have we been here before?
1471 */
1472 if (mon->historyMark) {
1473 int* rawStackTrace;
1474 int stackDepth;
1475
1476 LOGW("%s\n", kStartBanner);
1477 LOGW("Illegal lock attempt:\n");
1478 LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1479
1480 rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth);
1481 dvmLogRawStackTrace(rawStackTrace, stackDepth);
1482 free(rawStackTrace);
1483
1484 LOGW(" ");
1485 logHeldMonitors(self);
1486
1487 LOGW(" ");
1488 LOGW("Earlier, the following lock order (from last to first) was\n");
1489 LOGW("established -- stack trace is from first successful lock):\n");
1490 return false;
1491 }
1492 mon->historyMark = true;
1493
1494 /*
1495 * Examine the children. We do NOT hold these locks, so they might
1496 * very well transition from thin to fat or change ownership while
1497 * we work.
1498 *
1499 * NOTE: we rely on the fact that they cannot revert from fat to thin
1500 * while we work. This is currently a safe assumption.
1501 *
1502 * We can safely ignore thin-locked children, because by definition
1503 * they have no history and are leaf nodes. In the current
1504 * implementation we always fatten the locks to provide a place to
1505 * hang the stack trace.
1506 */
1507 ExpandingObjectList* pList = &mon->historyChildren;
1508 int i;
1509 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1510 const Object* child = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001511 u4 lock = child->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001512 if (!IS_LOCK_FAT(&lock))
1513 continue;
1514 if (!traverseTree(self, child)) {
1515 LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1516 dvmLogRawStackTrace(mon->historyRawStackTrace,
1517 mon->historyStackDepth);
1518 mon->historyMark = false;
1519 return false;
1520 }
1521 }
1522
1523 mon->historyMark = false;
1524
1525 return true;
1526}
1527
1528/*
1529 * Update the deadlock prediction tree, based on the current thread
1530 * acquiring "acqObj". This must be called before the object is added to
1531 * the thread's list of held monitors.
1532 *
1533 * If the thread already holds the lock (recursion), or this is a known
1534 * lock configuration, we return without doing anything. Otherwise, we add
1535 * a link from the most-recently-acquired lock in this thread to "acqObj"
1536 * after ensuring that the parent lock is "fat".
1537 *
1538 * This MUST NOT be called while a GC is in progress in another thread,
1539 * because we assume exclusive access to history trees in owned monitors.
1540 */
1541static void updateDeadlockPrediction(Thread* self, Object* acqObj)
1542{
1543 LockedObjectData* lod;
1544 LockedObjectData* mrl;
1545
1546 /*
1547 * Quick check for recursive access.
1548 */
1549 lod = dvmFindInMonitorList(self, acqObj);
1550 if (lod != NULL) {
1551 LOGV("+++ DP: recursive %p\n", acqObj);
1552 return;
1553 }
1554
1555 /*
1556 * Make the newly-acquired object's monitor "fat". In some ways this
1557 * isn't strictly necessary, but we need the GC to tell us when
1558 * "interesting" objects go away, and right now the only way to make
1559 * an object look interesting is to give it a monitor.
1560 *
1561 * This also gives us a place to hang a stack trace.
1562 *
1563 * Our thread holds the lock, so we're allowed to rewrite the lock
1564 * without worrying that something will change out from under us.
1565 */
1566 if (!IS_LOCK_FAT(&acqObj->lock)) {
1567 LOGVV("fattening lockee %p (recur=%d)\n",
Carl Shapiro94338aa2009-12-21 11:42:59 -08001568 acqObj, LW_LOCK_COUNT(acqObj->lock.thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001569 Monitor* newMon = dvmCreateMonitor(acqObj);
1570 lockMonitor(self, newMon); // can't stall, don't need VMWAIT
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001571 newMon->lockCount += LW_LOCK_COUNT(acqObj->lock);
1572 u4 hashState = LW_HASH_STATE(acqObj->lock) << LW_HASH_STATE_SHIFT;
1573 acqObj->lock = (u4)newMon | hashState | LW_SHAPE_FAT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001574 }
1575
1576 /* if we don't have a stack trace for this monitor, establish one */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001577 if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) {
1578 Monitor* mon = LW_MONITOR(acqObj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001579 mon->historyRawStackTrace = dvmFillInStackTraceRaw(self,
1580 &mon->historyStackDepth);
1581 }
1582
1583 /*
1584 * We need to examine and perhaps modify the most-recently-locked
1585 * monitor. We own that, so there's no risk of another thread
1586 * stepping on us.
1587 *
1588 * Retrieve the most-recently-locked entry from our thread.
1589 */
1590 mrl = self->pLockedObjects;
1591 if (mrl == NULL)
1592 return; /* no other locks held */
1593
1594 /*
1595 * Do a quick check to see if "acqObj" is a direct descendant. We can do
1596 * this without holding the global lock because of our assertion that
1597 * a GC is not running in parallel -- nobody except the GC can
1598 * modify a history list in a Monitor they don't own, and we own "mrl".
1599 * (There might be concurrent *reads*, but no concurrent *writes.)
1600 *
1601 * If we find it, this is a known good configuration, and we're done.
1602 */
1603 if (objectInChildList(mrl->obj, acqObj))
1604 return;
1605
1606 /*
1607 * "mrl" is going to need to have a history tree. If it's currently
1608 * a thin lock, we make it fat now. The thin lock might have a
1609 * nonzero recursive lock count, which we need to carry over.
1610 *
1611 * Our thread holds the lock, so we're allowed to rewrite the lock
1612 * without worrying that something will change out from under us.
1613 */
1614 if (!IS_LOCK_FAT(&mrl->obj->lock)) {
1615 LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n",
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001616 mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001617 Monitor* newMon = dvmCreateMonitor(mrl->obj);
1618 lockMonitor(self, newMon); // can't stall, don't need VMWAIT
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001619 newMon->lockCount += LW_LOCK_COUNT(mrl->obj->lock);
1620 u4 hashState = LW_HASH_STATE(mrl->obj->lock) << LW_HASH_STATE_SHIFT;
1621 mrl->obj->lock = (u4)newMon | hashState | LW_SHAPE_FAT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001622 }
1623
1624 /*
1625 * We haven't seen this configuration before. We need to scan down
1626 * acqObj's tree to see if any of the monitors in self->pLockedObjects
1627 * appear. We grab a global lock before traversing or updating the
1628 * history list.
1629 *
1630 * If we find a match for any of our held locks, we know that the lock
1631 * has previously been acquired *after* acqObj, and we throw an error.
1632 *
1633 * The easiest way to do this is to create a link from "mrl" to "acqObj"
1634 * and do a recursive traversal, marking nodes as we cross them. If
1635 * we cross one a second time, we have a cycle and can throw an error.
1636 * (We do the flag-clearing traversal before adding the new link, so
1637 * that we're guaranteed to terminate.)
1638 *
1639 * If "acqObj" is a thin lock, it has no history, and we can create a
1640 * link to it without additional checks. [ We now guarantee that it's
1641 * always fat. ]
1642 */
1643 bool failed = false;
1644 dvmLockMutex(&gDvm.deadlockHistoryLock);
1645 linkParentToChild(mrl->obj, acqObj);
1646 if (!traverseTree(self, acqObj)) {
1647 LOGW("%s\n", kEndBanner);
1648 failed = true;
1649
1650 /* remove the entry so we're still okay when in "warning" mode */
1651 unlinkParentFromChild(mrl->obj, acqObj);
1652 }
1653 dvmUnlockMutex(&gDvm.deadlockHistoryLock);
1654
1655 if (failed) {
1656 switch (gDvm.deadlockPredictMode) {
1657 case kDPErr:
1658 dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL);
1659 break;
1660 case kDPAbort:
1661 LOGE("Aborting due to potential deadlock\n");
1662 dvmAbort();
1663 break;
1664 default:
1665 /* warn only */
1666 break;
1667 }
1668 }
1669}
1670
1671/*
1672 * We're removing "child" from existence. We want to pull all of
1673 * child's children into "parent", filtering out duplicates. This is
1674 * called during the GC.
1675 *
1676 * This does not modify "child", which might have multiple parents.
1677 */
1678static void mergeChildren(Object* parent, const Object* child)
1679{
1680 Monitor* mon;
1681 int i;
1682
1683 assert(IS_LOCK_FAT(&child->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001684 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001685 ExpandingObjectList* pList = &mon->historyChildren;
1686
1687 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1688 Object* grandChild = expandBufGetEntry(pList, i);
1689
1690 if (!objectInChildList(parent, grandChild)) {
1691 LOGVV("+++ migrating %p link to %p\n", grandChild, parent);
1692 linkParentToChild(parent, grandChild);
1693 } else {
1694 LOGVV("+++ parent %p already links to %p\n", parent, grandChild);
1695 }
1696 }
1697}
1698
1699/*
1700 * An object with a fat lock is being collected during a GC pass. We
1701 * want to remove it from any lock history trees that it is a part of.
1702 *
1703 * This may require updating the history trees in several monitors. The
1704 * monitor semantics guarantee that no other thread will be accessing
1705 * the history trees at the same time.
1706 */
1707static void removeCollectedObject(Object* obj)
1708{
1709 Monitor* mon;
1710
1711 LOGVV("+++ collecting %p\n", obj);
1712
1713#if 0
1714 /*
1715 * We're currently running through the entire set of known monitors.
1716 * This can be somewhat slow. We may want to keep lists of parents
1717 * in each child to speed up GC.
1718 */
1719 mon = gDvm.monitorList;
1720 while (mon != NULL) {
1721 Object* parent = mon->obj;
1722 if (parent != NULL) { /* value nulled for deleted entries */
1723 if (objectInChildList(parent, obj)) {
1724 LOGVV("removing child %p from parent %p\n", obj, parent);
1725 unlinkParentFromChild(parent, obj);
1726 mergeChildren(parent, obj);
1727 }
1728 }
1729 mon = mon->next;
1730 }
1731#endif
1732
1733 /*
1734 * For every parent of this object:
1735 * - merge all of our children into the parent's child list (creates
1736 * a two-way link between parent and child)
1737 * - remove ourselves from the parent's child list
1738 */
1739 ExpandingObjectList* pList;
1740 int i;
1741
1742 assert(IS_LOCK_FAT(&obj->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001743 mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001744 pList = &mon->historyParents;
1745 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1746 Object* parent = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001747 Monitor* parentMon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001748
1749 if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) {
1750 LOGW("WARNING: child %p not found in parent %p\n", obj, parent);
1751 }
1752 assert(!expandObjHas(&parentMon->historyChildren, obj));
1753
1754 mergeChildren(parent, obj);
1755 }
1756
1757 /*
1758 * For every child of this object:
1759 * - remove ourselves from the child's parent list
1760 */
1761 pList = &mon->historyChildren;
1762 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1763 Object* child = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001764 Monitor* childMon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001765
1766 if (!expandObjRemoveEntry(&childMon->historyParents, obj)) {
1767 LOGW("WARNING: parent %p not found in child %p\n", obj, child);
1768 }
1769 assert(!expandObjHas(&childMon->historyParents, obj));
1770 }
1771}
1772
1773#endif /*WITH_DEADLOCK_PREDICTION*/
1774