blob: c0b3d08d138d793cda5d3e5e4826d026cb69f41e [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/*
179 * Release a Monitor.
180 */
181static void releaseMonitor(Monitor* mon)
182{
183 // TODO
184}
185
186/*
187 * Free the monitor list. Only used when shutting the VM down.
188 */
189void dvmFreeMonitorList(void)
190{
191 Monitor* mon;
192 Monitor* nextMon;
193
194 mon = gDvm.monitorList;
195 while (mon != NULL) {
196 nextMon = mon->next;
197
198#ifdef WITH_DEADLOCK_PREDICTION
199 expandObjClear(&mon->historyChildren);
200 expandObjClear(&mon->historyParents);
201 free(mon->historyRawStackTrace);
202#endif
203 free(mon);
204 mon = nextMon;
205 }
206}
207
208/*
209 * Log some info about our monitors.
210 */
211void dvmDumpMonitorInfo(const char* msg)
212{
213#if QUIET_ZYGOTE_MONITOR
214 if (gDvm.zygote) {
215 return;
216 }
217#endif
218
219 int totalCount;
220 int liveCount;
221
222 totalCount = liveCount = 0;
223 Monitor* mon = gDvm.monitorList;
224 while (mon != NULL) {
225 totalCount++;
226 if (mon->obj != NULL)
227 liveCount++;
228 mon = mon->next;
229 }
230
231 LOGD("%s: monitor list has %d entries (%d live)\n",
232 msg, totalCount, liveCount);
233}
234
235/*
236 * Get the object that a monitor is part of.
237 */
238Object* dvmGetMonitorObject(Monitor* mon)
239{
240 if (mon == NULL)
241 return NULL;
242 else
243 return mon->obj;
244}
245
246/*
247 * Checks whether the given thread holds the given
248 * objects's lock.
249 */
250bool dvmHoldsLock(Thread* thread, Object* obj)
251{
Carl Shapiro94338aa2009-12-21 11:42:59 -0800252 u4 thin;
253
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800254 if (thread == NULL || obj == NULL) {
255 return false;
256 }
257
258 /* Since we're reading the lock value multiple times,
259 * latch it so that it doesn't change out from under
260 * us if we get preempted.
261 */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800262 thin = obj->lock;
Carl Shapiro94338aa2009-12-21 11:42:59 -0800263 if (LW_SHAPE(thin) == LW_SHAPE_FAT) {
264 return thread == LW_MONITOR(thin)->owner;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800265 } else {
Carl Shapiro94338aa2009-12-21 11:42:59 -0800266 return thread->threadId == LW_LOCK_OWNER(thin);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800267 }
268}
269
270/*
271 * Free the monitor associated with an object and make the object's lock
272 * thin again. This is called during garbage collection.
273 */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800274void dvmFreeObjectMonitor_internal(u4 *lock)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800275{
276 Monitor *mon;
277
278 /* The macro that wraps this function checks IS_LOCK_FAT() first.
279 */
280 assert(IS_LOCK_FAT(lock));
281
282#ifdef WITH_DEADLOCK_PREDICTION
283 if (gDvm.deadlockPredictMode != kDPOff)
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800284 removeCollectedObject(LW_MONITOR(*lock)->obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800285#endif
286
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800287 mon = LW_MONITOR(*lock);
288 *lock = DVM_LOCK_INITIAL_THIN_VALUE;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800289
290 /* This lock is associated with an object
291 * that's being swept. The only possible way
292 * anyone could be holding this lock would be
293 * if some JNI code locked but didn't unlock
294 * the object, in which case we've got some bad
295 * native code somewhere.
296 */
297 assert(pthread_mutex_trylock(&mon->lock) == 0);
298 pthread_mutex_destroy(&mon->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800299#if 1
300//TODO: unlink from the monitor list (would require a lock)
301// (might not -- the GC suspension may be enough)
302 {
303 Monitor *next;
304 next = mon->next;
305#ifdef WITH_DEADLOCK_PREDICTION
306 expandObjClear(&mon->historyChildren);
307 expandObjClear(&mon->historyParents);
308 free(mon->historyRawStackTrace);
309#endif
310 memset(mon, 0, sizeof (*mon));
311 mon->next = next;
312 }
313//free(mon);
314#endif
315}
316
317
318/*
319 * Lock a monitor.
320 */
321static void lockMonitor(Thread* self, Monitor* mon)
322{
323 int cc;
324
325 if (mon->owner == self) {
326 mon->lockCount++;
327 } else {
328 ThreadStatus oldStatus;
329
330 if (pthread_mutex_trylock(&mon->lock) != 0) {
331 /* mutex is locked, switch to wait status and sleep on it */
332 oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
333 cc = pthread_mutex_lock(&mon->lock);
334 assert(cc == 0);
335 dvmChangeStatus(self, oldStatus);
336 }
337
338 mon->owner = self;
339 assert(mon->lockCount == 0);
340
341 /*
342 * "waiting", "notifying", and "interrupting" could all be nonzero
343 * if we're locking an object on which other threads are waiting.
344 * Nothing worth assert()ing about here.
345 */
346 }
347}
348
349/*
350 * Try to lock a monitor.
351 *
352 * Returns "true" on success.
353 */
354static bool tryLockMonitor(Thread* self, Monitor* mon)
355{
356 int cc;
357
358 if (mon->owner == self) {
359 mon->lockCount++;
360 return true;
361 } else {
362 cc = pthread_mutex_trylock(&mon->lock);
363 if (cc == 0) {
364 mon->owner = self;
365 assert(mon->lockCount == 0);
366 return true;
367 } else {
368 return false;
369 }
370 }
371}
372
373
374/*
375 * Unlock a monitor.
376 *
377 * Returns true if the unlock succeeded.
378 * If the unlock failed, an exception will be pending.
379 */
380static bool unlockMonitor(Thread* self, Monitor* mon)
381{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800382 assert(self != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800383 assert(mon != NULL); // can this happen?
384
385 if (mon->owner == self) {
386 /*
387 * We own the monitor, so nobody else can be in here.
388 */
389 if (mon->lockCount == 0) {
390 int cc;
391 mon->owner = NULL;
392 cc = pthread_mutex_unlock(&mon->lock);
393 assert(cc == 0);
394 } else {
395 mon->lockCount--;
396 }
397 } else {
398 /*
399 * We don't own this, so we're not allowed to unlock it.
400 * The JNI spec says that we should throw IllegalMonitorStateException
401 * in this case.
402 */
403 if (mon->owner == NULL) {
404 //LOGW("Unlock fat %p: not owned\n", mon->obj);
405 } else {
406 //LOGW("Unlock fat %p: id %d vs %d\n",
407 // mon->obj, mon->owner->threadId, self->threadId);
408 }
409 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
410 "unlock of unowned monitor");
411 return false;
412 }
413 return true;
414}
415
416/*
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800417 * Checks the wait set for circular structure. Returns 0 if the list
Carl Shapirob4539192010-01-04 16:50:00 -0800418 * is not circular. Otherwise, returns 1. Used only by asserts.
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800419 */
420static int waitSetCheck(Monitor *mon)
421{
422 Thread *fast, *slow;
423 size_t n;
424
425 assert(mon != NULL);
426 fast = slow = mon->waitSet;
427 n = 0;
428 for (;;) {
429 if (fast == NULL) return 0;
430 if (fast->waitNext == NULL) return 0;
Carl Shapiro5f56e672010-01-05 20:38:03 -0800431 if (fast == slow && n > 0) return 1;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800432 n += 2;
433 fast = fast->waitNext->waitNext;
434 slow = slow->waitNext;
435 }
436}
437
438/*
439 * Links a thread into a monitor's wait set.
440 */
441static void waitSetAppend(Monitor *mon, Thread *thread)
442{
443 Thread *elt;
444
445 assert(mon != NULL);
446 assert(thread != NULL);
447 assert(thread->waitNext == NULL);
448 assert(waitSetCheck(mon) == 0);
449 if (mon->waitSet == NULL) {
450 mon->waitSet = thread;
451 return;
452 }
453 elt = mon->waitSet;
454 while (elt->waitNext != NULL) {
455 elt = elt->waitNext;
456 }
457 elt->waitNext = thread;
458}
459
460/*
461 * Unlinks a thread from a monitor's wait set.
462 */
463static void waitSetRemove(Monitor *mon, Thread *thread)
464{
465 Thread *elt;
466
467 assert(mon != NULL);
468 assert(thread != NULL);
469 assert(waitSetCheck(mon) == 0);
470 if (mon->waitSet == NULL) {
471 return;
472 }
473 if (mon->waitSet == thread) {
474 mon->waitSet = thread->waitNext;
475 thread->waitNext = NULL;
476 return;
477 }
478 elt = mon->waitSet;
479 while (elt->waitNext != NULL) {
480 if (elt->waitNext == thread) {
481 elt->waitNext = thread->waitNext;
482 thread->waitNext = NULL;
483 return;
484 }
485 elt = elt->waitNext;
486 }
487}
488
Carl Shapirob4539192010-01-04 16:50:00 -0800489/*
490 * Converts the given relative waiting time into an absolute time.
491 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800492static void absoluteTime(s8 msec, s4 nsec, struct timespec *ts)
493{
494 s8 endSec;
495
496#ifdef HAVE_TIMEDWAIT_MONOTONIC
497 clock_gettime(CLOCK_MONOTONIC, ts);
498#else
499 {
500 struct timeval tv;
501 gettimeofday(&tv, NULL);
502 ts->tv_sec = tv.tv_sec;
503 ts->tv_nsec = tv.tv_usec * 1000;
504 }
505#endif
506 endSec = ts->tv_sec + msec / 1000;
507 if (endSec >= 0x7fffffff) {
508 LOGV("NOTE: end time exceeds epoch\n");
509 endSec = 0x7ffffffe;
510 }
511 ts->tv_sec = endSec;
512 ts->tv_nsec = (ts->tv_nsec + (msec % 1000) * 1000000) + nsec;
513
514 /* catch rollover */
515 if (ts->tv_nsec >= 1000000000L) {
516 ts->tv_sec++;
517 ts->tv_nsec -= 1000000000L;
518 }
519}
520
521/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800522 * Wait on a monitor until timeout, interrupt, or notification. Used for
523 * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join().
524 *
525 * If another thread calls Thread.interrupt(), we throw InterruptedException
526 * and return immediately if one of the following are true:
527 * - blocked in wait(), wait(long), or wait(long, int) methods of Object
528 * - blocked in join(), join(long), or join(long, int) methods of Thread
529 * - blocked in sleep(long), or sleep(long, int) methods of Thread
530 * Otherwise, we set the "interrupted" flag.
531 *
532 * Checks to make sure that "nsec" is in the range 0-999999
533 * (i.e. fractions of a millisecond) and throws the appropriate
534 * exception if it isn't.
535 *
536 * The spec allows "spurious wakeups", and recommends that all code using
537 * Object.wait() do so in a loop. This appears to derive from concerns
538 * about pthread_cond_wait() on multiprocessor systems. Some commentary
539 * on the web casts doubt on whether these can/should occur.
540 *
541 * Since we're allowed to wake up "early", we clamp extremely long durations
542 * to return at the end of the 32-bit time epoch.
543 */
544static void waitMonitor(Thread* self, Monitor* mon, s8 msec, s4 nsec,
545 bool interruptShouldThrow)
546{
547 struct timespec ts;
548 bool wasInterrupted = false;
549 bool timed;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800550 int ret;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800551
Carl Shapiro71938022009-12-22 13:49:53 -0800552 assert(self != NULL);
553 assert(mon != NULL);
554
Carl Shapiro94338aa2009-12-21 11:42:59 -0800555 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800556 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800557 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
558 "object not locked by thread before wait()");
559 return;
560 }
561
562 /*
563 * Enforce the timeout range.
564 */
565 if (msec < 0 || nsec < 0 || nsec > 999999) {
566 dvmThrowException("Ljava/lang/IllegalArgumentException;",
567 "timeout arguments out of range");
568 return;
569 }
570
571 /*
572 * Compute absolute wakeup time, if necessary.
573 */
574 if (msec == 0 && nsec == 0) {
575 timed = false;
576 } else {
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800577 absoluteTime(msec, nsec, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800578 timed = true;
579 }
580
581 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800582 * Add ourselves to the set of threads waiting on this monitor, and
583 * release our hold. We need to let it go even if we're a few levels
584 * deep in a recursive lock, and we need to restore that later.
585 *
586 * The order of operations here isn't significant, because we still
587 * hold the pthread mutex.
588 */
589 int prevLockCount;
590
591 prevLockCount = mon->lockCount;
592 mon->lockCount = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800593 mon->owner = NULL;
594
595 /*
596 * Update thread status. If the GC wakes up, it'll ignore us, knowing
597 * that we won't touch any references in this state, and we'll check
598 * our suspend mode before we transition out.
599 */
600 if (timed)
601 dvmChangeStatus(self, THREAD_TIMED_WAIT);
602 else
603 dvmChangeStatus(self, THREAD_WAIT);
604
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800605 ret = pthread_mutex_lock(&self->waitMutex);
606 assert(ret == 0);
607
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800608 /*
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800609 * Set waitMonitor to the monitor object we will be waiting on.
610 * When waitMonitor is non-NULL a notifying or interrupting thread
611 * must signal the thread's waitCond to wake it up.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800612 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800613 assert(self->waitMonitor == NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800614 self->waitMonitor = mon;
615
616 /*
617 * Handle the case where the thread was interrupted before we called
618 * wait().
619 */
620 if (self->interrupted) {
621 wasInterrupted = true;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800622 self->waitMonitor = NULL;
623 pthread_mutex_unlock(&self->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800624 goto done;
625 }
626
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800627 waitSetAppend(mon, self);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800628
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800629 /*
630 * Release the monitor lock and wait for a notification or
631 * a timeout to occur.
632 */
633 pthread_mutex_unlock(&mon->lock);
634
635 if (!timed) {
636 ret = pthread_cond_wait(&self->waitCond, &self->waitMutex);
637 assert(ret == 0);
638 } else {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800639#ifdef HAVE_TIMEDWAIT_MONOTONIC
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800640 ret = pthread_cond_timedwait_monotonic(&self->waitCond, &self->waitMutex, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800641#else
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800642 ret = pthread_cond_timedwait(&self->waitCond, &self->waitMutex, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800643#endif
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800644 assert(ret == 0 || ret == ETIMEDOUT);
645 }
646 if (self->interrupted) {
647 wasInterrupted = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800648 }
649
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800650 self->interrupted = false;
651 self->waitMonitor = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800652
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800653 pthread_mutex_unlock(&self->waitMutex);
654
655 /* Reaquire the monitor lock. */
656 lockMonitor(self, mon);
657
658 waitSetRemove(mon, self);
659
660done:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800661 /*
662 * Put everything back. Again, we hold the pthread mutex, so the order
663 * here isn't significant.
664 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800665 mon->owner = self;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800666 mon->lockCount = prevLockCount;
667
668 /* set self->status back to THREAD_RUNNING, and self-suspend if needed */
669 dvmChangeStatus(self, THREAD_RUNNING);
670
671 if (wasInterrupted) {
672 /*
673 * We were interrupted while waiting, or somebody interrupted an
674 * un-interruptable thread earlier and we're bailing out immediately.
675 *
676 * The doc sayeth: "The interrupted status of the current thread is
677 * cleared when this exception is thrown."
678 */
679 self->interrupted = false;
680 if (interruptShouldThrow)
681 dvmThrowException("Ljava/lang/InterruptedException;", NULL);
682 }
683}
684
685/*
686 * Notify one thread waiting on this monitor.
687 */
688static void notifyMonitor(Thread* self, Monitor* mon)
689{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800690 Thread* thread;
691 int ret;
692
Carl Shapiro71938022009-12-22 13:49:53 -0800693 assert(self != NULL);
694 assert(mon != NULL);
695
Carl Shapiro94338aa2009-12-21 11:42:59 -0800696 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800697 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800698 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
699 "object not locked by thread before notify()");
700 return;
701 }
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800702 /* Signal the first thread in the wait set. */
703 if (mon->waitSet != NULL) {
704 thread = mon->waitSet;
705 mon->waitSet = thread->waitNext;
706 thread->waitNext = NULL;
707 pthread_mutex_lock(&thread->waitMutex);
708 /* Check to see if the thread is still waiting. */
709 if (thread->waitMonitor != NULL) {
710 pthread_cond_signal(&thread->waitCond);
711 }
712 pthread_mutex_unlock(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800713 }
714}
715
716/*
717 * Notify all threads waiting on this monitor.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800718 */
719static void notifyAllMonitor(Thread* self, Monitor* mon)
720{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800721 Thread* thread;
722 int ret;
723
Carl Shapiro71938022009-12-22 13:49:53 -0800724 assert(self != NULL);
725 assert(mon != NULL);
726
Carl Shapiro94338aa2009-12-21 11:42:59 -0800727 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800728 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800729 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
730 "object not locked by thread before notifyAll()");
731 return;
732 }
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800733 /* Signal all threads in the wait set. */
734 while (mon->waitSet != NULL) {
735 thread = mon->waitSet;
736 mon->waitSet = thread->waitNext;
737 thread->waitNext = NULL;
738 pthread_mutex_lock(&thread->waitMutex);
739 /* Check to see if the thread is still waiting. */
740 if (thread->waitMonitor != NULL) {
741 pthread_cond_signal(&thread->waitCond);
742 }
743 pthread_mutex_unlock(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800744 }
745}
746
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800747/*
748 * Implements monitorenter for "synchronized" stuff.
749 *
750 * This does not fail or throw an exception (unless deadlock prediction
751 * is enabled and set to "err" mode).
752 */
753void dvmLockObject(Thread* self, Object *obj)
754{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800755 volatile u4 *thinp = &obj->lock;
756 u4 hashState;
Carl Shapiro94338aa2009-12-21 11:42:59 -0800757 u4 thin;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800758 u4 threadId = self->threadId;
Carl Shapiro94338aa2009-12-21 11:42:59 -0800759 Monitor *mon;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800760
761 /* First, try to grab the lock as if it's thin;
762 * this is the common case and will usually succeed.
763 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800764 thin = threadId << LW_LOCK_OWNER_SHIFT;
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800765 thin |= LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800766 if (!ATOMIC_CMP_SWAP((int32_t *)thinp,
767 (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
Carl Shapiro94338aa2009-12-21 11:42:59 -0800768 (int32_t)thin)) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800769 /* The lock is either a thin lock held by someone (possibly 'self'),
770 * or a fat lock.
771 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800772 if (LW_LOCK_OWNER(*thinp) == threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800773 /* 'self' is already holding the thin lock; we can just
774 * bump the count. Atomic operations are not necessary
775 * because only the thread holding the lock is allowed
776 * to modify the Lock field.
777 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800778 *thinp += 1 << LW_LOCK_COUNT_SHIFT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800779 } else {
780 /* If this is a thin lock we need to spin on it, if it's fat
781 * we need to acquire the monitor.
782 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800783 if (LW_SHAPE(*thinp) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800784 ThreadStatus oldStatus;
785 static const unsigned long maxSleepDelay = 1 * 1024 * 1024;
786 unsigned long sleepDelay;
787
788 LOG_THIN("(%d) spin on lock 0x%08x: 0x%08x (0x%08x) 0x%08x\n",
789 threadId, (uint)&obj->lock,
Carl Shapiro94338aa2009-12-21 11:42:59 -0800790 DVM_LOCK_INITIAL_THIN_VALUE, *thinp, thin);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800791
792 /* The lock is still thin, but some other thread is
793 * holding it. Let the VM know that we're about
794 * to wait on another thread.
795 */
796 oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
797
798 /* Spin until the other thread lets go.
799 */
800 sleepDelay = 0;
801 do {
802 /* In addition to looking for an unlock,
803 * we need to watch out for some other thread
804 * fattening the lock behind our back.
805 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800806 while (LW_LOCK_OWNER(*thinp) != 0) {
807 if (LW_SHAPE(*thinp) == LW_SHAPE_FAT) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800808 /* The lock has been fattened already.
809 */
810 LOG_THIN("(%d) lock 0x%08x surprise-fattened\n",
811 threadId, (uint)&obj->lock);
812 dvmChangeStatus(self, oldStatus);
813 goto fat_lock;
814 }
815
816 if (sleepDelay == 0) {
817 sched_yield();
818 sleepDelay = 1 * 1000;
819 } else {
820 usleep(sleepDelay);
821 if (sleepDelay < maxSleepDelay / 2) {
822 sleepDelay *= 2;
823 }
824 }
825 }
Carl Shapiro94338aa2009-12-21 11:42:59 -0800826 thin = threadId << LW_LOCK_OWNER_SHIFT;
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800827 thin |= LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800828 } while (!ATOMIC_CMP_SWAP((int32_t *)thinp,
829 (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
Carl Shapiro94338aa2009-12-21 11:42:59 -0800830 (int32_t)thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800831 LOG_THIN("(%d) spin on lock done 0x%08x: "
832 "0x%08x (0x%08x) 0x%08x\n",
833 threadId, (uint)&obj->lock,
Carl Shapiro94338aa2009-12-21 11:42:59 -0800834 DVM_LOCK_INITIAL_THIN_VALUE, *thinp, thin);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800835
836 /* We've got the thin lock; let the VM know that we're
837 * done waiting.
838 */
839 dvmChangeStatus(self, oldStatus);
840
841 /* Fatten the lock. Note this relinquishes ownership.
842 * We could also create the monitor in an "owned" state
843 * to avoid "re-locking" it in fat_lock.
844 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800845 mon = dvmCreateMonitor(obj);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800846 hashState = LW_HASH_STATE(*thinp) << LW_HASH_STATE_SHIFT;
847 obj->lock = (u4)mon | hashState | LW_SHAPE_FAT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800848 LOG_THIN("(%d) lock 0x%08x fattened\n",
849 threadId, (uint)&obj->lock);
850
851 /* Fall through to acquire the newly fat lock.
852 */
853 }
854
855 /* The lock is already fat, which means
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800856 * that obj->lock is a regular (Monitor *).
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800857 */
858 fat_lock:
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800859 assert(LW_MONITOR(obj->lock) != NULL);
860 lockMonitor(self, LW_MONITOR(obj->lock));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800861 }
862 }
863 // else, the lock was acquired with the ATOMIC_CMP_SWAP().
864
865#ifdef WITH_DEADLOCK_PREDICTION
866 /*
867 * See if we were allowed to grab the lock at this time. We do it
868 * *after* acquiring the lock, rather than before, so that we can
869 * freely update the Monitor struct. This seems counter-intuitive,
870 * but our goal is deadlock *prediction* not deadlock *prevention*.
871 * (If we actually deadlock, the situation is easy to diagnose from
872 * a thread dump, so there's no point making a special effort to do
873 * the checks before the lock is held.)
874 *
875 * This needs to happen before we add the object to the thread's
876 * monitor list, so we can tell the difference between first-lock and
877 * re-lock.
878 *
879 * It's also important that we do this while in THREAD_RUNNING, so
880 * that we don't interfere with cleanup operations in the GC.
881 */
882 if (gDvm.deadlockPredictMode != kDPOff) {
883 if (self->status != THREAD_RUNNING) {
884 LOGE("Bad thread status (%d) in DP\n", self->status);
885 dvmDumpThread(self, false);
886 dvmAbort();
887 }
888 assert(!dvmCheckException(self));
889 updateDeadlockPrediction(self, obj);
890 if (dvmCheckException(self)) {
891 /*
892 * If we're throwing an exception here, we need to free the
893 * lock. We add the object to the thread's monitor list so the
894 * "unlock" code can remove it.
895 */
896 dvmAddToMonitorList(self, obj, false);
897 dvmUnlockObject(self, obj);
898 LOGV("--- unlocked, pending is '%s'\n",
899 dvmGetException(self)->clazz->descriptor);
900 }
901 }
902
903 /*
904 * Add the locked object, and the current stack trace, to the list
905 * held by the Thread object. If deadlock prediction isn't on,
906 * don't capture the stack trace.
907 */
908 dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff);
909#elif defined(WITH_MONITOR_TRACKING)
910 /*
911 * Add the locked object to the list held by the Thread object.
912 */
913 dvmAddToMonitorList(self, obj, false);
914#endif
915}
916
917/*
918 * Implements monitorexit for "synchronized" stuff.
919 *
920 * On failure, throws an exception and returns "false".
921 */
922bool dvmUnlockObject(Thread* self, Object *obj)
923{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800924 volatile u4 *thinp = &obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800925 u4 threadId = self->threadId;
Carl Shapiro94338aa2009-12-21 11:42:59 -0800926 u4 thin;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800927
928 /* Check the common case, where 'self' has locked 'obj' once, first.
929 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800930 thin = *thinp;
931 if (LW_LOCK_OWNER(thin) == threadId && LW_LOCK_COUNT(thin) == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800932 /* Unlock 'obj' by clearing our threadId from 'thin'.
933 * The lock protects the lock field itself, so it's
934 * safe to update non-atomically.
935 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800936 *thinp &= (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT);
937 } else if (LW_SHAPE(*thinp) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800938 /* If the object is locked, it had better be locked by us.
939 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800940 if (LW_LOCK_OWNER(*thinp) != threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800941 /* The JNI spec says that we should throw an exception
942 * in this case.
943 */
944 //LOGW("Unlock thin %p: id %d vs %d\n",
945 // obj, (*thinp & 0xfff), threadId);
946 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
947 "unlock of unowned monitor");
948 return false;
949 }
950
951 /* It's a thin lock, but 'self' has locked 'obj'
952 * more than once. Decrement the count.
953 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800954 *thinp -= 1 << LW_LOCK_COUNT_SHIFT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800955 } else {
956 /* It's a fat lock.
957 */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800958 assert(LW_MONITOR(obj->lock) != NULL);
959 if (!unlockMonitor(self, LW_MONITOR(obj->lock))) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800960 /* exception has been raised */
961 return false;
962 }
963 }
964
965#ifdef WITH_MONITOR_TRACKING
966 /*
967 * Remove the object from the Thread's list.
968 */
969 dvmRemoveFromMonitorList(self, obj);
970#endif
971
972 return true;
973}
974
975/*
976 * Object.wait(). Also called for class init.
977 */
978void dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec,
979 bool interruptShouldThrow)
980{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -0800981 Monitor* mon = LW_MONITOR(obj->lock);
982 u4 hashState;
983 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800984
985 /* If the lock is still thin, we need to fatten it.
986 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800987 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800988 /* Make sure that 'self' holds the lock.
989 */
Carl Shapiro94338aa2009-12-21 11:42:59 -0800990 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800991 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
992 "object not locked by thread before wait()");
993 return;
994 }
995
996 /* This thread holds the lock. We need to fatten the lock
997 * so 'self' can block on it. Don't update the object lock
998 * field yet, because 'self' needs to acquire the lock before
999 * any other thread gets a chance.
1000 */
1001 mon = dvmCreateMonitor(obj);
1002
1003 /* 'self' has actually locked the object one or more times;
1004 * make sure that the monitor reflects this.
1005 */
1006 lockMonitor(self, mon);
Carl Shapiro94338aa2009-12-21 11:42:59 -08001007 mon->lockCount = LW_LOCK_COUNT(thin);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001008 LOG_THIN("(%d) lock 0x%08x fattened by wait() to count %d\n",
1009 self->threadId, (uint)&obj->lock, mon->lockCount);
1010
Andy McFadden581bed72009-10-15 11:24:54 -07001011
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001012 /* Make the monitor public now that it's in the right state.
1013 */
Andy McFadden581bed72009-10-15 11:24:54 -07001014 MEM_BARRIER();
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001015 hashState = LW_HASH_STATE(thin) << LW_HASH_STATE_SHIFT;
1016 obj->lock = (u4)mon | hashState | LW_SHAPE_FAT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001017 }
1018
1019 waitMonitor(self, mon, msec, nsec, interruptShouldThrow);
1020}
1021
1022/*
1023 * Object.notify().
1024 */
1025void dvmObjectNotify(Thread* self, Object *obj)
1026{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001027 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001028
1029 /* If the lock is still thin, there aren't any waiters;
1030 * waiting on an object forces lock fattening.
1031 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001032 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001033 /* Make sure that 'self' holds the lock.
1034 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001035 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001036 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1037 "object not locked by thread before notify()");
1038 return;
1039 }
1040
1041 /* no-op; there are no waiters to notify.
1042 */
1043 } else {
1044 /* It's a fat lock.
1045 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001046 notifyMonitor(self, LW_MONITOR(thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001047 }
1048}
1049
1050/*
1051 * Object.notifyAll().
1052 */
1053void dvmObjectNotifyAll(Thread* self, Object *obj)
1054{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001055 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001056
1057 /* If the lock is still thin, there aren't any waiters;
1058 * waiting on an object forces lock fattening.
1059 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001060 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001061 /* Make sure that 'self' holds the lock.
1062 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001063 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001064 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1065 "object not locked by thread before notifyAll()");
1066 return;
1067 }
1068
1069 /* no-op; there are no waiters to notify.
1070 */
1071 } else {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001072 /* It's a fat lock.
1073 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001074 notifyAllMonitor(self, LW_MONITOR(thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001075 }
1076}
1077
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001078/*
1079 * This implements java.lang.Thread.sleep(long msec, int nsec).
1080 *
1081 * The sleep is interruptible by other threads, which means we can't just
1082 * plop into an OS sleep call. (We probably could if we wanted to send
1083 * signals around and rely on EINTR, but that's inefficient and relies
1084 * on native code respecting our signal mask.)
1085 *
1086 * We have to do all of this stuff for Object.wait() as well, so it's
1087 * easiest to just sleep on a private Monitor.
1088 *
1089 * It appears that we want sleep(0,0) to go through the motions of sleeping
1090 * for a very short duration, rather than just returning.
1091 */
1092void dvmThreadSleep(u8 msec, u4 nsec)
1093{
1094 Thread* self = dvmThreadSelf();
1095 Monitor* mon = gDvm.threadSleepMon;
1096
1097 /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */
1098 if (msec == 0 && nsec == 0)
1099 nsec++;
1100
1101 lockMonitor(self, mon);
1102 waitMonitor(self, mon, msec, nsec, true);
1103 unlockMonitor(self, mon);
1104}
1105
1106/*
1107 * Implement java.lang.Thread.interrupt().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001108 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001109void dvmThreadInterrupt(Thread* thread)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001110{
1111 Monitor* mon;
1112
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001113 assert(thread != NULL);
1114
1115 pthread_mutex_lock(&thread->waitMutex);
1116
1117 /*
1118 * If the interrupted flag is already set no additional action is
1119 * required.
1120 */
1121 if (thread->interrupted == true) {
1122 pthread_mutex_unlock(&thread->waitMutex);
1123 return;
1124 }
1125
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001126 /*
1127 * Raise the "interrupted" flag. This will cause it to bail early out
1128 * of the next wait() attempt, if it's not currently waiting on
1129 * something.
1130 */
1131 thread->interrupted = true;
1132 MEM_BARRIER();
1133
1134 /*
1135 * Is the thread waiting?
1136 *
1137 * Note that fat vs. thin doesn't matter here; waitMonitor
1138 * is only set when a thread actually waits on a monitor,
1139 * which implies that the monitor has already been fattened.
1140 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001141 if (thread->waitMonitor != NULL) {
1142 pthread_cond_signal(&thread->waitCond);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001143 }
1144
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001145 pthread_mutex_unlock(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001146}
1147
Carl Shapiro94338aa2009-12-21 11:42:59 -08001148u4 dvmIdentityHashCode(Object *obj)
1149{
1150 return (u4)obj;
1151}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001152
1153#ifdef WITH_DEADLOCK_PREDICTION
1154/*
1155 * ===========================================================================
1156 * Deadlock prediction
1157 * ===========================================================================
1158 */
1159/*
1160The idea is to predict the possibility of deadlock by recording the order
1161in which monitors are acquired. If we see an attempt to acquire a lock
1162out of order, we can identify the locks and offending code.
1163
1164To make this work, we need to keep track of the locks held by each thread,
1165and create history trees for each lock. When a thread tries to acquire
1166a new lock, we walk through the "history children" of the lock, looking
1167for a match with locks the thread already holds. If we find a match,
1168it means the thread has made a request that could result in a deadlock.
1169
1170To support recursive locks, we always allow re-locking a currently-held
1171lock, and maintain a recursion depth count.
1172
1173An ASCII-art example, where letters represent Objects:
1174
1175 A
1176 /|\
1177 / | \
1178 B | D
1179 \ |
1180 \|
1181 C
1182
1183The above is the tree we'd have after handling Object synchronization
1184sequences "ABC", "AC", "AD". A has three children, {B, C, D}. C is also
1185a child of B. (The lines represent pointers between parent and child.
1186Every node can have multiple parents and multiple children.)
1187
1188If we hold AC, and want to lock B, we recursively search through B's
1189children to see if A or C appears. It does, so we reject the attempt.
1190(A straightforward way to implement it: add a link from C to B, then
1191determine whether the graph starting at B contains a cycle.)
1192
1193If we hold AC and want to lock D, we would succeed, creating a new link
1194from C to D.
1195
1196The lock history and a stack trace is attached to the Object's Monitor
1197struct, which means we need to fatten every Object we lock (thin locking
1198is effectively disabled). If we don't need the stack trace we can
1199avoid fattening the leaf nodes, only fattening objects that need to hold
1200history trees.
1201
1202Updates to Monitor structs are only allowed for the thread that holds
1203the Monitor, so we actually do most of our deadlock prediction work after
1204the lock has been acquired.
1205
1206When an object with a monitor is GCed, we need to remove it from the
1207history trees. There are two basic approaches:
1208 (1) For through the entire set of known monitors, search all child
1209 lists for the object in question. This is rather slow, resulting
1210 in GC passes that take upwards of 10 seconds to complete.
1211 (2) Maintain "parent" pointers in each node. Remove the entries as
1212 required. This requires additional storage and maintenance for
1213 every operation, but is significantly faster at GC time.
1214For each GCed object, we merge all of the object's children into each of
1215the object's parents.
1216*/
1217
1218#if !defined(WITH_MONITOR_TRACKING)
1219# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING"
1220#endif
1221
1222/*
1223 * Clear out the contents of an ExpandingObjectList, freeing any
1224 * dynamic allocations.
1225 */
1226static void expandObjClear(ExpandingObjectList* pList)
1227{
1228 if (pList->list != NULL) {
1229 free(pList->list);
1230 pList->list = NULL;
1231 }
1232 pList->alloc = pList->count = 0;
1233}
1234
1235/*
1236 * Get the number of objects currently stored in the list.
1237 */
1238static inline int expandBufGetCount(const ExpandingObjectList* pList)
1239{
1240 return pList->count;
1241}
1242
1243/*
1244 * Get the Nth entry from the list.
1245 */
1246static inline Object* expandBufGetEntry(const ExpandingObjectList* pList,
1247 int i)
1248{
1249 return pList->list[i];
1250}
1251
1252/*
1253 * Add a new entry to the list.
1254 *
1255 * We don't check for or try to enforce uniqueness. It's expected that
1256 * the higher-level code does this for us.
1257 */
1258static void expandObjAddEntry(ExpandingObjectList* pList, Object* obj)
1259{
1260 if (pList->count == pList->alloc) {
1261 /* time to expand */
1262 Object** newList;
1263
1264 if (pList->alloc == 0)
1265 pList->alloc = 4;
1266 else
1267 pList->alloc *= 2;
1268 LOGVV("expanding %p to %d\n", pList, pList->alloc);
1269 newList = realloc(pList->list, pList->alloc * sizeof(Object*));
1270 if (newList == NULL) {
1271 LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc);
1272 dvmAbort();
1273 }
1274 pList->list = newList;
1275 }
1276
1277 pList->list[pList->count++] = obj;
1278}
1279
1280/*
1281 * Returns "true" if the element was successfully removed.
1282 */
1283static bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj)
1284{
1285 int i;
1286
1287 for (i = pList->count-1; i >= 0; i--) {
1288 if (pList->list[i] == obj)
1289 break;
1290 }
1291 if (i < 0)
1292 return false;
1293
1294 if (i != pList->count-1) {
1295 /*
1296 * The order of elements is not important, so we just copy the
1297 * last entry into the new slot.
1298 */
1299 //memmove(&pList->list[i], &pList->list[i+1],
1300 // (pList->count-1 - i) * sizeof(pList->list[0]));
1301 pList->list[i] = pList->list[pList->count-1];
1302 }
1303
1304 pList->count--;
1305 pList->list[pList->count] = (Object*) 0xdecadead;
1306 return true;
1307}
1308
1309/*
1310 * Returns "true" if "obj" appears in the list.
1311 */
1312static bool expandObjHas(const ExpandingObjectList* pList, Object* obj)
1313{
1314 int i;
1315
1316 for (i = 0; i < pList->count; i++) {
1317 if (pList->list[i] == obj)
1318 return true;
1319 }
1320 return false;
1321}
1322
1323/*
1324 * Print the list contents to stdout. For debugging.
1325 */
1326static void expandObjDump(const ExpandingObjectList* pList)
1327{
1328 int i;
1329 for (i = 0; i < pList->count; i++)
1330 printf(" %p", pList->list[i]);
1331}
1332
1333/*
1334 * Check for duplicate entries. Returns the index of the first instance
1335 * of the duplicated value, or -1 if no duplicates were found.
1336 */
1337static int expandObjCheckForDuplicates(const ExpandingObjectList* pList)
1338{
1339 int i, j;
1340 for (i = 0; i < pList->count-1; i++) {
1341 for (j = i + 1; j < pList->count; j++) {
1342 if (pList->list[i] == pList->list[j]) {
1343 return i;
1344 }
1345 }
1346 }
1347
1348 return -1;
1349}
1350
1351
1352/*
1353 * Determine whether "child" appears in the list of objects associated
1354 * with the Monitor in "parent". If "parent" is a thin lock, we return
1355 * false immediately.
1356 */
1357static bool objectInChildList(const Object* parent, Object* child)
1358{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001359 u4 lock = parent->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001360 if (!IS_LOCK_FAT(&lock)) {
1361 //LOGI("on thin\n");
1362 return false;
1363 }
1364
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001365 return expandObjHas(&LW_MONITOR(lock)->historyChildren, child);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001366}
1367
1368/*
1369 * Print the child list.
1370 */
1371static void dumpKids(Object* parent)
1372{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001373 Monitor* mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001374
1375 printf("Children of %p:", parent);
1376 expandObjDump(&mon->historyChildren);
1377 printf("\n");
1378}
1379
1380/*
1381 * Add "child" to the list of children in "parent", and add "parent" to
1382 * the list of parents in "child".
1383 */
1384static void linkParentToChild(Object* parent, Object* child)
1385{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001386 //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for merge
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001387 assert(IS_LOCK_FAT(&parent->lock));
1388 assert(IS_LOCK_FAT(&child->lock));
1389 assert(parent != child);
1390 Monitor* mon;
1391
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001392 mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001393 assert(!expandObjHas(&mon->historyChildren, child));
1394 expandObjAddEntry(&mon->historyChildren, child);
1395
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001396 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001397 assert(!expandObjHas(&mon->historyParents, parent));
1398 expandObjAddEntry(&mon->historyParents, parent);
1399}
1400
1401
1402/*
1403 * Remove "child" from the list of children in "parent".
1404 */
1405static void unlinkParentFromChild(Object* parent, Object* child)
1406{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001407 //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for GC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001408 assert(IS_LOCK_FAT(&parent->lock));
1409 assert(IS_LOCK_FAT(&child->lock));
1410 assert(parent != child);
1411 Monitor* mon;
1412
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001413 mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001414 if (!expandObjRemoveEntry(&mon->historyChildren, child)) {
1415 LOGW("WARNING: child %p not found in parent %p\n", child, parent);
1416 }
1417 assert(!expandObjHas(&mon->historyChildren, child));
1418 assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0);
1419
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001420 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001421 if (!expandObjRemoveEntry(&mon->historyParents, parent)) {
1422 LOGW("WARNING: parent %p not found in child %p\n", parent, child);
1423 }
1424 assert(!expandObjHas(&mon->historyParents, parent));
1425 assert(expandObjCheckForDuplicates(&mon->historyParents) < 0);
1426}
1427
1428
1429/*
1430 * Log the monitors held by the current thread. This is done as part of
1431 * flagging an error.
1432 */
1433static void logHeldMonitors(Thread* self)
1434{
1435 char* name = NULL;
1436
1437 name = dvmGetThreadName(self);
1438 LOGW("Monitors currently held by thread (threadid=%d '%s')\n",
1439 self->threadId, name);
1440 LOGW("(most-recently-acquired on top):\n");
1441 free(name);
1442
1443 LockedObjectData* lod = self->pLockedObjects;
1444 while (lod != NULL) {
1445 LOGW("--- object %p[%d] (%s)\n",
1446 lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
1447 dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth);
1448
1449 lod = lod->next;
1450 }
1451}
1452
1453/*
1454 * Recursively traverse the object hierarchy starting at "obj". We mark
1455 * ourselves on entry and clear the mark on exit. If we ever encounter
1456 * a marked object, we have a cycle.
1457 *
1458 * Returns "true" if all is well, "false" if we found a cycle.
1459 */
1460static bool traverseTree(Thread* self, const Object* obj)
1461{
1462 assert(IS_LOCK_FAT(&obj->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001463 Monitor* mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001464
1465 /*
1466 * Have we been here before?
1467 */
1468 if (mon->historyMark) {
1469 int* rawStackTrace;
1470 int stackDepth;
1471
1472 LOGW("%s\n", kStartBanner);
1473 LOGW("Illegal lock attempt:\n");
1474 LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1475
1476 rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth);
1477 dvmLogRawStackTrace(rawStackTrace, stackDepth);
1478 free(rawStackTrace);
1479
1480 LOGW(" ");
1481 logHeldMonitors(self);
1482
1483 LOGW(" ");
1484 LOGW("Earlier, the following lock order (from last to first) was\n");
1485 LOGW("established -- stack trace is from first successful lock):\n");
1486 return false;
1487 }
1488 mon->historyMark = true;
1489
1490 /*
1491 * Examine the children. We do NOT hold these locks, so they might
1492 * very well transition from thin to fat or change ownership while
1493 * we work.
1494 *
1495 * NOTE: we rely on the fact that they cannot revert from fat to thin
1496 * while we work. This is currently a safe assumption.
1497 *
1498 * We can safely ignore thin-locked children, because by definition
1499 * they have no history and are leaf nodes. In the current
1500 * implementation we always fatten the locks to provide a place to
1501 * hang the stack trace.
1502 */
1503 ExpandingObjectList* pList = &mon->historyChildren;
1504 int i;
1505 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1506 const Object* child = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001507 u4 lock = child->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001508 if (!IS_LOCK_FAT(&lock))
1509 continue;
1510 if (!traverseTree(self, child)) {
1511 LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1512 dvmLogRawStackTrace(mon->historyRawStackTrace,
1513 mon->historyStackDepth);
1514 mon->historyMark = false;
1515 return false;
1516 }
1517 }
1518
1519 mon->historyMark = false;
1520
1521 return true;
1522}
1523
1524/*
1525 * Update the deadlock prediction tree, based on the current thread
1526 * acquiring "acqObj". This must be called before the object is added to
1527 * the thread's list of held monitors.
1528 *
1529 * If the thread already holds the lock (recursion), or this is a known
1530 * lock configuration, we return without doing anything. Otherwise, we add
1531 * a link from the most-recently-acquired lock in this thread to "acqObj"
1532 * after ensuring that the parent lock is "fat".
1533 *
1534 * This MUST NOT be called while a GC is in progress in another thread,
1535 * because we assume exclusive access to history trees in owned monitors.
1536 */
1537static void updateDeadlockPrediction(Thread* self, Object* acqObj)
1538{
1539 LockedObjectData* lod;
1540 LockedObjectData* mrl;
1541
1542 /*
1543 * Quick check for recursive access.
1544 */
1545 lod = dvmFindInMonitorList(self, acqObj);
1546 if (lod != NULL) {
1547 LOGV("+++ DP: recursive %p\n", acqObj);
1548 return;
1549 }
1550
1551 /*
1552 * Make the newly-acquired object's monitor "fat". In some ways this
1553 * isn't strictly necessary, but we need the GC to tell us when
1554 * "interesting" objects go away, and right now the only way to make
1555 * an object look interesting is to give it a monitor.
1556 *
1557 * This also gives us a place to hang a stack trace.
1558 *
1559 * Our thread holds the lock, so we're allowed to rewrite the lock
1560 * without worrying that something will change out from under us.
1561 */
1562 if (!IS_LOCK_FAT(&acqObj->lock)) {
1563 LOGVV("fattening lockee %p (recur=%d)\n",
Carl Shapiro94338aa2009-12-21 11:42:59 -08001564 acqObj, LW_LOCK_COUNT(acqObj->lock.thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001565 Monitor* newMon = dvmCreateMonitor(acqObj);
1566 lockMonitor(self, newMon); // can't stall, don't need VMWAIT
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001567 newMon->lockCount += LW_LOCK_COUNT(acqObj->lock);
1568 u4 hashState = LW_HASH_STATE(acqObj->lock) << LW_HASH_STATE_SHIFT;
1569 acqObj->lock = (u4)newMon | hashState | LW_SHAPE_FAT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001570 }
1571
1572 /* if we don't have a stack trace for this monitor, establish one */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001573 if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) {
1574 Monitor* mon = LW_MONITOR(acqObj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001575 mon->historyRawStackTrace = dvmFillInStackTraceRaw(self,
1576 &mon->historyStackDepth);
1577 }
1578
1579 /*
1580 * We need to examine and perhaps modify the most-recently-locked
1581 * monitor. We own that, so there's no risk of another thread
1582 * stepping on us.
1583 *
1584 * Retrieve the most-recently-locked entry from our thread.
1585 */
1586 mrl = self->pLockedObjects;
1587 if (mrl == NULL)
1588 return; /* no other locks held */
1589
1590 /*
1591 * Do a quick check to see if "acqObj" is a direct descendant. We can do
1592 * this without holding the global lock because of our assertion that
1593 * a GC is not running in parallel -- nobody except the GC can
1594 * modify a history list in a Monitor they don't own, and we own "mrl".
1595 * (There might be concurrent *reads*, but no concurrent *writes.)
1596 *
1597 * If we find it, this is a known good configuration, and we're done.
1598 */
1599 if (objectInChildList(mrl->obj, acqObj))
1600 return;
1601
1602 /*
1603 * "mrl" is going to need to have a history tree. If it's currently
1604 * a thin lock, we make it fat now. The thin lock might have a
1605 * nonzero recursive lock count, which we need to carry over.
1606 *
1607 * Our thread holds the lock, so we're allowed to rewrite the lock
1608 * without worrying that something will change out from under us.
1609 */
1610 if (!IS_LOCK_FAT(&mrl->obj->lock)) {
1611 LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n",
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001612 mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001613 Monitor* newMon = dvmCreateMonitor(mrl->obj);
1614 lockMonitor(self, newMon); // can't stall, don't need VMWAIT
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001615 newMon->lockCount += LW_LOCK_COUNT(mrl->obj->lock);
1616 u4 hashState = LW_HASH_STATE(mrl->obj->lock) << LW_HASH_STATE_SHIFT;
1617 mrl->obj->lock = (u4)newMon | hashState | LW_SHAPE_FAT;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001618 }
1619
1620 /*
1621 * We haven't seen this configuration before. We need to scan down
1622 * acqObj's tree to see if any of the monitors in self->pLockedObjects
1623 * appear. We grab a global lock before traversing or updating the
1624 * history list.
1625 *
1626 * If we find a match for any of our held locks, we know that the lock
1627 * has previously been acquired *after* acqObj, and we throw an error.
1628 *
1629 * The easiest way to do this is to create a link from "mrl" to "acqObj"
1630 * and do a recursive traversal, marking nodes as we cross them. If
1631 * we cross one a second time, we have a cycle and can throw an error.
1632 * (We do the flag-clearing traversal before adding the new link, so
1633 * that we're guaranteed to terminate.)
1634 *
1635 * If "acqObj" is a thin lock, it has no history, and we can create a
1636 * link to it without additional checks. [ We now guarantee that it's
1637 * always fat. ]
1638 */
1639 bool failed = false;
1640 dvmLockMutex(&gDvm.deadlockHistoryLock);
1641 linkParentToChild(mrl->obj, acqObj);
1642 if (!traverseTree(self, acqObj)) {
1643 LOGW("%s\n", kEndBanner);
1644 failed = true;
1645
1646 /* remove the entry so we're still okay when in "warning" mode */
1647 unlinkParentFromChild(mrl->obj, acqObj);
1648 }
1649 dvmUnlockMutex(&gDvm.deadlockHistoryLock);
1650
1651 if (failed) {
1652 switch (gDvm.deadlockPredictMode) {
1653 case kDPErr:
1654 dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL);
1655 break;
1656 case kDPAbort:
1657 LOGE("Aborting due to potential deadlock\n");
1658 dvmAbort();
1659 break;
1660 default:
1661 /* warn only */
1662 break;
1663 }
1664 }
1665}
1666
1667/*
1668 * We're removing "child" from existence. We want to pull all of
1669 * child's children into "parent", filtering out duplicates. This is
1670 * called during the GC.
1671 *
1672 * This does not modify "child", which might have multiple parents.
1673 */
1674static void mergeChildren(Object* parent, const Object* child)
1675{
1676 Monitor* mon;
1677 int i;
1678
1679 assert(IS_LOCK_FAT(&child->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001680 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001681 ExpandingObjectList* pList = &mon->historyChildren;
1682
1683 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1684 Object* grandChild = expandBufGetEntry(pList, i);
1685
1686 if (!objectInChildList(parent, grandChild)) {
1687 LOGVV("+++ migrating %p link to %p\n", grandChild, parent);
1688 linkParentToChild(parent, grandChild);
1689 } else {
1690 LOGVV("+++ parent %p already links to %p\n", parent, grandChild);
1691 }
1692 }
1693}
1694
1695/*
1696 * An object with a fat lock is being collected during a GC pass. We
1697 * want to remove it from any lock history trees that it is a part of.
1698 *
1699 * This may require updating the history trees in several monitors. The
1700 * monitor semantics guarantee that no other thread will be accessing
1701 * the history trees at the same time.
1702 */
1703static void removeCollectedObject(Object* obj)
1704{
1705 Monitor* mon;
1706
1707 LOGVV("+++ collecting %p\n", obj);
1708
1709#if 0
1710 /*
1711 * We're currently running through the entire set of known monitors.
1712 * This can be somewhat slow. We may want to keep lists of parents
1713 * in each child to speed up GC.
1714 */
1715 mon = gDvm.monitorList;
1716 while (mon != NULL) {
1717 Object* parent = mon->obj;
1718 if (parent != NULL) { /* value nulled for deleted entries */
1719 if (objectInChildList(parent, obj)) {
1720 LOGVV("removing child %p from parent %p\n", obj, parent);
1721 unlinkParentFromChild(parent, obj);
1722 mergeChildren(parent, obj);
1723 }
1724 }
1725 mon = mon->next;
1726 }
1727#endif
1728
1729 /*
1730 * For every parent of this object:
1731 * - merge all of our children into the parent's child list (creates
1732 * a two-way link between parent and child)
1733 * - remove ourselves from the parent's child list
1734 */
1735 ExpandingObjectList* pList;
1736 int i;
1737
1738 assert(IS_LOCK_FAT(&obj->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001739 mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001740 pList = &mon->historyParents;
1741 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1742 Object* parent = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001743 Monitor* parentMon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001744
1745 if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) {
1746 LOGW("WARNING: child %p not found in parent %p\n", obj, parent);
1747 }
1748 assert(!expandObjHas(&parentMon->historyChildren, obj));
1749
1750 mergeChildren(parent, obj);
1751 }
1752
1753 /*
1754 * For every child of this object:
1755 * - remove ourselves from the child's parent list
1756 */
1757 pList = &mon->historyChildren;
1758 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1759 Object* child = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001760 Monitor* childMon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001761
1762 if (!expandObjRemoveEntry(&childMon->historyParents, obj)) {
1763 LOGW("WARNING: parent %p not found in child %p\n", obj, child);
1764 }
1765 assert(!expandObjHas(&childMon->historyParents, obj));
1766 }
1767}
1768
1769#endif /*WITH_DEADLOCK_PREDICTION*/
1770