blob: 67263a664bf536055010d56a25d5b79eb19fb5cb [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
Carl Shapirof0c514c2010-04-09 15:03:33 -070036#include <fcntl.h>
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080037#include <stdlib.h>
38#include <unistd.h>
39#include <pthread.h>
40#include <time.h>
41#include <sys/time.h>
42#include <errno.h>
43
44#define LOG_THIN LOGV
45
46#ifdef WITH_DEADLOCK_PREDICTION /* fwd */
47static const char* kStartBanner =
48 "<-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#";
49static const char* kEndBanner =
50 "#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#-#->";
51
52/*
53 * Unsorted, expanding list of objects.
54 *
55 * This is very similar to PointerSet (which came into existence after this),
56 * but these are unsorted, uniqueness is not enforced by the "add" function,
57 * and the base object isn't allocated on the heap.
58 */
59typedef struct ExpandingObjectList {
60 u2 alloc;
61 u2 count;
62 Object** list;
63} ExpandingObjectList;
64
65/* fwd */
66static void updateDeadlockPrediction(Thread* self, Object* obj);
67static void removeCollectedObject(Object* obj);
68static void expandObjClear(ExpandingObjectList* pList);
69#endif
70
71/*
72 * Every Object has a monitor associated with it, but not every Object is
73 * actually locked. Even the ones that are locked do not need a
74 * full-fledged monitor until a) there is actual contention or b) wait()
75 * is called on the Object.
76 *
77 * For Dalvik, we have implemented a scheme similar to the one described
78 * in Bacon et al.'s "Thin locks: featherweight synchronization for Java"
79 * (ACM 1998). Things are even easier for us, though, because we have
80 * a full 32 bits to work with.
81 *
Carl Shapiro94338aa2009-12-21 11:42:59 -080082 * The two states of an Object's lock are referred to as "thin" and
83 * "fat". A lock may transition from the "thin" state to the "fat"
84 * state and this transition is referred to as inflation. Once a lock
85 * has been inflated it remains in the "fat" state indefinitely.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080086 *
Carl Shapiro77f52eb2009-12-24 19:56:53 -080087 * The lock value itself is stored in Object.lock. The LSB of the
88 * lock encodes its state. When cleared, the lock is in the "thin"
89 * state and its bits are formatted as follows:
Carl Shapiro71938022009-12-22 13:49:53 -080090 *
Carl Shapiro94338aa2009-12-21 11:42:59 -080091 * [31 ---- 19] [18 ---- 3] [2 ---- 1] [0]
92 * lock count thread id hash state 0
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080093 *
Carl Shapiro77f52eb2009-12-24 19:56:53 -080094 * When set, the lock is in the "fat" state and its bits are formatted
Carl Shapiro94338aa2009-12-21 11:42:59 -080095 * as follows:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080096 *
Carl Shapiro94338aa2009-12-21 11:42:59 -080097 * [31 ---- 3] [2 ---- 1] [0]
98 * pointer hash state 1
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080099 *
100 * For an in-depth description of the mechanics of thin-vs-fat locking,
101 * read the paper referred to above.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800102 */
103
104/*
105 * Monitors provide:
106 * - mutually exclusive access to resources
107 * - a way for multiple threads to wait for notification
108 *
109 * In effect, they fill the role of both mutexes and condition variables.
110 *
111 * Only one thread can own the monitor at any time. There may be several
112 * threads waiting on it (the wait call unlocks it). One or more waiting
113 * threads may be getting interrupted or notified at any given time.
Carl Shapirofa903b32010-08-31 15:11:46 -0700114 *
115 * TODO: the various members of monitor are not SMP-safe.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800116 */
117struct Monitor {
118 Thread* owner; /* which thread currently owns the lock? */
119 int lockCount; /* owner's recursive lock depth */
120 Object* obj; /* what object are we part of [debug only] */
121
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800122 Thread* waitSet; /* threads currently waiting on this monitor */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800123
124 pthread_mutex_t lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800125
126 Monitor* next;
127
Carl Shapirofa903b32010-08-31 15:11:46 -0700128 /*
129 * Who last acquired this monitor, when lock sampling is enabled.
130 * Even when enabled, ownerFileName may be NULL.
131 */
132 char* ownerFileName;
133 u4 ownerLineNumber;
134
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800135#ifdef WITH_DEADLOCK_PREDICTION
136 /*
137 * Objects that have been locked immediately after this one in the
138 * past. We use an expanding flat array, allocated on first use, to
139 * minimize allocations. Deletions from the list, expected to be
140 * infrequent, are crunched down.
141 */
142 ExpandingObjectList historyChildren;
143
144 /*
145 * We also track parents. This isn't strictly necessary, but it makes
146 * the cleanup at GC time significantly faster.
147 */
148 ExpandingObjectList historyParents;
149
150 /* used during cycle detection */
151 bool historyMark;
152
153 /* stack trace, established the first time we locked the object */
154 int historyStackDepth;
155 int* historyRawStackTrace;
156#endif
157};
158
159
160/*
161 * Create and initialize a monitor.
162 */
163Monitor* dvmCreateMonitor(Object* obj)
164{
165 Monitor* mon;
166
167 mon = (Monitor*) calloc(1, sizeof(Monitor));
168 if (mon == NULL) {
169 LOGE("Unable to allocate monitor\n");
170 dvmAbort();
171 }
Carl Shapiro94338aa2009-12-21 11:42:59 -0800172 if (((u4)mon & 7) != 0) {
173 LOGE("Misaligned monitor: %p\n", mon);
174 dvmAbort();
175 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800176 mon->obj = obj;
177 dvmInitMutex(&mon->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800178
179 /* replace the head of the list with the new monitor */
180 do {
181 mon->next = gDvm.monitorList;
Andy McFadden6e10b9a2010-06-14 15:24:39 -0700182 } while (android_atomic_release_cas((int32_t)mon->next, (int32_t)mon,
183 (int32_t*)(void*)&gDvm.monitorList) != 0);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800184
185 return mon;
186}
187
188/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800189 * Free the monitor list. Only used when shutting the VM down.
190 */
191void dvmFreeMonitorList(void)
192{
193 Monitor* mon;
194 Monitor* nextMon;
195
196 mon = gDvm.monitorList;
197 while (mon != NULL) {
198 nextMon = mon->next;
199
200#ifdef WITH_DEADLOCK_PREDICTION
201 expandObjClear(&mon->historyChildren);
202 expandObjClear(&mon->historyParents);
203 free(mon->historyRawStackTrace);
204#endif
205 free(mon);
206 mon = nextMon;
207 }
208}
209
210/*
211 * Log some info about our monitors.
212 */
213void dvmDumpMonitorInfo(const char* msg)
214{
215#if QUIET_ZYGOTE_MONITOR
216 if (gDvm.zygote) {
217 return;
218 }
219#endif
220
221 int totalCount;
222 int liveCount;
223
224 totalCount = liveCount = 0;
225 Monitor* mon = gDvm.monitorList;
226 while (mon != NULL) {
227 totalCount++;
228 if (mon->obj != NULL)
229 liveCount++;
230 mon = mon->next;
231 }
232
233 LOGD("%s: monitor list has %d entries (%d live)\n",
234 msg, totalCount, liveCount);
235}
236
237/*
238 * Get the object that a monitor is part of.
239 */
240Object* dvmGetMonitorObject(Monitor* mon)
241{
242 if (mon == NULL)
243 return NULL;
244 else
245 return mon->obj;
246}
247
248/*
Carl Shapiro30aa9972010-01-13 22:07:50 -0800249 * Returns the thread id of the thread owning the given lock.
250 */
251static u4 lockOwner(Object* obj)
252{
253 Thread *owner;
254 u4 lock;
255
256 assert(obj != NULL);
257 /*
258 * Since we're reading the lock value multiple times, latch it so
259 * that it doesn't change out from under us if we get preempted.
260 */
261 lock = obj->lock;
262 if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
263 return LW_LOCK_OWNER(lock);
264 } else {
265 owner = LW_MONITOR(lock)->owner;
266 return owner ? owner->threadId : 0;
267 }
268}
269
270/*
Andy McFaddenfd542662010-03-12 13:39:59 -0800271 * Get the thread that holds the lock on the specified object. The
272 * object may be unlocked, thin-locked, or fat-locked.
273 *
274 * The caller must lock the thread list before calling here.
275 */
276Thread* dvmGetObjectLockHolder(Object* obj)
277{
278 u4 threadId = lockOwner(obj);
279
280 if (threadId == 0)
281 return NULL;
282 return dvmGetThreadByThreadId(threadId);
283}
284
285/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800286 * Checks whether the given thread holds the given
287 * objects's lock.
288 */
289bool dvmHoldsLock(Thread* thread, Object* obj)
290{
291 if (thread == NULL || obj == NULL) {
292 return false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800293 } else {
Carl Shapiro30aa9972010-01-13 22:07:50 -0800294 return thread->threadId == lockOwner(obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800295 }
296}
297
298/*
299 * Free the monitor associated with an object and make the object's lock
300 * thin again. This is called during garbage collection.
301 */
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800302static void freeObjectMonitor(Object* obj)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800303{
304 Monitor *mon;
305
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800306 assert(LW_SHAPE(obj->lock) == LW_SHAPE_FAT);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800307
308#ifdef WITH_DEADLOCK_PREDICTION
309 if (gDvm.deadlockPredictMode != kDPOff)
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800310 removeCollectedObject(obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800311#endif
312
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800313 mon = LW_MONITOR(obj->lock);
314 obj->lock = DVM_LOCK_INITIAL_THIN_VALUE;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800315
316 /* This lock is associated with an object
317 * that's being swept. The only possible way
318 * anyone could be holding this lock would be
319 * if some JNI code locked but didn't unlock
320 * the object, in which case we've got some bad
321 * native code somewhere.
322 */
Carl Shapiro1ff876d2010-04-04 01:56:48 -0700323 assert(pthread_mutex_trylock(&mon->lock) == 0);
324 assert(pthread_mutex_unlock(&mon->lock) == 0);
Carl Shapiro980ffb02010-03-13 22:34:01 -0800325 dvmDestroyMutex(&mon->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800326#ifdef WITH_DEADLOCK_PREDICTION
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800327 expandObjClear(&mon->historyChildren);
328 expandObjClear(&mon->historyParents);
329 free(mon->historyRawStackTrace);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800330#endif
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800331 free(mon);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800332}
333
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800334/*
335 * Frees monitor objects belonging to unmarked objects.
336 */
337void dvmSweepMonitorList(Monitor** mon, int (*isUnmarkedObject)(void*))
338{
339 Monitor handle;
340 Monitor *prev, *curr;
341 Object *obj;
342
343 assert(mon != NULL);
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800344 assert(isUnmarkedObject != NULL);
Carl Shapiro8881a802010-08-10 15:55:45 -0700345#ifdef WITH_DEADLOCK_PREDICTION
346 dvmDumpMonitorInfo("before monitor sweep");
347#endif
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800348 prev = &handle;
349 prev->next = curr = *mon;
350 while (curr != NULL) {
351 obj = curr->obj;
352 if (obj != NULL && (*isUnmarkedObject)(obj) != 0) {
353 prev->next = curr = curr->next;
354 freeObjectMonitor(obj);
355 } else {
356 prev = curr;
357 curr = curr->next;
358 }
359 }
360 *mon = handle.next;
Carl Shapiro8881a802010-08-10 15:55:45 -0700361#ifdef WITH_DEADLOCK_PREDICTION
362 dvmDumpMonitorInfo("after monitor sweep");
363#endif
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800364}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800365
Carl Shapirof0c514c2010-04-09 15:03:33 -0700366static char *logWriteInt(char *dst, int value)
367{
368 *dst++ = EVENT_TYPE_INT;
369 set4LE((u1 *)dst, value);
370 return dst + 4;
371}
372
373static char *logWriteString(char *dst, const char *value, size_t len)
374{
375 *dst++ = EVENT_TYPE_STRING;
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700376 len = len < 32 ? len : 32;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700377 set4LE((u1 *)dst, len);
378 dst += 4;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700379 memcpy(dst, value, len);
380 return dst + len;
381}
382
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700383#define EVENT_LOG_TAG_dvm_lock_sample 20003
Carl Shapirof0c514c2010-04-09 15:03:33 -0700384
Carl Shapirofa903b32010-08-31 15:11:46 -0700385static void logContentionEvent(Thread *self, u4 waitMs, u4 samplePercent,
386 const char *ownerFileName, u4 ownerLineNumber)
Carl Shapirof0c514c2010-04-09 15:03:33 -0700387{
388 const StackSaveArea *saveArea;
389 const Method *meth;
390 u4 relativePc;
Carl Shapirofa903b32010-08-31 15:11:46 -0700391 char eventBuffer[174];
Carl Shapirof0c514c2010-04-09 15:03:33 -0700392 const char *fileName;
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700393 char procName[33], *selfName;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700394 char *cp;
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700395 size_t len;
396 int fd;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700397
398 saveArea = SAVEAREA_FROM_FP(self->curFrame);
399 meth = saveArea->method;
400 cp = eventBuffer;
401
402 /* Emit the event list length, 1 byte. */
Carl Shapirofa903b32010-08-31 15:11:46 -0700403 *cp++ = 9;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700404
405 /* Emit the process name, <= 37 bytes. */
406 fd = open("/proc/self/cmdline", O_RDONLY);
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700407 memset(procName, 0, sizeof(procName));
408 read(fd, procName, sizeof(procName) - 1);
Carl Shapirof0c514c2010-04-09 15:03:33 -0700409 close(fd);
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700410 len = strlen(procName);
411 cp = logWriteString(cp, procName, len);
Carl Shapirof0c514c2010-04-09 15:03:33 -0700412
413 /* Emit the main thread status, 5 bytes. */
414 bool isMainThread = (self->systemTid == getpid());
415 cp = logWriteInt(cp, isMainThread);
416
417 /* Emit self thread name string, <= 37 bytes. */
418 selfName = dvmGetThreadName(self);
419 cp = logWriteString(cp, selfName, strlen(selfName));
420 free(selfName);
421
422 /* Emit the wait time, 5 bytes. */
423 cp = logWriteInt(cp, waitMs);
424
425 /* Emit the source code file name, <= 37 bytes. */
426 fileName = dvmGetMethodSourceFile(meth);
427 if (fileName == NULL) fileName = "";
428 cp = logWriteString(cp, fileName, strlen(fileName));
429
430 /* Emit the source code line number, 5 bytes. */
431 relativePc = saveArea->xtra.currentPc - saveArea->method->insns;
432 cp = logWriteInt(cp, dvmLineNumFromPC(meth, relativePc));
433
Carl Shapirofa903b32010-08-31 15:11:46 -0700434 /* Emit the lock owner source code file name, <= 37 bytes. */
435 if (ownerFileName == NULL) {
436 ownerFileName = "";
437 } else if (strcmp(fileName, ownerFileName) == 0) {
438 /* Common case, so save on log space. */
439 ownerFileName = "-";
440 }
441 cp = logWriteString(cp, ownerFileName, strlen(ownerFileName));
442
443 /* Emit the source code line number, 5 bytes. */
444 cp = logWriteInt(cp, ownerLineNumber);
445
Carl Shapirof0c514c2010-04-09 15:03:33 -0700446 /* Emit the sample percentage, 5 bytes. */
447 cp = logWriteInt(cp, samplePercent);
448
449 assert((size_t)(cp - eventBuffer) <= sizeof(eventBuffer));
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700450 android_btWriteLog(EVENT_LOG_TAG_dvm_lock_sample,
Carl Shapirof0c514c2010-04-09 15:03:33 -0700451 EVENT_TYPE_LIST,
452 eventBuffer,
453 (size_t)(cp - eventBuffer));
454}
455
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800456/*
457 * Lock a monitor.
458 */
459static void lockMonitor(Thread* self, Monitor* mon)
460{
Carl Shapirof0c514c2010-04-09 15:03:33 -0700461 ThreadStatus oldStatus;
462 u4 waitThreshold, samplePercent;
463 u8 waitStart, waitEnd, waitMs;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800464
465 if (mon->owner == self) {
466 mon->lockCount++;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700467 return;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800468 }
Carl Shapiro045fdc92010-04-13 16:48:27 -0700469 if (dvmTryLockMutex(&mon->lock) != 0) {
Carl Shapirof0c514c2010-04-09 15:03:33 -0700470 oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
471 waitThreshold = gDvm.lockProfThreshold;
472 if (waitThreshold) {
473 waitStart = dvmGetRelativeTimeUsec();
474 }
Carl Shapirofa903b32010-08-31 15:11:46 -0700475 const char* currentOwnerFileName = mon->ownerFileName;
476 u4 currentOwnerLineNumber = mon->ownerLineNumber;
477
Carl Shapirof0c514c2010-04-09 15:03:33 -0700478 dvmLockMutex(&mon->lock);
479 if (waitThreshold) {
480 waitEnd = dvmGetRelativeTimeUsec();
481 }
482 dvmChangeStatus(self, oldStatus);
483 if (waitThreshold) {
484 waitMs = (waitEnd - waitStart) / 1000;
485 if (waitMs >= waitThreshold) {
486 samplePercent = 100;
487 } else {
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700488 samplePercent = 100 * waitMs / waitThreshold;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700489 }
Carl Shapirob8fcf572010-04-16 17:33:15 -0700490 if (samplePercent != 0 && ((u4)rand() % 100 < samplePercent)) {
Carl Shapirofa903b32010-08-31 15:11:46 -0700491 logContentionEvent(self, waitMs, samplePercent,
492 currentOwnerFileName, currentOwnerLineNumber);
Carl Shapirof0c514c2010-04-09 15:03:33 -0700493 }
494 }
495 }
496 mon->owner = self;
497 assert(mon->lockCount == 0);
Carl Shapirofa903b32010-08-31 15:11:46 -0700498
499 // When debugging, save the current monitor holder for future
500 // acquisition failures to use in sampled logging.
501 if (gDvm.lockProfThreshold > 0) {
502 const StackSaveArea *saveArea;
503 const Method *meth;
504 mon->ownerLineNumber = 0;
505 if (self->curFrame == NULL) {
506 mon->ownerFileName = "no_frame";
507 } else if ((saveArea = SAVEAREA_FROM_FP(self->curFrame)) == NULL) {
508 mon->ownerFileName = "no_save_area";
509 } else if ((meth = saveArea->method) == NULL) {
510 mon->ownerFileName = "no_method";
511 } else {
512 u4 relativePc = saveArea->xtra.currentPc - saveArea->method->insns;
513 mon->ownerFileName = (char*) dvmGetMethodSourceFile(meth);
514 if (mon->ownerFileName == NULL) {
515 mon->ownerFileName = "no_method_file";
516 } else {
517 mon->ownerLineNumber = dvmLineNumFromPC(meth, relativePc);
518 }
519 }
520 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800521}
522
523/*
524 * Try to lock a monitor.
525 *
526 * Returns "true" on success.
527 */
Carl Shapirob31b3012010-05-25 18:35:37 -0700528#ifdef WITH_COPYING_GC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800529static bool tryLockMonitor(Thread* self, Monitor* mon)
530{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800531 if (mon->owner == self) {
532 mon->lockCount++;
533 return true;
534 } else {
Carl Shapiro980ffb02010-03-13 22:34:01 -0800535 if (dvmTryLockMutex(&mon->lock) == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800536 mon->owner = self;
537 assert(mon->lockCount == 0);
538 return true;
539 } else {
540 return false;
541 }
542 }
543}
Carl Shapirob31b3012010-05-25 18:35:37 -0700544#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800545
546/*
547 * Unlock a monitor.
548 *
549 * Returns true if the unlock succeeded.
550 * If the unlock failed, an exception will be pending.
551 */
552static bool unlockMonitor(Thread* self, Monitor* mon)
553{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800554 assert(self != NULL);
Carl Shapiro92277082010-04-06 15:35:59 -0700555 assert(mon != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800556 if (mon->owner == self) {
557 /*
558 * We own the monitor, so nobody else can be in here.
559 */
560 if (mon->lockCount == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800561 mon->owner = NULL;
Carl Shapirofa903b32010-08-31 15:11:46 -0700562 mon->ownerFileName = "unlocked";
563 mon->ownerLineNumber = 0;
Carl Shapiro980ffb02010-03-13 22:34:01 -0800564 dvmUnlockMutex(&mon->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800565 } else {
566 mon->lockCount--;
567 }
568 } else {
569 /*
570 * We don't own this, so we're not allowed to unlock it.
571 * The JNI spec says that we should throw IllegalMonitorStateException
572 * in this case.
573 */
Carl Shapiro8782d7c2010-04-19 20:10:35 -0700574 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
575 "unlock of unowned monitor");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800576 return false;
577 }
578 return true;
579}
580
581/*
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800582 * Checks the wait set for circular structure. Returns 0 if the list
Carl Shapirob4539192010-01-04 16:50:00 -0800583 * is not circular. Otherwise, returns 1. Used only by asserts.
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800584 */
Carl Shapirob31b3012010-05-25 18:35:37 -0700585#ifndef NDEBUG
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800586static int waitSetCheck(Monitor *mon)
587{
588 Thread *fast, *slow;
589 size_t n;
590
591 assert(mon != NULL);
592 fast = slow = mon->waitSet;
593 n = 0;
594 for (;;) {
595 if (fast == NULL) return 0;
596 if (fast->waitNext == NULL) return 0;
Carl Shapiro5f56e672010-01-05 20:38:03 -0800597 if (fast == slow && n > 0) return 1;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800598 n += 2;
599 fast = fast->waitNext->waitNext;
600 slow = slow->waitNext;
601 }
602}
Carl Shapirob31b3012010-05-25 18:35:37 -0700603#endif
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800604
605/*
Carl Shapiro30aa9972010-01-13 22:07:50 -0800606 * Links a thread into a monitor's wait set. The monitor lock must be
607 * held by the caller of this routine.
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800608 */
609static void waitSetAppend(Monitor *mon, Thread *thread)
610{
611 Thread *elt;
612
613 assert(mon != NULL);
Carl Shapiro30aa9972010-01-13 22:07:50 -0800614 assert(mon->owner == dvmThreadSelf());
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800615 assert(thread != NULL);
616 assert(thread->waitNext == NULL);
617 assert(waitSetCheck(mon) == 0);
618 if (mon->waitSet == NULL) {
619 mon->waitSet = thread;
620 return;
621 }
622 elt = mon->waitSet;
623 while (elt->waitNext != NULL) {
624 elt = elt->waitNext;
625 }
626 elt->waitNext = thread;
627}
628
629/*
Carl Shapiro30aa9972010-01-13 22:07:50 -0800630 * Unlinks a thread from a monitor's wait set. The monitor lock must
631 * be held by the caller of this routine.
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800632 */
633static void waitSetRemove(Monitor *mon, Thread *thread)
634{
635 Thread *elt;
636
637 assert(mon != NULL);
Carl Shapiro30aa9972010-01-13 22:07:50 -0800638 assert(mon->owner == dvmThreadSelf());
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800639 assert(thread != NULL);
640 assert(waitSetCheck(mon) == 0);
641 if (mon->waitSet == NULL) {
642 return;
643 }
644 if (mon->waitSet == thread) {
645 mon->waitSet = thread->waitNext;
646 thread->waitNext = NULL;
647 return;
648 }
649 elt = mon->waitSet;
650 while (elt->waitNext != NULL) {
651 if (elt->waitNext == thread) {
652 elt->waitNext = thread->waitNext;
653 thread->waitNext = NULL;
654 return;
655 }
656 elt = elt->waitNext;
657 }
658}
659
Carl Shapirob4539192010-01-04 16:50:00 -0800660/*
661 * Converts the given relative waiting time into an absolute time.
662 */
Andy McFadden953a0ed2010-09-17 15:48:38 -0700663static void absoluteTime(s8 msec, s4 nsec, struct timespec *ts)
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800664{
665 s8 endSec;
666
667#ifdef HAVE_TIMEDWAIT_MONOTONIC
668 clock_gettime(CLOCK_MONOTONIC, ts);
669#else
670 {
671 struct timeval tv;
672 gettimeofday(&tv, NULL);
673 ts->tv_sec = tv.tv_sec;
674 ts->tv_nsec = tv.tv_usec * 1000;
675 }
676#endif
677 endSec = ts->tv_sec + msec / 1000;
678 if (endSec >= 0x7fffffff) {
679 LOGV("NOTE: end time exceeds epoch\n");
680 endSec = 0x7ffffffe;
681 }
682 ts->tv_sec = endSec;
683 ts->tv_nsec = (ts->tv_nsec + (msec % 1000) * 1000000) + nsec;
684
685 /* catch rollover */
686 if (ts->tv_nsec >= 1000000000L) {
687 ts->tv_sec++;
688 ts->tv_nsec -= 1000000000L;
689 }
690}
691
Bill Buzbeefccb31d2010-02-04 16:09:55 -0800692int dvmRelativeCondWait(pthread_cond_t* cond, pthread_mutex_t* mutex,
693 s8 msec, s4 nsec)
694{
695 int ret;
696 struct timespec ts;
697 absoluteTime(msec, nsec, &ts);
698#if defined(HAVE_TIMEDWAIT_MONOTONIC)
699 ret = pthread_cond_timedwait_monotonic(cond, mutex, &ts);
700#else
701 ret = pthread_cond_timedwait(cond, mutex, &ts);
702#endif
703 assert(ret == 0 || ret == ETIMEDOUT);
704 return ret;
705}
706
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800707/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800708 * Wait on a monitor until timeout, interrupt, or notification. Used for
709 * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join().
710 *
711 * If another thread calls Thread.interrupt(), we throw InterruptedException
712 * and return immediately if one of the following are true:
713 * - blocked in wait(), wait(long), or wait(long, int) methods of Object
714 * - blocked in join(), join(long), or join(long, int) methods of Thread
715 * - blocked in sleep(long), or sleep(long, int) methods of Thread
716 * Otherwise, we set the "interrupted" flag.
717 *
718 * Checks to make sure that "nsec" is in the range 0-999999
719 * (i.e. fractions of a millisecond) and throws the appropriate
720 * exception if it isn't.
721 *
722 * The spec allows "spurious wakeups", and recommends that all code using
723 * Object.wait() do so in a loop. This appears to derive from concerns
724 * about pthread_cond_wait() on multiprocessor systems. Some commentary
725 * on the web casts doubt on whether these can/should occur.
726 *
727 * Since we're allowed to wake up "early", we clamp extremely long durations
728 * to return at the end of the 32-bit time epoch.
729 */
730static void waitMonitor(Thread* self, Monitor* mon, s8 msec, s4 nsec,
731 bool interruptShouldThrow)
732{
733 struct timespec ts;
734 bool wasInterrupted = false;
735 bool timed;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800736 int ret;
Carl Shapirofa903b32010-08-31 15:11:46 -0700737 char *savedFileName;
738 u4 savedLineNumber;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800739
Carl Shapiro71938022009-12-22 13:49:53 -0800740 assert(self != NULL);
741 assert(mon != NULL);
742
Carl Shapiro94338aa2009-12-21 11:42:59 -0800743 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800744 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800745 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
746 "object not locked by thread before wait()");
747 return;
748 }
749
750 /*
751 * Enforce the timeout range.
752 */
753 if (msec < 0 || nsec < 0 || nsec > 999999) {
754 dvmThrowException("Ljava/lang/IllegalArgumentException;",
755 "timeout arguments out of range");
756 return;
757 }
758
759 /*
760 * Compute absolute wakeup time, if necessary.
761 */
762 if (msec == 0 && nsec == 0) {
763 timed = false;
764 } else {
Bill Buzbeefccb31d2010-02-04 16:09:55 -0800765 absoluteTime(msec, nsec, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800766 timed = true;
767 }
768
769 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800770 * Add ourselves to the set of threads waiting on this monitor, and
771 * release our hold. We need to let it go even if we're a few levels
772 * deep in a recursive lock, and we need to restore that later.
773 *
Carl Shapiro142ef272010-01-25 12:51:31 -0800774 * We append to the wait set ahead of clearing the count and owner
775 * fields so the subroutine can check that the calling thread owns
776 * the monitor. Aside from that, the order of member updates is
777 * not order sensitive as we hold the pthread mutex.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800778 */
Carl Shapiro142ef272010-01-25 12:51:31 -0800779 waitSetAppend(mon, self);
780 int prevLockCount = mon->lockCount;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800781 mon->lockCount = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800782 mon->owner = NULL;
Carl Shapirofa903b32010-08-31 15:11:46 -0700783 savedFileName = mon->ownerFileName;
784 mon->ownerFileName = NULL;
785 savedLineNumber = mon->ownerLineNumber;
786 mon->ownerLineNumber = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800787
788 /*
789 * Update thread status. If the GC wakes up, it'll ignore us, knowing
790 * that we won't touch any references in this state, and we'll check
791 * our suspend mode before we transition out.
792 */
793 if (timed)
794 dvmChangeStatus(self, THREAD_TIMED_WAIT);
795 else
796 dvmChangeStatus(self, THREAD_WAIT);
797
Carl Shapiro980ffb02010-03-13 22:34:01 -0800798 dvmLockMutex(&self->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800799
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800800 /*
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800801 * Set waitMonitor to the monitor object we will be waiting on.
802 * When waitMonitor is non-NULL a notifying or interrupting thread
803 * must signal the thread's waitCond to wake it up.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800804 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800805 assert(self->waitMonitor == NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800806 self->waitMonitor = mon;
807
808 /*
809 * Handle the case where the thread was interrupted before we called
810 * wait().
811 */
812 if (self->interrupted) {
813 wasInterrupted = true;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800814 self->waitMonitor = NULL;
Carl Shapiro980ffb02010-03-13 22:34:01 -0800815 dvmUnlockMutex(&self->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800816 goto done;
817 }
818
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800819 /*
820 * Release the monitor lock and wait for a notification or
821 * a timeout to occur.
822 */
Carl Shapiro980ffb02010-03-13 22:34:01 -0800823 dvmUnlockMutex(&mon->lock);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800824
825 if (!timed) {
826 ret = pthread_cond_wait(&self->waitCond, &self->waitMutex);
827 assert(ret == 0);
828 } else {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800829#ifdef HAVE_TIMEDWAIT_MONOTONIC
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800830 ret = pthread_cond_timedwait_monotonic(&self->waitCond, &self->waitMutex, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800831#else
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800832 ret = pthread_cond_timedwait(&self->waitCond, &self->waitMutex, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800833#endif
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800834 assert(ret == 0 || ret == ETIMEDOUT);
835 }
836 if (self->interrupted) {
837 wasInterrupted = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800838 }
839
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800840 self->interrupted = false;
841 self->waitMonitor = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800842
Carl Shapiro980ffb02010-03-13 22:34:01 -0800843 dvmUnlockMutex(&self->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800844
Carl Shapiro30aa9972010-01-13 22:07:50 -0800845 /* Reacquire the monitor lock. */
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800846 lockMonitor(self, mon);
847
Carl Shapiro142ef272010-01-25 12:51:31 -0800848done:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800849 /*
Carl Shapiro07b35922010-01-25 14:48:30 -0800850 * We remove our thread from wait set after restoring the count
851 * and owner fields so the subroutine can check that the calling
852 * thread owns the monitor. Aside from that, the order of member
853 * updates is not order sensitive as we hold the pthread mutex.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800854 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800855 mon->owner = self;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800856 mon->lockCount = prevLockCount;
Carl Shapirofa903b32010-08-31 15:11:46 -0700857 mon->ownerFileName = savedFileName;
858 mon->ownerLineNumber = savedLineNumber;
Carl Shapiro07b35922010-01-25 14:48:30 -0800859 waitSetRemove(mon, self);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800860
861 /* set self->status back to THREAD_RUNNING, and self-suspend if needed */
862 dvmChangeStatus(self, THREAD_RUNNING);
863
864 if (wasInterrupted) {
865 /*
866 * We were interrupted while waiting, or somebody interrupted an
Carl Shapiro30aa9972010-01-13 22:07:50 -0800867 * un-interruptible thread earlier and we're bailing out immediately.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800868 *
869 * The doc sayeth: "The interrupted status of the current thread is
870 * cleared when this exception is thrown."
871 */
872 self->interrupted = false;
873 if (interruptShouldThrow)
874 dvmThrowException("Ljava/lang/InterruptedException;", NULL);
875 }
876}
877
878/*
879 * Notify one thread waiting on this monitor.
880 */
881static void notifyMonitor(Thread* self, Monitor* mon)
882{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800883 Thread* thread;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800884
Carl Shapiro71938022009-12-22 13:49:53 -0800885 assert(self != NULL);
886 assert(mon != NULL);
887
Carl Shapiro94338aa2009-12-21 11:42:59 -0800888 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800889 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800890 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
891 "object not locked by thread before notify()");
892 return;
893 }
Carl Shapiro30aa9972010-01-13 22:07:50 -0800894 /* Signal the first waiting thread in the wait set. */
895 while (mon->waitSet != NULL) {
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800896 thread = mon->waitSet;
897 mon->waitSet = thread->waitNext;
898 thread->waitNext = NULL;
Carl Shapiro980ffb02010-03-13 22:34:01 -0800899 dvmLockMutex(&thread->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800900 /* Check to see if the thread is still waiting. */
901 if (thread->waitMonitor != NULL) {
902 pthread_cond_signal(&thread->waitCond);
Carl Shapiro980ffb02010-03-13 22:34:01 -0800903 dvmUnlockMutex(&thread->waitMutex);
Carl Shapiro30aa9972010-01-13 22:07:50 -0800904 return;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800905 }
Carl Shapiro980ffb02010-03-13 22:34:01 -0800906 dvmUnlockMutex(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800907 }
908}
909
910/*
911 * Notify all threads waiting on this monitor.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800912 */
913static void notifyAllMonitor(Thread* self, Monitor* mon)
914{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800915 Thread* thread;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800916
Carl Shapiro71938022009-12-22 13:49:53 -0800917 assert(self != NULL);
918 assert(mon != NULL);
919
Carl Shapiro94338aa2009-12-21 11:42:59 -0800920 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800921 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800922 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
923 "object not locked by thread before notifyAll()");
924 return;
925 }
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800926 /* Signal all threads in the wait set. */
927 while (mon->waitSet != NULL) {
928 thread = mon->waitSet;
929 mon->waitSet = thread->waitNext;
930 thread->waitNext = NULL;
Carl Shapiro980ffb02010-03-13 22:34:01 -0800931 dvmLockMutex(&thread->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800932 /* Check to see if the thread is still waiting. */
933 if (thread->waitMonitor != NULL) {
934 pthread_cond_signal(&thread->waitCond);
935 }
Carl Shapiro980ffb02010-03-13 22:34:01 -0800936 dvmUnlockMutex(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800937 }
938}
939
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800940/*
Carl Shapiro66bb7df2010-03-12 15:25:37 -0800941 * Changes the shape of a monitor from thin to fat, preserving the
942 * internal lock state. The calling thread must own the lock.
943 */
944static void inflateMonitor(Thread *self, Object *obj)
945{
946 Monitor *mon;
947 u4 thin;
948
949 assert(self != NULL);
950 assert(obj != NULL);
951 assert(LW_SHAPE(obj->lock) == LW_SHAPE_THIN);
952 assert(LW_LOCK_OWNER(obj->lock) == self->threadId);
953 /* Allocate and acquire a new monitor. */
954 mon = dvmCreateMonitor(obj);
955 lockMonitor(self, mon);
956 /* Propagate the lock state. */
957 thin = obj->lock;
958 mon->lockCount = LW_LOCK_COUNT(thin);
959 thin &= LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT;
960 thin |= (u4)mon | LW_SHAPE_FAT;
961 /* Publish the updated lock word. */
Carl Shapiro4ba56722010-06-21 11:04:33 -0700962 android_atomic_release_store(thin, (int32_t *)&obj->lock);
Carl Shapiro66bb7df2010-03-12 15:25:37 -0800963}
964
965/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800966 * Implements monitorenter for "synchronized" stuff.
967 *
968 * This does not fail or throw an exception (unless deadlock prediction
969 * is enabled and set to "err" mode).
970 */
971void dvmLockObject(Thread* self, Object *obj)
972{
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800973 volatile u4 *thinp;
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800974 ThreadStatus oldStatus;
975 useconds_t sleepDelay;
976 const useconds_t maxSleepDelay = 1 << 20;
977 u4 thin, newThin, threadId;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800978
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800979 assert(self != NULL);
980 assert(obj != NULL);
981 threadId = self->threadId;
982 thinp = &obj->lock;
983retry:
984 thin = *thinp;
985 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
986 /*
987 * The lock is a thin lock. The owner field is used to
988 * determine the acquire method, ordered by cost.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800989 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800990 if (LW_LOCK_OWNER(thin) == threadId) {
991 /*
992 * The calling thread owns the lock. Increment the
993 * value of the recursion count field.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800994 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800995 obj->lock += 1 << LW_LOCK_COUNT_SHIFT;
Carl Shapirof3cfbbf2010-07-23 16:30:12 -0700996 if (LW_LOCK_COUNT(obj->lock) == LW_LOCK_COUNT_MASK) {
997 /*
998 * The reacquisition limit has been reached. Inflate
999 * the lock so the next acquire will not overflow the
1000 * recursion count field.
1001 */
1002 inflateMonitor(self, obj);
1003 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001004 } else if (LW_LOCK_OWNER(thin) == 0) {
1005 /*
1006 * The lock is unowned. Install the thread id of the
1007 * calling thread into the owner field. This is the
1008 * common case. In performance critical code the JIT
1009 * will have tried this before calling out to the VM.
1010 */
1011 newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
Carl Shapiro3ba10c92010-09-02 16:43:16 -07001012 if (android_atomic_acquire_cas(thin, newThin,
Andy McFadden6e10b9a2010-06-14 15:24:39 -07001013 (int32_t*)thinp) != 0) {
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001014 /*
1015 * The acquire failed. Try again.
1016 */
1017 goto retry;
1018 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001019 } else {
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001020 LOG_THIN("(%d) spin on lock %p: %#x (%#x) %#x",
1021 threadId, &obj->lock, 0, *thinp, thin);
1022 /*
1023 * The lock is owned by another thread. Notify the VM
1024 * that we are about to wait.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001025 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001026 oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
1027 /*
1028 * Spin until the thin lock is released or inflated.
1029 */
1030 sleepDelay = 0;
1031 for (;;) {
1032 thin = *thinp;
1033 /*
1034 * Check the shape of the lock word. Another thread
1035 * may have inflated the lock while we were waiting.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001036 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001037 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1038 if (LW_LOCK_OWNER(thin) == 0) {
1039 /*
1040 * The lock has been released. Install the
1041 * thread id of the calling thread into the
1042 * owner field.
1043 */
1044 newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
Carl Shapiro3ba10c92010-09-02 16:43:16 -07001045 if (android_atomic_acquire_cas(thin, newThin,
Andy McFadden6e10b9a2010-06-14 15:24:39 -07001046 (int32_t *)thinp) == 0) {
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001047 /*
1048 * The acquire succeed. Break out of the
1049 * loop and proceed to inflate the lock.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001050 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001051 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001052 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001053 } else {
1054 /*
1055 * The lock has not been released. Yield so
1056 * the owning thread can run.
1057 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001058 if (sleepDelay == 0) {
1059 sched_yield();
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001060 sleepDelay = 1000;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001061 } else {
1062 usleep(sleepDelay);
1063 if (sleepDelay < maxSleepDelay / 2) {
1064 sleepDelay *= 2;
1065 }
1066 }
1067 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001068 } else {
1069 /*
1070 * The thin lock was inflated by another thread.
1071 * Let the VM know we are no longer waiting and
1072 * try again.
1073 */
1074 LOG_THIN("(%d) lock %p surprise-fattened",
1075 threadId, &obj->lock);
1076 dvmChangeStatus(self, oldStatus);
1077 goto retry;
1078 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001079 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001080 LOG_THIN("(%d) spin on lock done %p: %#x (%#x) %#x",
1081 threadId, &obj->lock, 0, *thinp, thin);
1082 /*
1083 * We have acquired the thin lock. Let the VM know that
1084 * we are no longer waiting.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001085 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001086 dvmChangeStatus(self, oldStatus);
1087 /*
1088 * Fatten the lock.
1089 */
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001090 inflateMonitor(self, obj);
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001091 LOG_THIN("(%d) lock %p fattened", threadId, &obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001092 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001093 } else {
1094 /*
1095 * The lock is a fat lock.
1096 */
1097 assert(LW_MONITOR(obj->lock) != NULL);
1098 lockMonitor(self, LW_MONITOR(obj->lock));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001099 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001100#ifdef WITH_DEADLOCK_PREDICTION
1101 /*
1102 * See if we were allowed to grab the lock at this time. We do it
1103 * *after* acquiring the lock, rather than before, so that we can
1104 * freely update the Monitor struct. This seems counter-intuitive,
1105 * but our goal is deadlock *prediction* not deadlock *prevention*.
1106 * (If we actually deadlock, the situation is easy to diagnose from
1107 * a thread dump, so there's no point making a special effort to do
1108 * the checks before the lock is held.)
1109 *
1110 * This needs to happen before we add the object to the thread's
1111 * monitor list, so we can tell the difference between first-lock and
1112 * re-lock.
1113 *
1114 * It's also important that we do this while in THREAD_RUNNING, so
1115 * that we don't interfere with cleanup operations in the GC.
1116 */
1117 if (gDvm.deadlockPredictMode != kDPOff) {
1118 if (self->status != THREAD_RUNNING) {
1119 LOGE("Bad thread status (%d) in DP\n", self->status);
1120 dvmDumpThread(self, false);
1121 dvmAbort();
1122 }
1123 assert(!dvmCheckException(self));
1124 updateDeadlockPrediction(self, obj);
1125 if (dvmCheckException(self)) {
1126 /*
1127 * If we're throwing an exception here, we need to free the
1128 * lock. We add the object to the thread's monitor list so the
1129 * "unlock" code can remove it.
1130 */
1131 dvmAddToMonitorList(self, obj, false);
1132 dvmUnlockObject(self, obj);
1133 LOGV("--- unlocked, pending is '%s'\n",
1134 dvmGetException(self)->clazz->descriptor);
1135 }
1136 }
1137
1138 /*
1139 * Add the locked object, and the current stack trace, to the list
1140 * held by the Thread object. If deadlock prediction isn't on,
1141 * don't capture the stack trace.
1142 */
1143 dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff);
1144#elif defined(WITH_MONITOR_TRACKING)
1145 /*
1146 * Add the locked object to the list held by the Thread object.
1147 */
1148 dvmAddToMonitorList(self, obj, false);
1149#endif
1150}
1151
1152/*
1153 * Implements monitorexit for "synchronized" stuff.
1154 *
1155 * On failure, throws an exception and returns "false".
1156 */
1157bool dvmUnlockObject(Thread* self, Object *obj)
1158{
Carl Shapiro94338aa2009-12-21 11:42:59 -08001159 u4 thin;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001160
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001161 assert(self != NULL);
1162 assert(self->status == THREAD_RUNNING);
1163 assert(obj != NULL);
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001164 /*
1165 * Cache the lock word as its value can change while we are
1166 * examining its state.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001167 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001168 thin = obj->lock;
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001169 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1170 /*
1171 * The lock is thin. We must ensure that the lock is owned
1172 * by the given thread before unlocking it.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001173 */
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001174 if (LW_LOCK_OWNER(thin) == self->threadId) {
1175 /*
1176 * We are the lock owner. It is safe to update the lock
1177 * without CAS as lock ownership guards the lock itself.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001178 */
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001179 if (LW_LOCK_COUNT(thin) == 0) {
1180 /*
1181 * The lock was not recursively acquired, the common
1182 * case. Unlock by clearing all bits except for the
1183 * hash state.
1184 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001185 obj->lock &= (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT);
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001186 } else {
1187 /*
1188 * The object was recursively acquired. Decrement the
1189 * lock recursion count field.
1190 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001191 obj->lock -= 1 << LW_LOCK_COUNT_SHIFT;
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001192 }
1193 } else {
1194 /*
1195 * We do not own the lock. The JVM spec requires that we
1196 * throw an exception in this case.
1197 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001198 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001199 "unlock of unowned monitor");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001200 return false;
1201 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001202 } else {
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001203 /*
1204 * The lock is fat. We must check to see if unlockMonitor has
1205 * raised any exceptions before continuing.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001206 */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001207 assert(LW_MONITOR(obj->lock) != NULL);
1208 if (!unlockMonitor(self, LW_MONITOR(obj->lock))) {
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001209 /*
1210 * An exception has been raised. Do not fall through.
1211 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001212 return false;
1213 }
1214 }
1215
1216#ifdef WITH_MONITOR_TRACKING
1217 /*
1218 * Remove the object from the Thread's list.
1219 */
1220 dvmRemoveFromMonitorList(self, obj);
1221#endif
1222
1223 return true;
1224}
1225
1226/*
1227 * Object.wait(). Also called for class init.
1228 */
1229void dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec,
1230 bool interruptShouldThrow)
1231{
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001232 Monitor* mon;
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001233 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001234
1235 /* If the lock is still thin, we need to fatten it.
1236 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001237 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001238 /* Make sure that 'self' holds the lock.
1239 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001240 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001241 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1242 "object not locked by thread before wait()");
1243 return;
1244 }
1245
1246 /* This thread holds the lock. We need to fatten the lock
1247 * so 'self' can block on it. Don't update the object lock
1248 * field yet, because 'self' needs to acquire the lock before
1249 * any other thread gets a chance.
1250 */
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001251 inflateMonitor(self, obj);
Patrick Scott2446f442010-10-21 14:50:15 -04001252 LOG_THIN("(%d) lock %p fattened by wait()", self->threadId, &obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001253 }
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001254 mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001255 waitMonitor(self, mon, msec, nsec, interruptShouldThrow);
1256}
1257
1258/*
1259 * Object.notify().
1260 */
1261void dvmObjectNotify(Thread* self, Object *obj)
1262{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001263 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001264
1265 /* If the lock is still thin, there aren't any waiters;
1266 * waiting on an object forces lock fattening.
1267 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001268 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001269 /* Make sure that 'self' holds the lock.
1270 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001271 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001272 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1273 "object not locked by thread before notify()");
1274 return;
1275 }
1276
1277 /* no-op; there are no waiters to notify.
1278 */
1279 } else {
1280 /* It's a fat lock.
1281 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001282 notifyMonitor(self, LW_MONITOR(thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001283 }
1284}
1285
1286/*
1287 * Object.notifyAll().
1288 */
1289void dvmObjectNotifyAll(Thread* self, Object *obj)
1290{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001291 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001292
1293 /* If the lock is still thin, there aren't any waiters;
1294 * waiting on an object forces lock fattening.
1295 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001296 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001297 /* Make sure that 'self' holds the lock.
1298 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001299 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001300 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1301 "object not locked by thread before notifyAll()");
1302 return;
1303 }
1304
1305 /* no-op; there are no waiters to notify.
1306 */
1307 } else {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001308 /* It's a fat lock.
1309 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001310 notifyAllMonitor(self, LW_MONITOR(thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001311 }
1312}
1313
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001314/*
1315 * This implements java.lang.Thread.sleep(long msec, int nsec).
1316 *
1317 * The sleep is interruptible by other threads, which means we can't just
1318 * plop into an OS sleep call. (We probably could if we wanted to send
1319 * signals around and rely on EINTR, but that's inefficient and relies
1320 * on native code respecting our signal mask.)
1321 *
1322 * We have to do all of this stuff for Object.wait() as well, so it's
1323 * easiest to just sleep on a private Monitor.
1324 *
1325 * It appears that we want sleep(0,0) to go through the motions of sleeping
1326 * for a very short duration, rather than just returning.
1327 */
1328void dvmThreadSleep(u8 msec, u4 nsec)
1329{
1330 Thread* self = dvmThreadSelf();
1331 Monitor* mon = gDvm.threadSleepMon;
1332
1333 /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */
1334 if (msec == 0 && nsec == 0)
1335 nsec++;
1336
1337 lockMonitor(self, mon);
1338 waitMonitor(self, mon, msec, nsec, true);
1339 unlockMonitor(self, mon);
1340}
1341
1342/*
1343 * Implement java.lang.Thread.interrupt().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001344 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001345void dvmThreadInterrupt(Thread* thread)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001346{
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001347 assert(thread != NULL);
1348
Carl Shapiro980ffb02010-03-13 22:34:01 -08001349 dvmLockMutex(&thread->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001350
1351 /*
1352 * If the interrupted flag is already set no additional action is
1353 * required.
1354 */
1355 if (thread->interrupted == true) {
Carl Shapiro980ffb02010-03-13 22:34:01 -08001356 dvmUnlockMutex(&thread->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001357 return;
1358 }
1359
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001360 /*
1361 * Raise the "interrupted" flag. This will cause it to bail early out
1362 * of the next wait() attempt, if it's not currently waiting on
1363 * something.
1364 */
1365 thread->interrupted = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001366
1367 /*
1368 * Is the thread waiting?
1369 *
1370 * Note that fat vs. thin doesn't matter here; waitMonitor
1371 * is only set when a thread actually waits on a monitor,
1372 * which implies that the monitor has already been fattened.
1373 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001374 if (thread->waitMonitor != NULL) {
1375 pthread_cond_signal(&thread->waitCond);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001376 }
1377
Carl Shapiro980ffb02010-03-13 22:34:01 -08001378 dvmUnlockMutex(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001379}
1380
Carl Shapiro30aa9972010-01-13 22:07:50 -08001381#ifndef WITH_COPYING_GC
Carl Shapiro94338aa2009-12-21 11:42:59 -08001382u4 dvmIdentityHashCode(Object *obj)
1383{
1384 return (u4)obj;
1385}
Carl Shapiro30aa9972010-01-13 22:07:50 -08001386#else
Carl Shapiro30aa9972010-01-13 22:07:50 -08001387/*
1388 * Returns the identity hash code of the given object.
1389 */
1390u4 dvmIdentityHashCode(Object *obj)
1391{
1392 Thread *self, *thread;
1393 volatile u4 *lw;
Carl Shapirobfe4dcc2010-04-16 17:55:27 -07001394 size_t size;
Carl Shapiro30aa9972010-01-13 22:07:50 -08001395 u4 lock, owner, hashState;
1396
1397 if (obj == NULL) {
1398 /*
1399 * Null is defined to have an identity hash code of 0.
1400 */
1401 return 0;
1402 }
1403 lw = &obj->lock;
1404retry:
1405 hashState = LW_HASH_STATE(*lw);
1406 if (hashState == LW_HASH_STATE_HASHED) {
1407 /*
1408 * The object has been hashed but has not had its hash code
1409 * relocated by the garbage collector. Use the raw object
1410 * address.
1411 */
1412 return (u4)obj >> 3;
1413 } else if (hashState == LW_HASH_STATE_HASHED_AND_MOVED) {
1414 /*
1415 * The object has been hashed and its hash code has been
1416 * relocated by the collector. Use the value of the naturally
1417 * aligned word following the instance data.
1418 */
Carl Shapiroc48b6d02010-05-04 11:19:53 -07001419 assert(obj->clazz != gDvm.classJavaLangClass);
Carl Shapiro30aa9972010-01-13 22:07:50 -08001420 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
Carl Shapirobfe4dcc2010-04-16 17:55:27 -07001421 size = dvmArrayObjectSize((ArrayObject *)obj);
Carl Shapiroc48b6d02010-05-04 11:19:53 -07001422 size = (size + 2) & ~2;
Carl Shapiro30aa9972010-01-13 22:07:50 -08001423 } else {
Carl Shapirobfe4dcc2010-04-16 17:55:27 -07001424 size = obj->clazz->objectSize;
Carl Shapiro30aa9972010-01-13 22:07:50 -08001425 }
Carl Shapirobfe4dcc2010-04-16 17:55:27 -07001426 return *(u4 *)(((char *)obj) + size);
Carl Shapiro30aa9972010-01-13 22:07:50 -08001427 } else if (hashState == LW_HASH_STATE_UNHASHED) {
1428 /*
1429 * The object has never been hashed. Change the hash state to
1430 * hashed and use the raw object address.
1431 */
1432 self = dvmThreadSelf();
1433 if (self->threadId == lockOwner(obj)) {
1434 /*
1435 * We already own the lock so we can update the hash state
1436 * directly.
1437 */
1438 *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
1439 return (u4)obj >> 3;
1440 }
1441 /*
1442 * We do not own the lock. Try acquiring the lock. Should
1443 * this fail, we must suspend the owning thread.
1444 */
1445 if (LW_SHAPE(*lw) == LW_SHAPE_THIN) {
1446 /*
1447 * If the lock is thin assume it is unowned. We simulate
1448 * an acquire, update, and release with a single CAS.
1449 */
1450 lock = DVM_LOCK_INITIAL_THIN_VALUE;
1451 lock |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
Carl Shapiro3ba10c92010-09-02 16:43:16 -07001452 if (android_atomic_acquire_cas(
Carl Shapiro30aa9972010-01-13 22:07:50 -08001453 (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
Andy McFadden6e10b9a2010-06-14 15:24:39 -07001454 (int32_t)lock,
1455 (int32_t *)lw) == 0) {
Carl Shapiro30aa9972010-01-13 22:07:50 -08001456 /*
1457 * A new lockword has been installed with a hash state
1458 * of hashed. Use the raw object address.
1459 */
1460 return (u4)obj >> 3;
1461 }
1462 } else {
1463 if (tryLockMonitor(self, LW_MONITOR(*lw))) {
1464 /*
1465 * The monitor lock has been acquired. Change the
1466 * hash state to hashed and use the raw object
1467 * address.
1468 */
1469 *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
1470 unlockMonitor(self, LW_MONITOR(*lw));
1471 return (u4)obj >> 3;
1472 }
1473 }
1474 /*
1475 * At this point we have failed to acquire the lock. We must
1476 * identify the owning thread and suspend it.
1477 */
1478 dvmLockThreadList(self);
1479 /*
1480 * Cache the lock word as its value can change between
1481 * determining its shape and retrieving its owner.
1482 */
1483 lock = *lw;
1484 if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
1485 /*
1486 * Find the thread with the corresponding thread id.
1487 */
1488 owner = LW_LOCK_OWNER(lock);
1489 assert(owner != self->threadId);
1490 /*
1491 * If the lock has no owner do not bother scanning the
1492 * thread list and fall through to the failure handler.
1493 */
1494 thread = owner ? gDvm.threadList : NULL;
1495 while (thread != NULL) {
1496 if (thread->threadId == owner) {
1497 break;
1498 }
1499 thread = thread->next;
1500 }
1501 } else {
1502 thread = LW_MONITOR(lock)->owner;
1503 }
1504 /*
1505 * If thread is NULL the object has been released since the
1506 * thread list lock was acquired. Try again.
1507 */
1508 if (thread == NULL) {
1509 dvmUnlockThreadList();
1510 goto retry;
1511 }
1512 /*
1513 * Wait for the owning thread to suspend.
1514 */
1515 dvmSuspendThread(thread);
1516 if (dvmHoldsLock(thread, obj)) {
1517 /*
1518 * The owning thread has been suspended. We can safely
1519 * change the hash state to hashed.
1520 */
1521 *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
1522 dvmResumeThread(thread);
1523 dvmUnlockThreadList();
1524 return (u4)obj >> 3;
1525 }
1526 /*
1527 * The wrong thread has been suspended. Try again.
1528 */
1529 dvmResumeThread(thread);
1530 dvmUnlockThreadList();
1531 goto retry;
1532 }
1533 LOGE("object %p has an unknown hash state %#x", obj, hashState);
1534 dvmDumpThread(dvmThreadSelf(), false);
1535 dvmAbort();
1536 return 0; /* Quiet the compiler. */
1537}
1538#endif /* WITH_COPYING_GC */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001539
1540#ifdef WITH_DEADLOCK_PREDICTION
1541/*
1542 * ===========================================================================
1543 * Deadlock prediction
1544 * ===========================================================================
1545 */
1546/*
1547The idea is to predict the possibility of deadlock by recording the order
1548in which monitors are acquired. If we see an attempt to acquire a lock
1549out of order, we can identify the locks and offending code.
1550
1551To make this work, we need to keep track of the locks held by each thread,
1552and create history trees for each lock. When a thread tries to acquire
1553a new lock, we walk through the "history children" of the lock, looking
1554for a match with locks the thread already holds. If we find a match,
1555it means the thread has made a request that could result in a deadlock.
1556
1557To support recursive locks, we always allow re-locking a currently-held
1558lock, and maintain a recursion depth count.
1559
1560An ASCII-art example, where letters represent Objects:
1561
1562 A
1563 /|\
1564 / | \
1565 B | D
1566 \ |
1567 \|
1568 C
1569
1570The above is the tree we'd have after handling Object synchronization
1571sequences "ABC", "AC", "AD". A has three children, {B, C, D}. C is also
1572a child of B. (The lines represent pointers between parent and child.
1573Every node can have multiple parents and multiple children.)
1574
1575If we hold AC, and want to lock B, we recursively search through B's
1576children to see if A or C appears. It does, so we reject the attempt.
1577(A straightforward way to implement it: add a link from C to B, then
1578determine whether the graph starting at B contains a cycle.)
1579
1580If we hold AC and want to lock D, we would succeed, creating a new link
1581from C to D.
1582
1583The lock history and a stack trace is attached to the Object's Monitor
1584struct, which means we need to fatten every Object we lock (thin locking
1585is effectively disabled). If we don't need the stack trace we can
1586avoid fattening the leaf nodes, only fattening objects that need to hold
1587history trees.
1588
1589Updates to Monitor structs are only allowed for the thread that holds
1590the Monitor, so we actually do most of our deadlock prediction work after
1591the lock has been acquired.
1592
1593When an object with a monitor is GCed, we need to remove it from the
1594history trees. There are two basic approaches:
1595 (1) For through the entire set of known monitors, search all child
1596 lists for the object in question. This is rather slow, resulting
1597 in GC passes that take upwards of 10 seconds to complete.
1598 (2) Maintain "parent" pointers in each node. Remove the entries as
1599 required. This requires additional storage and maintenance for
1600 every operation, but is significantly faster at GC time.
1601For each GCed object, we merge all of the object's children into each of
1602the object's parents.
1603*/
1604
1605#if !defined(WITH_MONITOR_TRACKING)
1606# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING"
1607#endif
1608
1609/*
1610 * Clear out the contents of an ExpandingObjectList, freeing any
1611 * dynamic allocations.
1612 */
1613static void expandObjClear(ExpandingObjectList* pList)
1614{
1615 if (pList->list != NULL) {
1616 free(pList->list);
1617 pList->list = NULL;
1618 }
1619 pList->alloc = pList->count = 0;
1620}
1621
1622/*
1623 * Get the number of objects currently stored in the list.
1624 */
1625static inline int expandBufGetCount(const ExpandingObjectList* pList)
1626{
1627 return pList->count;
1628}
1629
1630/*
1631 * Get the Nth entry from the list.
1632 */
1633static inline Object* expandBufGetEntry(const ExpandingObjectList* pList,
1634 int i)
1635{
1636 return pList->list[i];
1637}
1638
1639/*
1640 * Add a new entry to the list.
1641 *
1642 * We don't check for or try to enforce uniqueness. It's expected that
1643 * the higher-level code does this for us.
1644 */
1645static void expandObjAddEntry(ExpandingObjectList* pList, Object* obj)
1646{
1647 if (pList->count == pList->alloc) {
1648 /* time to expand */
1649 Object** newList;
1650
1651 if (pList->alloc == 0)
1652 pList->alloc = 4;
1653 else
1654 pList->alloc *= 2;
1655 LOGVV("expanding %p to %d\n", pList, pList->alloc);
1656 newList = realloc(pList->list, pList->alloc * sizeof(Object*));
1657 if (newList == NULL) {
1658 LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc);
1659 dvmAbort();
1660 }
1661 pList->list = newList;
1662 }
1663
1664 pList->list[pList->count++] = obj;
1665}
1666
1667/*
1668 * Returns "true" if the element was successfully removed.
1669 */
1670static bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj)
1671{
1672 int i;
1673
1674 for (i = pList->count-1; i >= 0; i--) {
1675 if (pList->list[i] == obj)
1676 break;
1677 }
1678 if (i < 0)
1679 return false;
1680
1681 if (i != pList->count-1) {
1682 /*
1683 * The order of elements is not important, so we just copy the
1684 * last entry into the new slot.
1685 */
1686 //memmove(&pList->list[i], &pList->list[i+1],
1687 // (pList->count-1 - i) * sizeof(pList->list[0]));
1688 pList->list[i] = pList->list[pList->count-1];
1689 }
1690
1691 pList->count--;
1692 pList->list[pList->count] = (Object*) 0xdecadead;
1693 return true;
1694}
1695
1696/*
1697 * Returns "true" if "obj" appears in the list.
1698 */
1699static bool expandObjHas(const ExpandingObjectList* pList, Object* obj)
1700{
1701 int i;
1702
1703 for (i = 0; i < pList->count; i++) {
1704 if (pList->list[i] == obj)
1705 return true;
1706 }
1707 return false;
1708}
1709
1710/*
1711 * Print the list contents to stdout. For debugging.
1712 */
1713static void expandObjDump(const ExpandingObjectList* pList)
1714{
1715 int i;
1716 for (i = 0; i < pList->count; i++)
1717 printf(" %p", pList->list[i]);
1718}
1719
1720/*
1721 * Check for duplicate entries. Returns the index of the first instance
1722 * of the duplicated value, or -1 if no duplicates were found.
1723 */
1724static int expandObjCheckForDuplicates(const ExpandingObjectList* pList)
1725{
1726 int i, j;
1727 for (i = 0; i < pList->count-1; i++) {
1728 for (j = i + 1; j < pList->count; j++) {
1729 if (pList->list[i] == pList->list[j]) {
1730 return i;
1731 }
1732 }
1733 }
1734
1735 return -1;
1736}
1737
1738
1739/*
1740 * Determine whether "child" appears in the list of objects associated
1741 * with the Monitor in "parent". If "parent" is a thin lock, we return
1742 * false immediately.
1743 */
1744static bool objectInChildList(const Object* parent, Object* child)
1745{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001746 u4 lock = parent->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001747 if (!IS_LOCK_FAT(&lock)) {
1748 //LOGI("on thin\n");
1749 return false;
1750 }
1751
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001752 return expandObjHas(&LW_MONITOR(lock)->historyChildren, child);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001753}
1754
1755/*
1756 * Print the child list.
1757 */
1758static void dumpKids(Object* parent)
1759{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001760 Monitor* mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001761
1762 printf("Children of %p:", parent);
1763 expandObjDump(&mon->historyChildren);
1764 printf("\n");
1765}
1766
1767/*
1768 * Add "child" to the list of children in "parent", and add "parent" to
1769 * the list of parents in "child".
1770 */
1771static void linkParentToChild(Object* parent, Object* child)
1772{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001773 //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for merge
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001774 assert(IS_LOCK_FAT(&parent->lock));
1775 assert(IS_LOCK_FAT(&child->lock));
1776 assert(parent != child);
1777 Monitor* mon;
1778
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001779 mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001780 assert(!expandObjHas(&mon->historyChildren, child));
1781 expandObjAddEntry(&mon->historyChildren, child);
1782
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001783 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001784 assert(!expandObjHas(&mon->historyParents, parent));
1785 expandObjAddEntry(&mon->historyParents, parent);
1786}
1787
1788
1789/*
1790 * Remove "child" from the list of children in "parent".
1791 */
1792static void unlinkParentFromChild(Object* parent, Object* child)
1793{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001794 //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for GC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001795 assert(IS_LOCK_FAT(&parent->lock));
1796 assert(IS_LOCK_FAT(&child->lock));
1797 assert(parent != child);
1798 Monitor* mon;
1799
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001800 mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001801 if (!expandObjRemoveEntry(&mon->historyChildren, child)) {
1802 LOGW("WARNING: child %p not found in parent %p\n", child, parent);
1803 }
1804 assert(!expandObjHas(&mon->historyChildren, child));
1805 assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0);
1806
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001807 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001808 if (!expandObjRemoveEntry(&mon->historyParents, parent)) {
1809 LOGW("WARNING: parent %p not found in child %p\n", parent, child);
1810 }
1811 assert(!expandObjHas(&mon->historyParents, parent));
1812 assert(expandObjCheckForDuplicates(&mon->historyParents) < 0);
1813}
1814
1815
1816/*
1817 * Log the monitors held by the current thread. This is done as part of
1818 * flagging an error.
1819 */
1820static void logHeldMonitors(Thread* self)
1821{
1822 char* name = NULL;
1823
1824 name = dvmGetThreadName(self);
1825 LOGW("Monitors currently held by thread (threadid=%d '%s')\n",
1826 self->threadId, name);
1827 LOGW("(most-recently-acquired on top):\n");
1828 free(name);
1829
1830 LockedObjectData* lod = self->pLockedObjects;
1831 while (lod != NULL) {
1832 LOGW("--- object %p[%d] (%s)\n",
1833 lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
1834 dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth);
1835
1836 lod = lod->next;
1837 }
1838}
1839
1840/*
1841 * Recursively traverse the object hierarchy starting at "obj". We mark
1842 * ourselves on entry and clear the mark on exit. If we ever encounter
1843 * a marked object, we have a cycle.
1844 *
1845 * Returns "true" if all is well, "false" if we found a cycle.
1846 */
1847static bool traverseTree(Thread* self, const Object* obj)
1848{
1849 assert(IS_LOCK_FAT(&obj->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001850 Monitor* mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001851
1852 /*
1853 * Have we been here before?
1854 */
1855 if (mon->historyMark) {
1856 int* rawStackTrace;
1857 int stackDepth;
1858
1859 LOGW("%s\n", kStartBanner);
1860 LOGW("Illegal lock attempt:\n");
1861 LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1862
1863 rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth);
1864 dvmLogRawStackTrace(rawStackTrace, stackDepth);
1865 free(rawStackTrace);
1866
1867 LOGW(" ");
1868 logHeldMonitors(self);
1869
1870 LOGW(" ");
1871 LOGW("Earlier, the following lock order (from last to first) was\n");
1872 LOGW("established -- stack trace is from first successful lock):\n");
1873 return false;
1874 }
1875 mon->historyMark = true;
1876
1877 /*
1878 * Examine the children. We do NOT hold these locks, so they might
1879 * very well transition from thin to fat or change ownership while
1880 * we work.
1881 *
1882 * NOTE: we rely on the fact that they cannot revert from fat to thin
1883 * while we work. This is currently a safe assumption.
1884 *
1885 * We can safely ignore thin-locked children, because by definition
1886 * they have no history and are leaf nodes. In the current
1887 * implementation we always fatten the locks to provide a place to
1888 * hang the stack trace.
1889 */
1890 ExpandingObjectList* pList = &mon->historyChildren;
1891 int i;
1892 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1893 const Object* child = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001894 u4 lock = child->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001895 if (!IS_LOCK_FAT(&lock))
1896 continue;
1897 if (!traverseTree(self, child)) {
1898 LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1899 dvmLogRawStackTrace(mon->historyRawStackTrace,
1900 mon->historyStackDepth);
1901 mon->historyMark = false;
1902 return false;
1903 }
1904 }
1905
1906 mon->historyMark = false;
1907
1908 return true;
1909}
1910
1911/*
1912 * Update the deadlock prediction tree, based on the current thread
1913 * acquiring "acqObj". This must be called before the object is added to
1914 * the thread's list of held monitors.
1915 *
1916 * If the thread already holds the lock (recursion), or this is a known
1917 * lock configuration, we return without doing anything. Otherwise, we add
1918 * a link from the most-recently-acquired lock in this thread to "acqObj"
1919 * after ensuring that the parent lock is "fat".
1920 *
1921 * This MUST NOT be called while a GC is in progress in another thread,
1922 * because we assume exclusive access to history trees in owned monitors.
1923 */
1924static void updateDeadlockPrediction(Thread* self, Object* acqObj)
1925{
1926 LockedObjectData* lod;
1927 LockedObjectData* mrl;
1928
1929 /*
1930 * Quick check for recursive access.
1931 */
1932 lod = dvmFindInMonitorList(self, acqObj);
1933 if (lod != NULL) {
1934 LOGV("+++ DP: recursive %p\n", acqObj);
1935 return;
1936 }
1937
1938 /*
1939 * Make the newly-acquired object's monitor "fat". In some ways this
1940 * isn't strictly necessary, but we need the GC to tell us when
1941 * "interesting" objects go away, and right now the only way to make
1942 * an object look interesting is to give it a monitor.
1943 *
1944 * This also gives us a place to hang a stack trace.
1945 *
1946 * Our thread holds the lock, so we're allowed to rewrite the lock
1947 * without worrying that something will change out from under us.
1948 */
1949 if (!IS_LOCK_FAT(&acqObj->lock)) {
1950 LOGVV("fattening lockee %p (recur=%d)\n",
Carl Shapiro94338aa2009-12-21 11:42:59 -08001951 acqObj, LW_LOCK_COUNT(acqObj->lock.thin));
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001952 inflateMonitor(self, acqObj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001953 }
1954
1955 /* if we don't have a stack trace for this monitor, establish one */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001956 if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) {
1957 Monitor* mon = LW_MONITOR(acqObj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001958 mon->historyRawStackTrace = dvmFillInStackTraceRaw(self,
1959 &mon->historyStackDepth);
1960 }
1961
1962 /*
1963 * We need to examine and perhaps modify the most-recently-locked
1964 * monitor. We own that, so there's no risk of another thread
1965 * stepping on us.
1966 *
1967 * Retrieve the most-recently-locked entry from our thread.
1968 */
1969 mrl = self->pLockedObjects;
1970 if (mrl == NULL)
1971 return; /* no other locks held */
1972
1973 /*
1974 * Do a quick check to see if "acqObj" is a direct descendant. We can do
1975 * this without holding the global lock because of our assertion that
1976 * a GC is not running in parallel -- nobody except the GC can
1977 * modify a history list in a Monitor they don't own, and we own "mrl".
1978 * (There might be concurrent *reads*, but no concurrent *writes.)
1979 *
1980 * If we find it, this is a known good configuration, and we're done.
1981 */
1982 if (objectInChildList(mrl->obj, acqObj))
1983 return;
1984
1985 /*
1986 * "mrl" is going to need to have a history tree. If it's currently
1987 * a thin lock, we make it fat now. The thin lock might have a
1988 * nonzero recursive lock count, which we need to carry over.
1989 *
1990 * Our thread holds the lock, so we're allowed to rewrite the lock
1991 * without worrying that something will change out from under us.
1992 */
1993 if (!IS_LOCK_FAT(&mrl->obj->lock)) {
1994 LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n",
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001995 mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock));
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001996 inflateMonitor(self, mrl->obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001997 }
1998
1999 /*
2000 * We haven't seen this configuration before. We need to scan down
2001 * acqObj's tree to see if any of the monitors in self->pLockedObjects
2002 * appear. We grab a global lock before traversing or updating the
2003 * history list.
2004 *
2005 * If we find a match for any of our held locks, we know that the lock
2006 * has previously been acquired *after* acqObj, and we throw an error.
2007 *
2008 * The easiest way to do this is to create a link from "mrl" to "acqObj"
2009 * and do a recursive traversal, marking nodes as we cross them. If
2010 * we cross one a second time, we have a cycle and can throw an error.
2011 * (We do the flag-clearing traversal before adding the new link, so
2012 * that we're guaranteed to terminate.)
2013 *
2014 * If "acqObj" is a thin lock, it has no history, and we can create a
2015 * link to it without additional checks. [ We now guarantee that it's
2016 * always fat. ]
2017 */
2018 bool failed = false;
2019 dvmLockMutex(&gDvm.deadlockHistoryLock);
2020 linkParentToChild(mrl->obj, acqObj);
2021 if (!traverseTree(self, acqObj)) {
2022 LOGW("%s\n", kEndBanner);
2023 failed = true;
2024
2025 /* remove the entry so we're still okay when in "warning" mode */
2026 unlinkParentFromChild(mrl->obj, acqObj);
2027 }
2028 dvmUnlockMutex(&gDvm.deadlockHistoryLock);
2029
2030 if (failed) {
2031 switch (gDvm.deadlockPredictMode) {
2032 case kDPErr:
2033 dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL);
2034 break;
2035 case kDPAbort:
2036 LOGE("Aborting due to potential deadlock\n");
2037 dvmAbort();
2038 break;
2039 default:
2040 /* warn only */
2041 break;
2042 }
2043 }
2044}
2045
2046/*
2047 * We're removing "child" from existence. We want to pull all of
2048 * child's children into "parent", filtering out duplicates. This is
2049 * called during the GC.
2050 *
2051 * This does not modify "child", which might have multiple parents.
2052 */
2053static void mergeChildren(Object* parent, const Object* child)
2054{
2055 Monitor* mon;
2056 int i;
2057
2058 assert(IS_LOCK_FAT(&child->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08002059 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002060 ExpandingObjectList* pList = &mon->historyChildren;
2061
2062 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2063 Object* grandChild = expandBufGetEntry(pList, i);
2064
2065 if (!objectInChildList(parent, grandChild)) {
2066 LOGVV("+++ migrating %p link to %p\n", grandChild, parent);
2067 linkParentToChild(parent, grandChild);
2068 } else {
2069 LOGVV("+++ parent %p already links to %p\n", parent, grandChild);
2070 }
2071 }
2072}
2073
2074/*
2075 * An object with a fat lock is being collected during a GC pass. We
2076 * want to remove it from any lock history trees that it is a part of.
2077 *
2078 * This may require updating the history trees in several monitors. The
2079 * monitor semantics guarantee that no other thread will be accessing
2080 * the history trees at the same time.
2081 */
2082static void removeCollectedObject(Object* obj)
2083{
2084 Monitor* mon;
2085
2086 LOGVV("+++ collecting %p\n", obj);
2087
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002088 /*
2089 * For every parent of this object:
2090 * - merge all of our children into the parent's child list (creates
2091 * a two-way link between parent and child)
2092 * - remove ourselves from the parent's child list
2093 */
2094 ExpandingObjectList* pList;
2095 int i;
2096
2097 assert(IS_LOCK_FAT(&obj->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08002098 mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002099 pList = &mon->historyParents;
2100 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2101 Object* parent = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08002102 Monitor* parentMon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002103
2104 if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) {
2105 LOGW("WARNING: child %p not found in parent %p\n", obj, parent);
2106 }
2107 assert(!expandObjHas(&parentMon->historyChildren, obj));
2108
2109 mergeChildren(parent, obj);
2110 }
2111
2112 /*
2113 * For every child of this object:
2114 * - remove ourselves from the child's parent list
2115 */
2116 pList = &mon->historyChildren;
2117 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2118 Object* child = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08002119 Monitor* childMon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002120
2121 if (!expandObjRemoveEntry(&childMon->historyParents, obj)) {
2122 LOGW("WARNING: parent %p not found in child %p\n", obj, child);
2123 }
2124 assert(!expandObjHas(&childMon->historyParents, obj));
2125 }
2126}
2127
2128#endif /*WITH_DEADLOCK_PREDICTION*/