blob: 967a0d01e845a29c19b8d74d5bd049be5634fa90 [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{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800215 if (gDvm.zygote) {
216 return;
217 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800218
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/*
Carl Shapiro30aa9972010-01-13 22:07:50 -0800247 * Returns the thread id of the thread owning the given lock.
248 */
249static u4 lockOwner(Object* obj)
250{
251 Thread *owner;
252 u4 lock;
253
254 assert(obj != NULL);
255 /*
256 * Since we're reading the lock value multiple times, latch it so
257 * that it doesn't change out from under us if we get preempted.
258 */
259 lock = obj->lock;
260 if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
261 return LW_LOCK_OWNER(lock);
262 } else {
263 owner = LW_MONITOR(lock)->owner;
264 return owner ? owner->threadId : 0;
265 }
266}
267
268/*
Andy McFaddenfd542662010-03-12 13:39:59 -0800269 * Get the thread that holds the lock on the specified object. The
270 * object may be unlocked, thin-locked, or fat-locked.
271 *
272 * The caller must lock the thread list before calling here.
273 */
274Thread* dvmGetObjectLockHolder(Object* obj)
275{
276 u4 threadId = lockOwner(obj);
277
278 if (threadId == 0)
279 return NULL;
280 return dvmGetThreadByThreadId(threadId);
281}
282
283/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800284 * Checks whether the given thread holds the given
285 * objects's lock.
286 */
287bool dvmHoldsLock(Thread* thread, Object* obj)
288{
289 if (thread == NULL || obj == NULL) {
290 return false;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800291 } else {
Carl Shapiro30aa9972010-01-13 22:07:50 -0800292 return thread->threadId == lockOwner(obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800293 }
294}
295
296/*
297 * Free the monitor associated with an object and make the object's lock
298 * thin again. This is called during garbage collection.
299 */
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800300static void freeObjectMonitor(Object* obj)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800301{
302 Monitor *mon;
303
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800304 assert(LW_SHAPE(obj->lock) == LW_SHAPE_FAT);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800305
306#ifdef WITH_DEADLOCK_PREDICTION
307 if (gDvm.deadlockPredictMode != kDPOff)
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800308 removeCollectedObject(obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800309#endif
310
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800311 mon = LW_MONITOR(obj->lock);
312 obj->lock = DVM_LOCK_INITIAL_THIN_VALUE;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800313
314 /* This lock is associated with an object
315 * that's being swept. The only possible way
316 * anyone could be holding this lock would be
317 * if some JNI code locked but didn't unlock
318 * the object, in which case we've got some bad
319 * native code somewhere.
320 */
Carl Shapiro1ff876d2010-04-04 01:56:48 -0700321 assert(pthread_mutex_trylock(&mon->lock) == 0);
322 assert(pthread_mutex_unlock(&mon->lock) == 0);
Carl Shapiro980ffb02010-03-13 22:34:01 -0800323 dvmDestroyMutex(&mon->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800324#ifdef WITH_DEADLOCK_PREDICTION
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800325 expandObjClear(&mon->historyChildren);
326 expandObjClear(&mon->historyParents);
327 free(mon->historyRawStackTrace);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800328#endif
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800329 free(mon);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800330}
331
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800332/*
333 * Frees monitor objects belonging to unmarked objects.
334 */
335void dvmSweepMonitorList(Monitor** mon, int (*isUnmarkedObject)(void*))
336{
337 Monitor handle;
338 Monitor *prev, *curr;
339 Object *obj;
340
341 assert(mon != NULL);
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800342 assert(isUnmarkedObject != NULL);
Carl Shapiro8881a802010-08-10 15:55:45 -0700343#ifdef WITH_DEADLOCK_PREDICTION
344 dvmDumpMonitorInfo("before monitor sweep");
345#endif
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800346 prev = &handle;
347 prev->next = curr = *mon;
348 while (curr != NULL) {
349 obj = curr->obj;
350 if (obj != NULL && (*isUnmarkedObject)(obj) != 0) {
351 prev->next = curr = curr->next;
352 freeObjectMonitor(obj);
353 } else {
354 prev = curr;
355 curr = curr->next;
356 }
357 }
358 *mon = handle.next;
Carl Shapiro8881a802010-08-10 15:55:45 -0700359#ifdef WITH_DEADLOCK_PREDICTION
360 dvmDumpMonitorInfo("after monitor sweep");
361#endif
Carl Shapiro5a6071b2010-01-07 21:35:50 -0800362}
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800363
Carl Shapirof0c514c2010-04-09 15:03:33 -0700364static char *logWriteInt(char *dst, int value)
365{
366 *dst++ = EVENT_TYPE_INT;
367 set4LE((u1 *)dst, value);
368 return dst + 4;
369}
370
371static char *logWriteString(char *dst, const char *value, size_t len)
372{
373 *dst++ = EVENT_TYPE_STRING;
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700374 len = len < 32 ? len : 32;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700375 set4LE((u1 *)dst, len);
376 dst += 4;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700377 memcpy(dst, value, len);
378 return dst + len;
379}
380
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700381#define EVENT_LOG_TAG_dvm_lock_sample 20003
Carl Shapirof0c514c2010-04-09 15:03:33 -0700382
Carl Shapirofa903b32010-08-31 15:11:46 -0700383static void logContentionEvent(Thread *self, u4 waitMs, u4 samplePercent,
384 const char *ownerFileName, u4 ownerLineNumber)
Carl Shapirof0c514c2010-04-09 15:03:33 -0700385{
386 const StackSaveArea *saveArea;
387 const Method *meth;
388 u4 relativePc;
Carl Shapirofa903b32010-08-31 15:11:46 -0700389 char eventBuffer[174];
Carl Shapirof0c514c2010-04-09 15:03:33 -0700390 const char *fileName;
Carl Shapiroe3c01da2010-05-20 22:54:18 -0700391 char procName[33], *selfName;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700392 char *cp;
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700393 size_t len;
394 int fd;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700395
396 saveArea = SAVEAREA_FROM_FP(self->curFrame);
397 meth = saveArea->method;
398 cp = eventBuffer;
399
400 /* Emit the event list length, 1 byte. */
Carl Shapirofa903b32010-08-31 15:11:46 -0700401 *cp++ = 9;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700402
403 /* Emit the process name, <= 37 bytes. */
404 fd = open("/proc/self/cmdline", O_RDONLY);
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700405 memset(procName, 0, sizeof(procName));
406 read(fd, procName, sizeof(procName) - 1);
Carl Shapirof0c514c2010-04-09 15:03:33 -0700407 close(fd);
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700408 len = strlen(procName);
409 cp = logWriteString(cp, procName, len);
Carl Shapirof0c514c2010-04-09 15:03:33 -0700410
Brad Fitzpatrick3b556752010-12-13 16:53:28 -0800411 /* Emit the sensitive thread ("main thread") status, 5 bytes. */
412 bool isSensitive = false;
413 if (gDvm.isSensitiveThreadHook != NULL) {
414 isSensitive = gDvm.isSensitiveThreadHook();
415 }
416 cp = logWriteInt(cp, isSensitive);
Carl Shapirof0c514c2010-04-09 15:03:33 -0700417
418 /* Emit self thread name string, <= 37 bytes. */
419 selfName = dvmGetThreadName(self);
420 cp = logWriteString(cp, selfName, strlen(selfName));
421 free(selfName);
422
423 /* Emit the wait time, 5 bytes. */
424 cp = logWriteInt(cp, waitMs);
425
426 /* Emit the source code file name, <= 37 bytes. */
427 fileName = dvmGetMethodSourceFile(meth);
428 if (fileName == NULL) fileName = "";
429 cp = logWriteString(cp, fileName, strlen(fileName));
430
431 /* Emit the source code line number, 5 bytes. */
432 relativePc = saveArea->xtra.currentPc - saveArea->method->insns;
433 cp = logWriteInt(cp, dvmLineNumFromPC(meth, relativePc));
434
Carl Shapirofa903b32010-08-31 15:11:46 -0700435 /* Emit the lock owner source code file name, <= 37 bytes. */
436 if (ownerFileName == NULL) {
Brad Fitzpatrick3b556752010-12-13 16:53:28 -0800437 ownerFileName = "";
Carl Shapirofa903b32010-08-31 15:11:46 -0700438 } else if (strcmp(fileName, ownerFileName) == 0) {
Brad Fitzpatrick3b556752010-12-13 16:53:28 -0800439 /* Common case, so save on log space. */
440 ownerFileName = "-";
Carl Shapirofa903b32010-08-31 15:11:46 -0700441 }
442 cp = logWriteString(cp, ownerFileName, strlen(ownerFileName));
443
444 /* Emit the source code line number, 5 bytes. */
445 cp = logWriteInt(cp, ownerLineNumber);
446
Carl Shapirof0c514c2010-04-09 15:03:33 -0700447 /* Emit the sample percentage, 5 bytes. */
448 cp = logWriteInt(cp, samplePercent);
449
450 assert((size_t)(cp - eventBuffer) <= sizeof(eventBuffer));
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700451 android_btWriteLog(EVENT_LOG_TAG_dvm_lock_sample,
Carl Shapirof0c514c2010-04-09 15:03:33 -0700452 EVENT_TYPE_LIST,
453 eventBuffer,
454 (size_t)(cp - eventBuffer));
455}
456
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800457/*
458 * Lock a monitor.
459 */
460static void lockMonitor(Thread* self, Monitor* mon)
461{
Carl Shapirof0c514c2010-04-09 15:03:33 -0700462 ThreadStatus oldStatus;
463 u4 waitThreshold, samplePercent;
464 u8 waitStart, waitEnd, waitMs;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800465
466 if (mon->owner == self) {
467 mon->lockCount++;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700468 return;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800469 }
Carl Shapiro045fdc92010-04-13 16:48:27 -0700470 if (dvmTryLockMutex(&mon->lock) != 0) {
Carl Shapirof0c514c2010-04-09 15:03:33 -0700471 oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
472 waitThreshold = gDvm.lockProfThreshold;
473 if (waitThreshold) {
474 waitStart = dvmGetRelativeTimeUsec();
475 }
Carl Shapirofa903b32010-08-31 15:11:46 -0700476 const char* currentOwnerFileName = mon->ownerFileName;
477 u4 currentOwnerLineNumber = mon->ownerLineNumber;
478
Carl Shapirof0c514c2010-04-09 15:03:33 -0700479 dvmLockMutex(&mon->lock);
480 if (waitThreshold) {
481 waitEnd = dvmGetRelativeTimeUsec();
482 }
483 dvmChangeStatus(self, oldStatus);
484 if (waitThreshold) {
485 waitMs = (waitEnd - waitStart) / 1000;
486 if (waitMs >= waitThreshold) {
487 samplePercent = 100;
488 } else {
Carl Shapiroaf69cf82010-04-16 17:33:15 -0700489 samplePercent = 100 * waitMs / waitThreshold;
Carl Shapirof0c514c2010-04-09 15:03:33 -0700490 }
Carl Shapirob8fcf572010-04-16 17:33:15 -0700491 if (samplePercent != 0 && ((u4)rand() % 100 < samplePercent)) {
Carl Shapirofa903b32010-08-31 15:11:46 -0700492 logContentionEvent(self, waitMs, samplePercent,
493 currentOwnerFileName, currentOwnerLineNumber);
Carl Shapirof0c514c2010-04-09 15:03:33 -0700494 }
495 }
496 }
497 mon->owner = self;
498 assert(mon->lockCount == 0);
Carl Shapirofa903b32010-08-31 15:11:46 -0700499
500 // When debugging, save the current monitor holder for future
501 // acquisition failures to use in sampled logging.
502 if (gDvm.lockProfThreshold > 0) {
503 const StackSaveArea *saveArea;
504 const Method *meth;
505 mon->ownerLineNumber = 0;
506 if (self->curFrame == NULL) {
507 mon->ownerFileName = "no_frame";
508 } else if ((saveArea = SAVEAREA_FROM_FP(self->curFrame)) == NULL) {
509 mon->ownerFileName = "no_save_area";
510 } else if ((meth = saveArea->method) == NULL) {
511 mon->ownerFileName = "no_method";
512 } else {
513 u4 relativePc = saveArea->xtra.currentPc - saveArea->method->insns;
514 mon->ownerFileName = (char*) dvmGetMethodSourceFile(meth);
515 if (mon->ownerFileName == NULL) {
516 mon->ownerFileName = "no_method_file";
517 } else {
518 mon->ownerLineNumber = dvmLineNumFromPC(meth, relativePc);
519 }
520 }
521 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800522}
523
524/*
525 * Try to lock a monitor.
526 *
527 * Returns "true" on success.
528 */
Carl Shapirob31b3012010-05-25 18:35:37 -0700529#ifdef WITH_COPYING_GC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800530static bool tryLockMonitor(Thread* self, Monitor* mon)
531{
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800532 if (mon->owner == self) {
533 mon->lockCount++;
534 return true;
535 } else {
Carl Shapiro980ffb02010-03-13 22:34:01 -0800536 if (dvmTryLockMutex(&mon->lock) == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800537 mon->owner = self;
538 assert(mon->lockCount == 0);
539 return true;
540 } else {
541 return false;
542 }
543 }
544}
Carl Shapirob31b3012010-05-25 18:35:37 -0700545#endif
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800546
547/*
548 * Unlock a monitor.
549 *
550 * Returns true if the unlock succeeded.
551 * If the unlock failed, an exception will be pending.
552 */
553static bool unlockMonitor(Thread* self, Monitor* mon)
554{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800555 assert(self != NULL);
Carl Shapiro92277082010-04-06 15:35:59 -0700556 assert(mon != NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800557 if (mon->owner == self) {
558 /*
559 * We own the monitor, so nobody else can be in here.
560 */
561 if (mon->lockCount == 0) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800562 mon->owner = NULL;
Carl Shapirofa903b32010-08-31 15:11:46 -0700563 mon->ownerFileName = "unlocked";
564 mon->ownerLineNumber = 0;
Carl Shapiro980ffb02010-03-13 22:34:01 -0800565 dvmUnlockMutex(&mon->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800566 } else {
567 mon->lockCount--;
568 }
569 } else {
570 /*
571 * We don't own this, so we're not allowed to unlock it.
572 * The JNI spec says that we should throw IllegalMonitorStateException
573 * in this case.
574 */
Carl Shapiro8782d7c2010-04-19 20:10:35 -0700575 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
576 "unlock of unowned monitor");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800577 return false;
578 }
579 return true;
580}
581
582/*
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800583 * Checks the wait set for circular structure. Returns 0 if the list
Carl Shapirob4539192010-01-04 16:50:00 -0800584 * is not circular. Otherwise, returns 1. Used only by asserts.
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800585 */
Carl Shapirob31b3012010-05-25 18:35:37 -0700586#ifndef NDEBUG
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800587static int waitSetCheck(Monitor *mon)
588{
589 Thread *fast, *slow;
590 size_t n;
591
592 assert(mon != NULL);
593 fast = slow = mon->waitSet;
594 n = 0;
595 for (;;) {
596 if (fast == NULL) return 0;
597 if (fast->waitNext == NULL) return 0;
Carl Shapiro5f56e672010-01-05 20:38:03 -0800598 if (fast == slow && n > 0) return 1;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800599 n += 2;
600 fast = fast->waitNext->waitNext;
601 slow = slow->waitNext;
602 }
603}
Carl Shapirob31b3012010-05-25 18:35:37 -0700604#endif
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800605
606/*
Carl Shapiro30aa9972010-01-13 22:07:50 -0800607 * Links a thread into a monitor's wait set. The monitor lock must be
608 * held by the caller of this routine.
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800609 */
610static void waitSetAppend(Monitor *mon, Thread *thread)
611{
612 Thread *elt;
613
614 assert(mon != NULL);
Carl Shapiro30aa9972010-01-13 22:07:50 -0800615 assert(mon->owner == dvmThreadSelf());
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800616 assert(thread != NULL);
617 assert(thread->waitNext == NULL);
618 assert(waitSetCheck(mon) == 0);
619 if (mon->waitSet == NULL) {
620 mon->waitSet = thread;
621 return;
622 }
623 elt = mon->waitSet;
624 while (elt->waitNext != NULL) {
625 elt = elt->waitNext;
626 }
627 elt->waitNext = thread;
628}
629
630/*
Carl Shapiro30aa9972010-01-13 22:07:50 -0800631 * Unlinks a thread from a monitor's wait set. The monitor lock must
632 * be held by the caller of this routine.
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800633 */
634static void waitSetRemove(Monitor *mon, Thread *thread)
635{
636 Thread *elt;
637
638 assert(mon != NULL);
Carl Shapiro30aa9972010-01-13 22:07:50 -0800639 assert(mon->owner == dvmThreadSelf());
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800640 assert(thread != NULL);
641 assert(waitSetCheck(mon) == 0);
642 if (mon->waitSet == NULL) {
643 return;
644 }
645 if (mon->waitSet == thread) {
646 mon->waitSet = thread->waitNext;
647 thread->waitNext = NULL;
648 return;
649 }
650 elt = mon->waitSet;
651 while (elt->waitNext != NULL) {
652 if (elt->waitNext == thread) {
653 elt->waitNext = thread->waitNext;
654 thread->waitNext = NULL;
655 return;
656 }
657 elt = elt->waitNext;
658 }
659}
660
Carl Shapirob4539192010-01-04 16:50:00 -0800661/*
662 * Converts the given relative waiting time into an absolute time.
663 */
Andy McFadden953a0ed2010-09-17 15:48:38 -0700664static void absoluteTime(s8 msec, s4 nsec, struct timespec *ts)
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800665{
666 s8 endSec;
667
668#ifdef HAVE_TIMEDWAIT_MONOTONIC
669 clock_gettime(CLOCK_MONOTONIC, ts);
670#else
671 {
672 struct timeval tv;
673 gettimeofday(&tv, NULL);
674 ts->tv_sec = tv.tv_sec;
675 ts->tv_nsec = tv.tv_usec * 1000;
676 }
677#endif
678 endSec = ts->tv_sec + msec / 1000;
679 if (endSec >= 0x7fffffff) {
680 LOGV("NOTE: end time exceeds epoch\n");
681 endSec = 0x7ffffffe;
682 }
683 ts->tv_sec = endSec;
684 ts->tv_nsec = (ts->tv_nsec + (msec % 1000) * 1000000) + nsec;
685
686 /* catch rollover */
687 if (ts->tv_nsec >= 1000000000L) {
688 ts->tv_sec++;
689 ts->tv_nsec -= 1000000000L;
690 }
691}
692
Bill Buzbeefccb31d2010-02-04 16:09:55 -0800693int dvmRelativeCondWait(pthread_cond_t* cond, pthread_mutex_t* mutex,
694 s8 msec, s4 nsec)
695{
696 int ret;
697 struct timespec ts;
698 absoluteTime(msec, nsec, &ts);
699#if defined(HAVE_TIMEDWAIT_MONOTONIC)
700 ret = pthread_cond_timedwait_monotonic(cond, mutex, &ts);
701#else
702 ret = pthread_cond_timedwait(cond, mutex, &ts);
703#endif
704 assert(ret == 0 || ret == ETIMEDOUT);
705 return ret;
706}
707
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800708/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800709 * Wait on a monitor until timeout, interrupt, or notification. Used for
710 * Object.wait() and (somewhat indirectly) Thread.sleep() and Thread.join().
711 *
712 * If another thread calls Thread.interrupt(), we throw InterruptedException
713 * and return immediately if one of the following are true:
714 * - blocked in wait(), wait(long), or wait(long, int) methods of Object
715 * - blocked in join(), join(long), or join(long, int) methods of Thread
716 * - blocked in sleep(long), or sleep(long, int) methods of Thread
717 * Otherwise, we set the "interrupted" flag.
718 *
719 * Checks to make sure that "nsec" is in the range 0-999999
720 * (i.e. fractions of a millisecond) and throws the appropriate
721 * exception if it isn't.
722 *
723 * The spec allows "spurious wakeups", and recommends that all code using
724 * Object.wait() do so in a loop. This appears to derive from concerns
725 * about pthread_cond_wait() on multiprocessor systems. Some commentary
726 * on the web casts doubt on whether these can/should occur.
727 *
728 * Since we're allowed to wake up "early", we clamp extremely long durations
729 * to return at the end of the 32-bit time epoch.
730 */
731static void waitMonitor(Thread* self, Monitor* mon, s8 msec, s4 nsec,
732 bool interruptShouldThrow)
733{
734 struct timespec ts;
735 bool wasInterrupted = false;
736 bool timed;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800737 int ret;
Carl Shapirofa903b32010-08-31 15:11:46 -0700738 char *savedFileName;
739 u4 savedLineNumber;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800740
Carl Shapiro71938022009-12-22 13:49:53 -0800741 assert(self != NULL);
742 assert(mon != NULL);
743
Carl Shapiro94338aa2009-12-21 11:42:59 -0800744 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800745 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800746 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
747 "object not locked by thread before wait()");
748 return;
749 }
750
751 /*
752 * Enforce the timeout range.
753 */
754 if (msec < 0 || nsec < 0 || nsec > 999999) {
755 dvmThrowException("Ljava/lang/IllegalArgumentException;",
756 "timeout arguments out of range");
757 return;
758 }
759
760 /*
761 * Compute absolute wakeup time, if necessary.
762 */
763 if (msec == 0 && nsec == 0) {
764 timed = false;
765 } else {
Bill Buzbeefccb31d2010-02-04 16:09:55 -0800766 absoluteTime(msec, nsec, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800767 timed = true;
768 }
769
770 /*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800771 * Add ourselves to the set of threads waiting on this monitor, and
772 * release our hold. We need to let it go even if we're a few levels
773 * deep in a recursive lock, and we need to restore that later.
774 *
Carl Shapiro142ef272010-01-25 12:51:31 -0800775 * We append to the wait set ahead of clearing the count and owner
776 * fields so the subroutine can check that the calling thread owns
777 * the monitor. Aside from that, the order of member updates is
778 * not order sensitive as we hold the pthread mutex.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800779 */
Carl Shapiro142ef272010-01-25 12:51:31 -0800780 waitSetAppend(mon, self);
781 int prevLockCount = mon->lockCount;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800782 mon->lockCount = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800783 mon->owner = NULL;
Carl Shapirofa903b32010-08-31 15:11:46 -0700784 savedFileName = mon->ownerFileName;
785 mon->ownerFileName = NULL;
786 savedLineNumber = mon->ownerLineNumber;
787 mon->ownerLineNumber = 0;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800788
789 /*
790 * Update thread status. If the GC wakes up, it'll ignore us, knowing
791 * that we won't touch any references in this state, and we'll check
792 * our suspend mode before we transition out.
793 */
794 if (timed)
795 dvmChangeStatus(self, THREAD_TIMED_WAIT);
796 else
797 dvmChangeStatus(self, THREAD_WAIT);
798
Carl Shapiro980ffb02010-03-13 22:34:01 -0800799 dvmLockMutex(&self->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800800
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800801 /*
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800802 * Set waitMonitor to the monitor object we will be waiting on.
803 * When waitMonitor is non-NULL a notifying or interrupting thread
804 * must signal the thread's waitCond to wake it up.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800805 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800806 assert(self->waitMonitor == NULL);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800807 self->waitMonitor = mon;
808
809 /*
810 * Handle the case where the thread was interrupted before we called
811 * wait().
812 */
813 if (self->interrupted) {
814 wasInterrupted = true;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800815 self->waitMonitor = NULL;
Carl Shapiro980ffb02010-03-13 22:34:01 -0800816 dvmUnlockMutex(&self->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800817 goto done;
818 }
819
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800820 /*
821 * Release the monitor lock and wait for a notification or
822 * a timeout to occur.
823 */
Carl Shapiro980ffb02010-03-13 22:34:01 -0800824 dvmUnlockMutex(&mon->lock);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800825
826 if (!timed) {
827 ret = pthread_cond_wait(&self->waitCond, &self->waitMutex);
828 assert(ret == 0);
829 } else {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800830#ifdef HAVE_TIMEDWAIT_MONOTONIC
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800831 ret = pthread_cond_timedwait_monotonic(&self->waitCond, &self->waitMutex, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800832#else
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800833 ret = pthread_cond_timedwait(&self->waitCond, &self->waitMutex, &ts);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800834#endif
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800835 assert(ret == 0 || ret == ETIMEDOUT);
836 }
837 if (self->interrupted) {
838 wasInterrupted = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800839 }
840
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800841 self->interrupted = false;
842 self->waitMonitor = NULL;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800843
Carl Shapiro980ffb02010-03-13 22:34:01 -0800844 dvmUnlockMutex(&self->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800845
Carl Shapiro30aa9972010-01-13 22:07:50 -0800846 /* Reacquire the monitor lock. */
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800847 lockMonitor(self, mon);
848
Carl Shapiro142ef272010-01-25 12:51:31 -0800849done:
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800850 /*
Carl Shapiro07b35922010-01-25 14:48:30 -0800851 * We remove our thread from wait set after restoring the count
852 * and owner fields so the subroutine can check that the calling
853 * thread owns the monitor. Aside from that, the order of member
854 * updates is not order sensitive as we hold the pthread mutex.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800855 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800856 mon->owner = self;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800857 mon->lockCount = prevLockCount;
Carl Shapirofa903b32010-08-31 15:11:46 -0700858 mon->ownerFileName = savedFileName;
859 mon->ownerLineNumber = savedLineNumber;
Carl Shapiro07b35922010-01-25 14:48:30 -0800860 waitSetRemove(mon, self);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800861
862 /* set self->status back to THREAD_RUNNING, and self-suspend if needed */
863 dvmChangeStatus(self, THREAD_RUNNING);
864
865 if (wasInterrupted) {
866 /*
867 * We were interrupted while waiting, or somebody interrupted an
Carl Shapiro30aa9972010-01-13 22:07:50 -0800868 * un-interruptible thread earlier and we're bailing out immediately.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800869 *
870 * The doc sayeth: "The interrupted status of the current thread is
871 * cleared when this exception is thrown."
872 */
873 self->interrupted = false;
874 if (interruptShouldThrow)
875 dvmThrowException("Ljava/lang/InterruptedException;", NULL);
876 }
877}
878
879/*
880 * Notify one thread waiting on this monitor.
881 */
882static void notifyMonitor(Thread* self, Monitor* mon)
883{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800884 Thread* thread;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800885
Carl Shapiro71938022009-12-22 13:49:53 -0800886 assert(self != NULL);
887 assert(mon != NULL);
888
Carl Shapiro94338aa2009-12-21 11:42:59 -0800889 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800890 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800891 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
892 "object not locked by thread before notify()");
893 return;
894 }
Carl Shapiro30aa9972010-01-13 22:07:50 -0800895 /* Signal the first waiting thread in the wait set. */
896 while (mon->waitSet != NULL) {
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800897 thread = mon->waitSet;
898 mon->waitSet = thread->waitNext;
899 thread->waitNext = NULL;
Carl Shapiro980ffb02010-03-13 22:34:01 -0800900 dvmLockMutex(&thread->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800901 /* Check to see if the thread is still waiting. */
902 if (thread->waitMonitor != NULL) {
903 pthread_cond_signal(&thread->waitCond);
Carl Shapiro980ffb02010-03-13 22:34:01 -0800904 dvmUnlockMutex(&thread->waitMutex);
Carl Shapiro30aa9972010-01-13 22:07:50 -0800905 return;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800906 }
Carl Shapiro980ffb02010-03-13 22:34:01 -0800907 dvmUnlockMutex(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800908 }
909}
910
911/*
912 * Notify all threads waiting on this monitor.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800913 */
914static void notifyAllMonitor(Thread* self, Monitor* mon)
915{
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800916 Thread* thread;
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800917
Carl Shapiro71938022009-12-22 13:49:53 -0800918 assert(self != NULL);
919 assert(mon != NULL);
920
Carl Shapiro94338aa2009-12-21 11:42:59 -0800921 /* Make sure that we hold the lock. */
Carl Shapiro71938022009-12-22 13:49:53 -0800922 if (mon->owner != self) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800923 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
924 "object not locked by thread before notifyAll()");
925 return;
926 }
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800927 /* Signal all threads in the wait set. */
928 while (mon->waitSet != NULL) {
929 thread = mon->waitSet;
930 mon->waitSet = thread->waitNext;
931 thread->waitNext = NULL;
Carl Shapiro980ffb02010-03-13 22:34:01 -0800932 dvmLockMutex(&thread->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -0800933 /* Check to see if the thread is still waiting. */
934 if (thread->waitMonitor != NULL) {
935 pthread_cond_signal(&thread->waitCond);
936 }
Carl Shapiro980ffb02010-03-13 22:34:01 -0800937 dvmUnlockMutex(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800938 }
939}
940
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800941/*
Carl Shapiro66bb7df2010-03-12 15:25:37 -0800942 * Changes the shape of a monitor from thin to fat, preserving the
943 * internal lock state. The calling thread must own the lock.
944 */
945static void inflateMonitor(Thread *self, Object *obj)
946{
947 Monitor *mon;
948 u4 thin;
949
950 assert(self != NULL);
951 assert(obj != NULL);
952 assert(LW_SHAPE(obj->lock) == LW_SHAPE_THIN);
953 assert(LW_LOCK_OWNER(obj->lock) == self->threadId);
954 /* Allocate and acquire a new monitor. */
955 mon = dvmCreateMonitor(obj);
956 lockMonitor(self, mon);
957 /* Propagate the lock state. */
958 thin = obj->lock;
959 mon->lockCount = LW_LOCK_COUNT(thin);
960 thin &= LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT;
961 thin |= (u4)mon | LW_SHAPE_FAT;
962 /* Publish the updated lock word. */
Carl Shapiro4ba56722010-06-21 11:04:33 -0700963 android_atomic_release_store(thin, (int32_t *)&obj->lock);
Carl Shapiro66bb7df2010-03-12 15:25:37 -0800964}
965
966/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800967 * Implements monitorenter for "synchronized" stuff.
968 *
969 * This does not fail or throw an exception (unless deadlock prediction
970 * is enabled and set to "err" mode).
971 */
972void dvmLockObject(Thread* self, Object *obj)
973{
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800974 volatile u4 *thinp;
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800975 ThreadStatus oldStatus;
976 useconds_t sleepDelay;
977 const useconds_t maxSleepDelay = 1 << 20;
978 u4 thin, newThin, threadId;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800979
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800980 assert(self != NULL);
981 assert(obj != NULL);
982 threadId = self->threadId;
983 thinp = &obj->lock;
984retry:
985 thin = *thinp;
986 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
987 /*
988 * The lock is a thin lock. The owner field is used to
989 * determine the acquire method, ordered by cost.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800990 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800991 if (LW_LOCK_OWNER(thin) == threadId) {
992 /*
993 * The calling thread owns the lock. Increment the
994 * value of the recursion count field.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800995 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -0800996 obj->lock += 1 << LW_LOCK_COUNT_SHIFT;
Carl Shapirof3cfbbf2010-07-23 16:30:12 -0700997 if (LW_LOCK_COUNT(obj->lock) == LW_LOCK_COUNT_MASK) {
998 /*
999 * The reacquisition limit has been reached. Inflate
1000 * the lock so the next acquire will not overflow the
1001 * recursion count field.
1002 */
1003 inflateMonitor(self, obj);
1004 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001005 } else if (LW_LOCK_OWNER(thin) == 0) {
1006 /*
1007 * The lock is unowned. Install the thread id of the
1008 * calling thread into the owner field. This is the
1009 * common case. In performance critical code the JIT
1010 * will have tried this before calling out to the VM.
1011 */
1012 newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
Carl Shapiro3ba10c92010-09-02 16:43:16 -07001013 if (android_atomic_acquire_cas(thin, newThin,
Andy McFadden6e10b9a2010-06-14 15:24:39 -07001014 (int32_t*)thinp) != 0) {
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001015 /*
1016 * The acquire failed. Try again.
1017 */
1018 goto retry;
1019 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001020 } else {
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001021 LOG_THIN("(%d) spin on lock %p: %#x (%#x) %#x",
1022 threadId, &obj->lock, 0, *thinp, thin);
1023 /*
1024 * The lock is owned by another thread. Notify the VM
1025 * that we are about to wait.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001026 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001027 oldStatus = dvmChangeStatus(self, THREAD_MONITOR);
1028 /*
1029 * Spin until the thin lock is released or inflated.
1030 */
1031 sleepDelay = 0;
1032 for (;;) {
1033 thin = *thinp;
1034 /*
1035 * Check the shape of the lock word. Another thread
1036 * may have inflated the lock while we were waiting.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001037 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001038 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1039 if (LW_LOCK_OWNER(thin) == 0) {
1040 /*
1041 * The lock has been released. Install the
1042 * thread id of the calling thread into the
1043 * owner field.
1044 */
1045 newThin = thin | (threadId << LW_LOCK_OWNER_SHIFT);
Carl Shapiro3ba10c92010-09-02 16:43:16 -07001046 if (android_atomic_acquire_cas(thin, newThin,
Andy McFadden6e10b9a2010-06-14 15:24:39 -07001047 (int32_t *)thinp) == 0) {
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001048 /*
1049 * The acquire succeed. Break out of the
1050 * loop and proceed to inflate the lock.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001051 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001052 break;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001053 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001054 } else {
1055 /*
1056 * The lock has not been released. Yield so
1057 * the owning thread can run.
1058 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001059 if (sleepDelay == 0) {
1060 sched_yield();
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001061 sleepDelay = 1000;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001062 } else {
1063 usleep(sleepDelay);
1064 if (sleepDelay < maxSleepDelay / 2) {
1065 sleepDelay *= 2;
1066 }
1067 }
1068 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001069 } else {
1070 /*
1071 * The thin lock was inflated by another thread.
1072 * Let the VM know we are no longer waiting and
1073 * try again.
1074 */
1075 LOG_THIN("(%d) lock %p surprise-fattened",
1076 threadId, &obj->lock);
1077 dvmChangeStatus(self, oldStatus);
1078 goto retry;
1079 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001080 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001081 LOG_THIN("(%d) spin on lock done %p: %#x (%#x) %#x",
1082 threadId, &obj->lock, 0, *thinp, thin);
1083 /*
1084 * We have acquired the thin lock. Let the VM know that
1085 * we are no longer waiting.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001086 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001087 dvmChangeStatus(self, oldStatus);
1088 /*
1089 * Fatten the lock.
1090 */
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001091 inflateMonitor(self, obj);
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001092 LOG_THIN("(%d) lock %p fattened", threadId, &obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001093 }
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001094 } else {
1095 /*
1096 * The lock is a fat lock.
1097 */
1098 assert(LW_MONITOR(obj->lock) != NULL);
1099 lockMonitor(self, LW_MONITOR(obj->lock));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001100 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001101#ifdef WITH_DEADLOCK_PREDICTION
1102 /*
1103 * See if we were allowed to grab the lock at this time. We do it
1104 * *after* acquiring the lock, rather than before, so that we can
1105 * freely update the Monitor struct. This seems counter-intuitive,
1106 * but our goal is deadlock *prediction* not deadlock *prevention*.
1107 * (If we actually deadlock, the situation is easy to diagnose from
1108 * a thread dump, so there's no point making a special effort to do
1109 * the checks before the lock is held.)
1110 *
1111 * This needs to happen before we add the object to the thread's
1112 * monitor list, so we can tell the difference between first-lock and
1113 * re-lock.
1114 *
1115 * It's also important that we do this while in THREAD_RUNNING, so
1116 * that we don't interfere with cleanup operations in the GC.
1117 */
1118 if (gDvm.deadlockPredictMode != kDPOff) {
1119 if (self->status != THREAD_RUNNING) {
1120 LOGE("Bad thread status (%d) in DP\n", self->status);
1121 dvmDumpThread(self, false);
1122 dvmAbort();
1123 }
1124 assert(!dvmCheckException(self));
1125 updateDeadlockPrediction(self, obj);
1126 if (dvmCheckException(self)) {
1127 /*
1128 * If we're throwing an exception here, we need to free the
1129 * lock. We add the object to the thread's monitor list so the
1130 * "unlock" code can remove it.
1131 */
1132 dvmAddToMonitorList(self, obj, false);
1133 dvmUnlockObject(self, obj);
1134 LOGV("--- unlocked, pending is '%s'\n",
1135 dvmGetException(self)->clazz->descriptor);
1136 }
1137 }
1138
1139 /*
1140 * Add the locked object, and the current stack trace, to the list
1141 * held by the Thread object. If deadlock prediction isn't on,
1142 * don't capture the stack trace.
1143 */
1144 dvmAddToMonitorList(self, obj, gDvm.deadlockPredictMode != kDPOff);
1145#elif defined(WITH_MONITOR_TRACKING)
1146 /*
1147 * Add the locked object to the list held by the Thread object.
1148 */
1149 dvmAddToMonitorList(self, obj, false);
1150#endif
1151}
1152
1153/*
1154 * Implements monitorexit for "synchronized" stuff.
1155 *
1156 * On failure, throws an exception and returns "false".
1157 */
1158bool dvmUnlockObject(Thread* self, Object *obj)
1159{
Carl Shapiro94338aa2009-12-21 11:42:59 -08001160 u4 thin;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001161
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001162 assert(self != NULL);
1163 assert(self->status == THREAD_RUNNING);
1164 assert(obj != NULL);
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001165 /*
1166 * Cache the lock word as its value can change while we are
1167 * examining its state.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001168 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001169 thin = obj->lock;
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001170 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
1171 /*
1172 * The lock is thin. We must ensure that the lock is owned
1173 * by the given thread before unlocking it.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001174 */
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001175 if (LW_LOCK_OWNER(thin) == self->threadId) {
1176 /*
1177 * We are the lock owner. It is safe to update the lock
1178 * without CAS as lock ownership guards the lock itself.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001179 */
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001180 if (LW_LOCK_COUNT(thin) == 0) {
1181 /*
1182 * The lock was not recursively acquired, the common
1183 * case. Unlock by clearing all bits except for the
1184 * hash state.
1185 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001186 obj->lock &= (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT);
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001187 } else {
1188 /*
1189 * The object was recursively acquired. Decrement the
1190 * lock recursion count field.
1191 */
Carl Shapiro147dd3f2010-03-08 14:38:42 -08001192 obj->lock -= 1 << LW_LOCK_COUNT_SHIFT;
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001193 }
1194 } else {
1195 /*
1196 * We do not own the lock. The JVM spec requires that we
1197 * throw an exception in this case.
1198 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001199 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001200 "unlock of unowned monitor");
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001201 return false;
1202 }
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001203 } else {
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001204 /*
1205 * The lock is fat. We must check to see if unlockMonitor has
1206 * raised any exceptions before continuing.
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001207 */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001208 assert(LW_MONITOR(obj->lock) != NULL);
1209 if (!unlockMonitor(self, LW_MONITOR(obj->lock))) {
Carl Shapiroef5b4d32010-01-26 13:22:04 -08001210 /*
1211 * An exception has been raised. Do not fall through.
1212 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001213 return false;
1214 }
1215 }
1216
1217#ifdef WITH_MONITOR_TRACKING
1218 /*
1219 * Remove the object from the Thread's list.
1220 */
1221 dvmRemoveFromMonitorList(self, obj);
1222#endif
1223
1224 return true;
1225}
1226
1227/*
1228 * Object.wait(). Also called for class init.
1229 */
1230void dvmObjectWait(Thread* self, Object *obj, s8 msec, s4 nsec,
1231 bool interruptShouldThrow)
1232{
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001233 Monitor* mon;
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001234 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001235
1236 /* If the lock is still thin, we need to fatten it.
1237 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001238 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001239 /* Make sure that 'self' holds the lock.
1240 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001241 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001242 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1243 "object not locked by thread before wait()");
1244 return;
1245 }
1246
1247 /* This thread holds the lock. We need to fatten the lock
1248 * so 'self' can block on it. Don't update the object lock
1249 * field yet, because 'self' needs to acquire the lock before
1250 * any other thread gets a chance.
1251 */
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001252 inflateMonitor(self, obj);
Patrick Scott2446f442010-10-21 14:50:15 -04001253 LOG_THIN("(%d) lock %p fattened by wait()", self->threadId, &obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001254 }
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001255 mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001256 waitMonitor(self, mon, msec, nsec, interruptShouldThrow);
1257}
1258
1259/*
1260 * Object.notify().
1261 */
1262void dvmObjectNotify(Thread* self, Object *obj)
1263{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001264 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001265
1266 /* If the lock is still thin, there aren't any waiters;
1267 * waiting on an object forces lock fattening.
1268 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001269 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001270 /* Make sure that 'self' holds the lock.
1271 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001272 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001273 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1274 "object not locked by thread before notify()");
1275 return;
1276 }
1277
1278 /* no-op; there are no waiters to notify.
1279 */
1280 } else {
1281 /* It's a fat lock.
1282 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001283 notifyMonitor(self, LW_MONITOR(thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001284 }
1285}
1286
1287/*
1288 * Object.notifyAll().
1289 */
1290void dvmObjectNotifyAll(Thread* self, Object *obj)
1291{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001292 u4 thin = obj->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001293
1294 /* If the lock is still thin, there aren't any waiters;
1295 * waiting on an object forces lock fattening.
1296 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001297 if (LW_SHAPE(thin) == LW_SHAPE_THIN) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001298 /* Make sure that 'self' holds the lock.
1299 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001300 if (LW_LOCK_OWNER(thin) != self->threadId) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001301 dvmThrowException("Ljava/lang/IllegalMonitorStateException;",
1302 "object not locked by thread before notifyAll()");
1303 return;
1304 }
1305
1306 /* no-op; there are no waiters to notify.
1307 */
1308 } else {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001309 /* It's a fat lock.
1310 */
Carl Shapiro94338aa2009-12-21 11:42:59 -08001311 notifyAllMonitor(self, LW_MONITOR(thin));
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001312 }
1313}
1314
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001315/*
1316 * This implements java.lang.Thread.sleep(long msec, int nsec).
1317 *
1318 * The sleep is interruptible by other threads, which means we can't just
1319 * plop into an OS sleep call. (We probably could if we wanted to send
1320 * signals around and rely on EINTR, but that's inefficient and relies
1321 * on native code respecting our signal mask.)
1322 *
1323 * We have to do all of this stuff for Object.wait() as well, so it's
1324 * easiest to just sleep on a private Monitor.
1325 *
1326 * It appears that we want sleep(0,0) to go through the motions of sleeping
1327 * for a very short duration, rather than just returning.
1328 */
1329void dvmThreadSleep(u8 msec, u4 nsec)
1330{
1331 Thread* self = dvmThreadSelf();
1332 Monitor* mon = gDvm.threadSleepMon;
1333
1334 /* sleep(0,0) wakes up immediately, wait(0,0) means wait forever; adjust */
1335 if (msec == 0 && nsec == 0)
1336 nsec++;
1337
1338 lockMonitor(self, mon);
1339 waitMonitor(self, mon, msec, nsec, true);
1340 unlockMonitor(self, mon);
1341}
1342
1343/*
1344 * Implement java.lang.Thread.interrupt().
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001345 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001346void dvmThreadInterrupt(Thread* thread)
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001347{
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001348 assert(thread != NULL);
1349
Carl Shapiro980ffb02010-03-13 22:34:01 -08001350 dvmLockMutex(&thread->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001351
1352 /*
1353 * If the interrupted flag is already set no additional action is
1354 * required.
1355 */
1356 if (thread->interrupted == true) {
Carl Shapiro980ffb02010-03-13 22:34:01 -08001357 dvmUnlockMutex(&thread->waitMutex);
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001358 return;
1359 }
1360
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001361 /*
1362 * Raise the "interrupted" flag. This will cause it to bail early out
1363 * of the next wait() attempt, if it's not currently waiting on
1364 * something.
1365 */
1366 thread->interrupted = true;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001367
1368 /*
1369 * Is the thread waiting?
1370 *
1371 * Note that fat vs. thin doesn't matter here; waitMonitor
1372 * is only set when a thread actually waits on a monitor,
1373 * which implies that the monitor has already been fattened.
1374 */
Carl Shapiro77f52eb2009-12-24 19:56:53 -08001375 if (thread->waitMonitor != NULL) {
1376 pthread_cond_signal(&thread->waitCond);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001377 }
1378
Carl Shapiro980ffb02010-03-13 22:34:01 -08001379 dvmUnlockMutex(&thread->waitMutex);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001380}
1381
Carl Shapiro30aa9972010-01-13 22:07:50 -08001382#ifndef WITH_COPYING_GC
Carl Shapiro94338aa2009-12-21 11:42:59 -08001383u4 dvmIdentityHashCode(Object *obj)
1384{
1385 return (u4)obj;
1386}
Carl Shapiro30aa9972010-01-13 22:07:50 -08001387#else
Carl Shapiro30aa9972010-01-13 22:07:50 -08001388/*
1389 * Returns the identity hash code of the given object.
1390 */
1391u4 dvmIdentityHashCode(Object *obj)
1392{
1393 Thread *self, *thread;
1394 volatile u4 *lw;
Carl Shapirobfe4dcc2010-04-16 17:55:27 -07001395 size_t size;
Carl Shapiro30aa9972010-01-13 22:07:50 -08001396 u4 lock, owner, hashState;
1397
1398 if (obj == NULL) {
1399 /*
1400 * Null is defined to have an identity hash code of 0.
1401 */
1402 return 0;
1403 }
1404 lw = &obj->lock;
1405retry:
1406 hashState = LW_HASH_STATE(*lw);
1407 if (hashState == LW_HASH_STATE_HASHED) {
1408 /*
1409 * The object has been hashed but has not had its hash code
1410 * relocated by the garbage collector. Use the raw object
1411 * address.
1412 */
1413 return (u4)obj >> 3;
1414 } else if (hashState == LW_HASH_STATE_HASHED_AND_MOVED) {
1415 /*
1416 * The object has been hashed and its hash code has been
1417 * relocated by the collector. Use the value of the naturally
1418 * aligned word following the instance data.
1419 */
Carl Shapiroc48b6d02010-05-04 11:19:53 -07001420 assert(obj->clazz != gDvm.classJavaLangClass);
Carl Shapiro30aa9972010-01-13 22:07:50 -08001421 if (IS_CLASS_FLAG_SET(obj->clazz, CLASS_ISARRAY)) {
Carl Shapirobfe4dcc2010-04-16 17:55:27 -07001422 size = dvmArrayObjectSize((ArrayObject *)obj);
Carl Shapiroc48b6d02010-05-04 11:19:53 -07001423 size = (size + 2) & ~2;
Carl Shapiro30aa9972010-01-13 22:07:50 -08001424 } else {
Carl Shapirobfe4dcc2010-04-16 17:55:27 -07001425 size = obj->clazz->objectSize;
Carl Shapiro30aa9972010-01-13 22:07:50 -08001426 }
Carl Shapirobfe4dcc2010-04-16 17:55:27 -07001427 return *(u4 *)(((char *)obj) + size);
Carl Shapiro30aa9972010-01-13 22:07:50 -08001428 } else if (hashState == LW_HASH_STATE_UNHASHED) {
1429 /*
1430 * The object has never been hashed. Change the hash state to
1431 * hashed and use the raw object address.
1432 */
1433 self = dvmThreadSelf();
1434 if (self->threadId == lockOwner(obj)) {
1435 /*
1436 * We already own the lock so we can update the hash state
1437 * directly.
1438 */
1439 *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
1440 return (u4)obj >> 3;
1441 }
1442 /*
1443 * We do not own the lock. Try acquiring the lock. Should
1444 * this fail, we must suspend the owning thread.
1445 */
1446 if (LW_SHAPE(*lw) == LW_SHAPE_THIN) {
1447 /*
1448 * If the lock is thin assume it is unowned. We simulate
1449 * an acquire, update, and release with a single CAS.
1450 */
1451 lock = DVM_LOCK_INITIAL_THIN_VALUE;
1452 lock |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
Carl Shapiro3ba10c92010-09-02 16:43:16 -07001453 if (android_atomic_acquire_cas(
Carl Shapiro30aa9972010-01-13 22:07:50 -08001454 (int32_t)DVM_LOCK_INITIAL_THIN_VALUE,
Andy McFadden6e10b9a2010-06-14 15:24:39 -07001455 (int32_t)lock,
1456 (int32_t *)lw) == 0) {
Carl Shapiro30aa9972010-01-13 22:07:50 -08001457 /*
1458 * A new lockword has been installed with a hash state
1459 * of hashed. Use the raw object address.
1460 */
1461 return (u4)obj >> 3;
1462 }
1463 } else {
1464 if (tryLockMonitor(self, LW_MONITOR(*lw))) {
1465 /*
1466 * The monitor lock has been acquired. Change the
1467 * hash state to hashed and use the raw object
1468 * address.
1469 */
1470 *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
1471 unlockMonitor(self, LW_MONITOR(*lw));
1472 return (u4)obj >> 3;
1473 }
1474 }
1475 /*
1476 * At this point we have failed to acquire the lock. We must
1477 * identify the owning thread and suspend it.
1478 */
1479 dvmLockThreadList(self);
1480 /*
1481 * Cache the lock word as its value can change between
1482 * determining its shape and retrieving its owner.
1483 */
1484 lock = *lw;
1485 if (LW_SHAPE(lock) == LW_SHAPE_THIN) {
1486 /*
1487 * Find the thread with the corresponding thread id.
1488 */
1489 owner = LW_LOCK_OWNER(lock);
1490 assert(owner != self->threadId);
1491 /*
1492 * If the lock has no owner do not bother scanning the
1493 * thread list and fall through to the failure handler.
1494 */
1495 thread = owner ? gDvm.threadList : NULL;
1496 while (thread != NULL) {
1497 if (thread->threadId == owner) {
1498 break;
1499 }
1500 thread = thread->next;
1501 }
1502 } else {
1503 thread = LW_MONITOR(lock)->owner;
1504 }
1505 /*
1506 * If thread is NULL the object has been released since the
1507 * thread list lock was acquired. Try again.
1508 */
1509 if (thread == NULL) {
1510 dvmUnlockThreadList();
1511 goto retry;
1512 }
1513 /*
1514 * Wait for the owning thread to suspend.
1515 */
1516 dvmSuspendThread(thread);
1517 if (dvmHoldsLock(thread, obj)) {
1518 /*
1519 * The owning thread has been suspended. We can safely
1520 * change the hash state to hashed.
1521 */
1522 *lw |= (LW_HASH_STATE_HASHED << LW_HASH_STATE_SHIFT);
1523 dvmResumeThread(thread);
1524 dvmUnlockThreadList();
1525 return (u4)obj >> 3;
1526 }
1527 /*
1528 * The wrong thread has been suspended. Try again.
1529 */
1530 dvmResumeThread(thread);
1531 dvmUnlockThreadList();
1532 goto retry;
1533 }
1534 LOGE("object %p has an unknown hash state %#x", obj, hashState);
1535 dvmDumpThread(dvmThreadSelf(), false);
1536 dvmAbort();
1537 return 0; /* Quiet the compiler. */
1538}
1539#endif /* WITH_COPYING_GC */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001540
1541#ifdef WITH_DEADLOCK_PREDICTION
1542/*
1543 * ===========================================================================
1544 * Deadlock prediction
1545 * ===========================================================================
1546 */
1547/*
1548The idea is to predict the possibility of deadlock by recording the order
1549in which monitors are acquired. If we see an attempt to acquire a lock
1550out of order, we can identify the locks and offending code.
1551
1552To make this work, we need to keep track of the locks held by each thread,
1553and create history trees for each lock. When a thread tries to acquire
1554a new lock, we walk through the "history children" of the lock, looking
1555for a match with locks the thread already holds. If we find a match,
1556it means the thread has made a request that could result in a deadlock.
1557
1558To support recursive locks, we always allow re-locking a currently-held
1559lock, and maintain a recursion depth count.
1560
1561An ASCII-art example, where letters represent Objects:
1562
1563 A
1564 /|\
1565 / | \
1566 B | D
1567 \ |
1568 \|
1569 C
1570
1571The above is the tree we'd have after handling Object synchronization
1572sequences "ABC", "AC", "AD". A has three children, {B, C, D}. C is also
1573a child of B. (The lines represent pointers between parent and child.
1574Every node can have multiple parents and multiple children.)
1575
1576If we hold AC, and want to lock B, we recursively search through B's
1577children to see if A or C appears. It does, so we reject the attempt.
1578(A straightforward way to implement it: add a link from C to B, then
1579determine whether the graph starting at B contains a cycle.)
1580
1581If we hold AC and want to lock D, we would succeed, creating a new link
1582from C to D.
1583
1584The lock history and a stack trace is attached to the Object's Monitor
1585struct, which means we need to fatten every Object we lock (thin locking
1586is effectively disabled). If we don't need the stack trace we can
1587avoid fattening the leaf nodes, only fattening objects that need to hold
1588history trees.
1589
1590Updates to Monitor structs are only allowed for the thread that holds
1591the Monitor, so we actually do most of our deadlock prediction work after
1592the lock has been acquired.
1593
1594When an object with a monitor is GCed, we need to remove it from the
1595history trees. There are two basic approaches:
1596 (1) For through the entire set of known monitors, search all child
1597 lists for the object in question. This is rather slow, resulting
1598 in GC passes that take upwards of 10 seconds to complete.
1599 (2) Maintain "parent" pointers in each node. Remove the entries as
1600 required. This requires additional storage and maintenance for
1601 every operation, but is significantly faster at GC time.
1602For each GCed object, we merge all of the object's children into each of
1603the object's parents.
1604*/
1605
1606#if !defined(WITH_MONITOR_TRACKING)
1607# error "WITH_DEADLOCK_PREDICTION requires WITH_MONITOR_TRACKING"
1608#endif
1609
1610/*
1611 * Clear out the contents of an ExpandingObjectList, freeing any
1612 * dynamic allocations.
1613 */
1614static void expandObjClear(ExpandingObjectList* pList)
1615{
1616 if (pList->list != NULL) {
1617 free(pList->list);
1618 pList->list = NULL;
1619 }
1620 pList->alloc = pList->count = 0;
1621}
1622
1623/*
1624 * Get the number of objects currently stored in the list.
1625 */
1626static inline int expandBufGetCount(const ExpandingObjectList* pList)
1627{
1628 return pList->count;
1629}
1630
1631/*
1632 * Get the Nth entry from the list.
1633 */
1634static inline Object* expandBufGetEntry(const ExpandingObjectList* pList,
1635 int i)
1636{
1637 return pList->list[i];
1638}
1639
1640/*
1641 * Add a new entry to the list.
1642 *
1643 * We don't check for or try to enforce uniqueness. It's expected that
1644 * the higher-level code does this for us.
1645 */
1646static void expandObjAddEntry(ExpandingObjectList* pList, Object* obj)
1647{
1648 if (pList->count == pList->alloc) {
1649 /* time to expand */
1650 Object** newList;
1651
1652 if (pList->alloc == 0)
1653 pList->alloc = 4;
1654 else
1655 pList->alloc *= 2;
1656 LOGVV("expanding %p to %d\n", pList, pList->alloc);
1657 newList = realloc(pList->list, pList->alloc * sizeof(Object*));
1658 if (newList == NULL) {
1659 LOGE("Failed expanding DP object list (alloc=%d)\n", pList->alloc);
1660 dvmAbort();
1661 }
1662 pList->list = newList;
1663 }
1664
1665 pList->list[pList->count++] = obj;
1666}
1667
1668/*
1669 * Returns "true" if the element was successfully removed.
1670 */
1671static bool expandObjRemoveEntry(ExpandingObjectList* pList, Object* obj)
1672{
1673 int i;
1674
1675 for (i = pList->count-1; i >= 0; i--) {
1676 if (pList->list[i] == obj)
1677 break;
1678 }
1679 if (i < 0)
1680 return false;
1681
1682 if (i != pList->count-1) {
1683 /*
1684 * The order of elements is not important, so we just copy the
1685 * last entry into the new slot.
1686 */
1687 //memmove(&pList->list[i], &pList->list[i+1],
1688 // (pList->count-1 - i) * sizeof(pList->list[0]));
1689 pList->list[i] = pList->list[pList->count-1];
1690 }
1691
1692 pList->count--;
1693 pList->list[pList->count] = (Object*) 0xdecadead;
1694 return true;
1695}
1696
1697/*
1698 * Returns "true" if "obj" appears in the list.
1699 */
1700static bool expandObjHas(const ExpandingObjectList* pList, Object* obj)
1701{
1702 int i;
1703
1704 for (i = 0; i < pList->count; i++) {
1705 if (pList->list[i] == obj)
1706 return true;
1707 }
1708 return false;
1709}
1710
1711/*
1712 * Print the list contents to stdout. For debugging.
1713 */
1714static void expandObjDump(const ExpandingObjectList* pList)
1715{
1716 int i;
1717 for (i = 0; i < pList->count; i++)
1718 printf(" %p", pList->list[i]);
1719}
1720
1721/*
1722 * Check for duplicate entries. Returns the index of the first instance
1723 * of the duplicated value, or -1 if no duplicates were found.
1724 */
1725static int expandObjCheckForDuplicates(const ExpandingObjectList* pList)
1726{
1727 int i, j;
1728 for (i = 0; i < pList->count-1; i++) {
1729 for (j = i + 1; j < pList->count; j++) {
1730 if (pList->list[i] == pList->list[j]) {
1731 return i;
1732 }
1733 }
1734 }
1735
1736 return -1;
1737}
1738
1739
1740/*
1741 * Determine whether "child" appears in the list of objects associated
1742 * with the Monitor in "parent". If "parent" is a thin lock, we return
1743 * false immediately.
1744 */
1745static bool objectInChildList(const Object* parent, Object* child)
1746{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001747 u4 lock = parent->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001748 if (!IS_LOCK_FAT(&lock)) {
1749 //LOGI("on thin\n");
1750 return false;
1751 }
1752
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001753 return expandObjHas(&LW_MONITOR(lock)->historyChildren, child);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001754}
1755
1756/*
1757 * Print the child list.
1758 */
1759static void dumpKids(Object* parent)
1760{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001761 Monitor* mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001762
1763 printf("Children of %p:", parent);
1764 expandObjDump(&mon->historyChildren);
1765 printf("\n");
1766}
1767
1768/*
1769 * Add "child" to the list of children in "parent", and add "parent" to
1770 * the list of parents in "child".
1771 */
1772static void linkParentToChild(Object* parent, Object* child)
1773{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001774 //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for merge
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001775 assert(IS_LOCK_FAT(&parent->lock));
1776 assert(IS_LOCK_FAT(&child->lock));
1777 assert(parent != child);
1778 Monitor* mon;
1779
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001780 mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001781 assert(!expandObjHas(&mon->historyChildren, child));
1782 expandObjAddEntry(&mon->historyChildren, child);
1783
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001784 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001785 assert(!expandObjHas(&mon->historyParents, parent));
1786 expandObjAddEntry(&mon->historyParents, parent);
1787}
1788
1789
1790/*
1791 * Remove "child" from the list of children in "parent".
1792 */
1793static void unlinkParentFromChild(Object* parent, Object* child)
1794{
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001795 //assert(LW_MONITOR(parent->lock)->owner == dvmThreadSelf()); // !owned for GC
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001796 assert(IS_LOCK_FAT(&parent->lock));
1797 assert(IS_LOCK_FAT(&child->lock));
1798 assert(parent != child);
1799 Monitor* mon;
1800
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001801 mon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001802 if (!expandObjRemoveEntry(&mon->historyChildren, child)) {
1803 LOGW("WARNING: child %p not found in parent %p\n", child, parent);
1804 }
1805 assert(!expandObjHas(&mon->historyChildren, child));
1806 assert(expandObjCheckForDuplicates(&mon->historyChildren) < 0);
1807
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001808 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001809 if (!expandObjRemoveEntry(&mon->historyParents, parent)) {
1810 LOGW("WARNING: parent %p not found in child %p\n", parent, child);
1811 }
1812 assert(!expandObjHas(&mon->historyParents, parent));
1813 assert(expandObjCheckForDuplicates(&mon->historyParents) < 0);
1814}
1815
1816
1817/*
1818 * Log the monitors held by the current thread. This is done as part of
1819 * flagging an error.
1820 */
1821static void logHeldMonitors(Thread* self)
1822{
1823 char* name = NULL;
1824
1825 name = dvmGetThreadName(self);
1826 LOGW("Monitors currently held by thread (threadid=%d '%s')\n",
1827 self->threadId, name);
1828 LOGW("(most-recently-acquired on top):\n");
1829 free(name);
1830
1831 LockedObjectData* lod = self->pLockedObjects;
1832 while (lod != NULL) {
1833 LOGW("--- object %p[%d] (%s)\n",
1834 lod->obj, lod->recursionCount, lod->obj->clazz->descriptor);
1835 dvmLogRawStackTrace(lod->rawStackTrace, lod->stackDepth);
1836
1837 lod = lod->next;
1838 }
1839}
1840
1841/*
1842 * Recursively traverse the object hierarchy starting at "obj". We mark
1843 * ourselves on entry and clear the mark on exit. If we ever encounter
1844 * a marked object, we have a cycle.
1845 *
1846 * Returns "true" if all is well, "false" if we found a cycle.
1847 */
1848static bool traverseTree(Thread* self, const Object* obj)
1849{
1850 assert(IS_LOCK_FAT(&obj->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001851 Monitor* mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001852
1853 /*
1854 * Have we been here before?
1855 */
1856 if (mon->historyMark) {
1857 int* rawStackTrace;
1858 int stackDepth;
1859
1860 LOGW("%s\n", kStartBanner);
1861 LOGW("Illegal lock attempt:\n");
1862 LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1863
1864 rawStackTrace = dvmFillInStackTraceRaw(self, &stackDepth);
1865 dvmLogRawStackTrace(rawStackTrace, stackDepth);
1866 free(rawStackTrace);
1867
1868 LOGW(" ");
1869 logHeldMonitors(self);
1870
1871 LOGW(" ");
1872 LOGW("Earlier, the following lock order (from last to first) was\n");
1873 LOGW("established -- stack trace is from first successful lock):\n");
1874 return false;
1875 }
1876 mon->historyMark = true;
1877
1878 /*
1879 * Examine the children. We do NOT hold these locks, so they might
1880 * very well transition from thin to fat or change ownership while
1881 * we work.
1882 *
1883 * NOTE: we rely on the fact that they cannot revert from fat to thin
1884 * while we work. This is currently a safe assumption.
1885 *
1886 * We can safely ignore thin-locked children, because by definition
1887 * they have no history and are leaf nodes. In the current
1888 * implementation we always fatten the locks to provide a place to
1889 * hang the stack trace.
1890 */
1891 ExpandingObjectList* pList = &mon->historyChildren;
1892 int i;
1893 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
1894 const Object* child = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001895 u4 lock = child->lock;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001896 if (!IS_LOCK_FAT(&lock))
1897 continue;
1898 if (!traverseTree(self, child)) {
1899 LOGW("--- object %p (%s)\n", obj, obj->clazz->descriptor);
1900 dvmLogRawStackTrace(mon->historyRawStackTrace,
1901 mon->historyStackDepth);
1902 mon->historyMark = false;
1903 return false;
1904 }
1905 }
1906
1907 mon->historyMark = false;
1908
1909 return true;
1910}
1911
1912/*
1913 * Update the deadlock prediction tree, based on the current thread
1914 * acquiring "acqObj". This must be called before the object is added to
1915 * the thread's list of held monitors.
1916 *
1917 * If the thread already holds the lock (recursion), or this is a known
1918 * lock configuration, we return without doing anything. Otherwise, we add
1919 * a link from the most-recently-acquired lock in this thread to "acqObj"
1920 * after ensuring that the parent lock is "fat".
1921 *
1922 * This MUST NOT be called while a GC is in progress in another thread,
1923 * because we assume exclusive access to history trees in owned monitors.
1924 */
1925static void updateDeadlockPrediction(Thread* self, Object* acqObj)
1926{
1927 LockedObjectData* lod;
1928 LockedObjectData* mrl;
1929
1930 /*
1931 * Quick check for recursive access.
1932 */
1933 lod = dvmFindInMonitorList(self, acqObj);
1934 if (lod != NULL) {
1935 LOGV("+++ DP: recursive %p\n", acqObj);
1936 return;
1937 }
1938
1939 /*
1940 * Make the newly-acquired object's monitor "fat". In some ways this
1941 * isn't strictly necessary, but we need the GC to tell us when
1942 * "interesting" objects go away, and right now the only way to make
1943 * an object look interesting is to give it a monitor.
1944 *
1945 * This also gives us a place to hang a stack trace.
1946 *
1947 * Our thread holds the lock, so we're allowed to rewrite the lock
1948 * without worrying that something will change out from under us.
1949 */
1950 if (!IS_LOCK_FAT(&acqObj->lock)) {
1951 LOGVV("fattening lockee %p (recur=%d)\n",
Carl Shapiro94338aa2009-12-21 11:42:59 -08001952 acqObj, LW_LOCK_COUNT(acqObj->lock.thin));
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001953 inflateMonitor(self, acqObj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001954 }
1955
1956 /* if we don't have a stack trace for this monitor, establish one */
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001957 if (LW_MONITOR(acqObj->lock)->historyRawStackTrace == NULL) {
1958 Monitor* mon = LW_MONITOR(acqObj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001959 mon->historyRawStackTrace = dvmFillInStackTraceRaw(self,
1960 &mon->historyStackDepth);
1961 }
1962
1963 /*
1964 * We need to examine and perhaps modify the most-recently-locked
1965 * monitor. We own that, so there's no risk of another thread
1966 * stepping on us.
1967 *
1968 * Retrieve the most-recently-locked entry from our thread.
1969 */
1970 mrl = self->pLockedObjects;
1971 if (mrl == NULL)
1972 return; /* no other locks held */
1973
1974 /*
1975 * Do a quick check to see if "acqObj" is a direct descendant. We can do
1976 * this without holding the global lock because of our assertion that
1977 * a GC is not running in parallel -- nobody except the GC can
1978 * modify a history list in a Monitor they don't own, and we own "mrl".
1979 * (There might be concurrent *reads*, but no concurrent *writes.)
1980 *
1981 * If we find it, this is a known good configuration, and we're done.
1982 */
1983 if (objectInChildList(mrl->obj, acqObj))
1984 return;
1985
1986 /*
1987 * "mrl" is going to need to have a history tree. If it's currently
1988 * a thin lock, we make it fat now. The thin lock might have a
1989 * nonzero recursive lock count, which we need to carry over.
1990 *
1991 * Our thread holds the lock, so we're allowed to rewrite the lock
1992 * without worrying that something will change out from under us.
1993 */
1994 if (!IS_LOCK_FAT(&mrl->obj->lock)) {
1995 LOGVV("fattening parent %p f/b/o child %p (recur=%d)\n",
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08001996 mrl->obj, acqObj, LW_LOCK_COUNT(mrl->obj->lock));
Carl Shapiro66bb7df2010-03-12 15:25:37 -08001997 inflateMonitor(self, mrl->obj);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001998 }
1999
2000 /*
2001 * We haven't seen this configuration before. We need to scan down
2002 * acqObj's tree to see if any of the monitors in self->pLockedObjects
2003 * appear. We grab a global lock before traversing or updating the
2004 * history list.
2005 *
2006 * If we find a match for any of our held locks, we know that the lock
2007 * has previously been acquired *after* acqObj, and we throw an error.
2008 *
2009 * The easiest way to do this is to create a link from "mrl" to "acqObj"
2010 * and do a recursive traversal, marking nodes as we cross them. If
2011 * we cross one a second time, we have a cycle and can throw an error.
2012 * (We do the flag-clearing traversal before adding the new link, so
2013 * that we're guaranteed to terminate.)
2014 *
2015 * If "acqObj" is a thin lock, it has no history, and we can create a
2016 * link to it without additional checks. [ We now guarantee that it's
2017 * always fat. ]
2018 */
2019 bool failed = false;
2020 dvmLockMutex(&gDvm.deadlockHistoryLock);
2021 linkParentToChild(mrl->obj, acqObj);
2022 if (!traverseTree(self, acqObj)) {
2023 LOGW("%s\n", kEndBanner);
2024 failed = true;
2025
2026 /* remove the entry so we're still okay when in "warning" mode */
2027 unlinkParentFromChild(mrl->obj, acqObj);
2028 }
2029 dvmUnlockMutex(&gDvm.deadlockHistoryLock);
2030
2031 if (failed) {
2032 switch (gDvm.deadlockPredictMode) {
2033 case kDPErr:
2034 dvmThrowException("Ldalvik/system/PotentialDeadlockError;", NULL);
2035 break;
2036 case kDPAbort:
2037 LOGE("Aborting due to potential deadlock\n");
2038 dvmAbort();
2039 break;
2040 default:
2041 /* warn only */
2042 break;
2043 }
2044 }
2045}
2046
2047/*
2048 * We're removing "child" from existence. We want to pull all of
2049 * child's children into "parent", filtering out duplicates. This is
2050 * called during the GC.
2051 *
2052 * This does not modify "child", which might have multiple parents.
2053 */
2054static void mergeChildren(Object* parent, const Object* child)
2055{
2056 Monitor* mon;
2057 int i;
2058
2059 assert(IS_LOCK_FAT(&child->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08002060 mon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002061 ExpandingObjectList* pList = &mon->historyChildren;
2062
2063 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2064 Object* grandChild = expandBufGetEntry(pList, i);
2065
2066 if (!objectInChildList(parent, grandChild)) {
2067 LOGVV("+++ migrating %p link to %p\n", grandChild, parent);
2068 linkParentToChild(parent, grandChild);
2069 } else {
2070 LOGVV("+++ parent %p already links to %p\n", parent, grandChild);
2071 }
2072 }
2073}
2074
2075/*
2076 * An object with a fat lock is being collected during a GC pass. We
2077 * want to remove it from any lock history trees that it is a part of.
2078 *
2079 * This may require updating the history trees in several monitors. The
2080 * monitor semantics guarantee that no other thread will be accessing
2081 * the history trees at the same time.
2082 */
2083static void removeCollectedObject(Object* obj)
2084{
2085 Monitor* mon;
2086
2087 LOGVV("+++ collecting %p\n", obj);
2088
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002089 /*
2090 * For every parent of this object:
2091 * - merge all of our children into the parent's child list (creates
2092 * a two-way link between parent and child)
2093 * - remove ourselves from the parent's child list
2094 */
2095 ExpandingObjectList* pList;
2096 int i;
2097
2098 assert(IS_LOCK_FAT(&obj->lock));
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08002099 mon = LW_MONITOR(obj->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002100 pList = &mon->historyParents;
2101 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2102 Object* parent = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08002103 Monitor* parentMon = LW_MONITOR(parent->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002104
2105 if (!expandObjRemoveEntry(&parentMon->historyChildren, obj)) {
2106 LOGW("WARNING: child %p not found in parent %p\n", obj, parent);
2107 }
2108 assert(!expandObjHas(&parentMon->historyChildren, obj));
2109
2110 mergeChildren(parent, obj);
2111 }
2112
2113 /*
2114 * For every child of this object:
2115 * - remove ourselves from the child's parent list
2116 */
2117 pList = &mon->historyChildren;
2118 for (i = expandBufGetCount(pList)-1; i >= 0; i--) {
2119 Object* child = expandBufGetEntry(pList, i);
Carl Shapiro8d7f9b22009-12-21 20:23:45 -08002120 Monitor* childMon = LW_MONITOR(child->lock);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08002121
2122 if (!expandObjRemoveEntry(&childMon->historyParents, obj)) {
2123 LOGW("WARNING: parent %p not found in child %p\n", obj, child);
2124 }
2125 assert(!expandObjHas(&childMon->historyParents, obj));
2126 }
2127}
2128
2129#endif /*WITH_DEADLOCK_PREDICTION*/