/* * Grab the lock, but put ourselves into THREAD_VMWAIT if it looks like * we're going to have to wait on the mutex. */ bool dvmLockHeap() { if (dvmTryLockMutex(&gDvm.gcHeapLock) != 0) { Thread *self; ThreadStatus oldStatus; self = dvmThreadSelf(); oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); dvmLockMutex(&gDvm.gcHeapLock); dvmChangeStatus(self, oldStatus); } return true; }
/* * Acquires a mutex, transitioning to the VMWAIT state if the mutex is * held. This allows the thread to suspend while it waits for another * thread to release the mutex. */ static void lockMutex(pthread_mutex_t *mu) { Thread *self; ThreadStatus oldStatus; assert(mu != NULL); if (dvmTryLockMutex(mu) != 0) { self = dvmThreadSelf(); assert(self != NULL); oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); dvmLockMutex(mu); dvmChangeStatus(self, oldStatus); } }
static bool tryLockMonitor(Thread* self, Monitor* mon) { if (mon->owner == self) { mon->lockCount++; return true; } else { if (dvmTryLockMutex(&mon->lock) == 0) { mon->owner = self; assert(mon->lockCount == 0); return true; } else { return false; } } }
/* * Grab the lock, but put ourselves into THREAD_VMWAIT if it looks like * we're going to have to wait on the mutex. */ bool dvmLockHeap() { /* This is hacked a bit to avoid deadlocks. Basically I don't want a thread * to suspend itself hodling the heap lock. */ int res; while ((res = dvmTryLockMutex(&gDvm.gcHeapLock)) != 0) { assert(res == EBUSY); Thread *self; ThreadStatus oldStatus; self = dvmThreadSelf(); oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); dvmLockMutex(&gDvm.gcHeapLock); dvmUnlockMutex(&gDvm.gcHeapLock); dvmChangeStatus(self, oldStatus); } return true; }
/* * Grab the lock, but put ourselves into THREAD_VMWAIT if it looks like * we're going to have to wait on the mutex. */ bool dvmLockHeap() { if (dvmTryLockMutex(&gDvm.gcHeapLock) != 0) { Thread *self; ThreadStatus oldStatus; self = dvmThreadSelf(); #ifdef FASTIVA FASTIVA_SUSPEND_STACK_unsafe(self); #endif oldStatus = dvmChangeStatus(self, THREAD_VMWAIT); dvmLockMutex(&gDvm.gcHeapLock); dvmChangeStatus(self, oldStatus); #ifdef FASTIVA FASTIVA_RESUME_STACK_unsafe(self); #endif } return true; }
/* * Lock a monitor. */ static void lockMonitor(Thread* self, Monitor* mon) { ThreadStatus oldStatus; u4 waitThreshold, samplePercent; u8 waitStart, waitEnd, waitMs; if (mon->owner == self) { mon->lockCount++; return; } if (dvmTryLockMutex(&mon->lock) != 0) { oldStatus = dvmChangeStatus(self, THREAD_MONITOR); waitThreshold = gDvm.lockProfThreshold; if (waitThreshold) { waitStart = dvmGetRelativeTimeUsec(); } const Method* currentOwnerMethod = mon->ownerMethod; u4 currentOwnerPc = mon->ownerPc; dvmLockMutex(&mon->lock); if (waitThreshold) { waitEnd = dvmGetRelativeTimeUsec(); } dvmChangeStatus(self, oldStatus); if (waitThreshold) { waitMs = (waitEnd - waitStart) / 1000; if (waitMs >= waitThreshold) { samplePercent = 100; } else { samplePercent = 100 * waitMs / waitThreshold; } if (samplePercent != 0 && ((u4)rand() % 100 < samplePercent)) { const char* currentOwnerFileName = "no_method"; u4 currentOwnerLineNumber = 0; if (currentOwnerMethod != NULL) { currentOwnerFileName = dvmGetMethodSourceFile(currentOwnerMethod); if (currentOwnerFileName == NULL) { currentOwnerFileName = "no_method_file"; } currentOwnerLineNumber = dvmLineNumFromPC(currentOwnerMethod, currentOwnerPc); } logContentionEvent(self, waitMs, samplePercent, currentOwnerFileName, currentOwnerLineNumber); } } } mon->owner = self; assert(mon->lockCount == 0); // When debugging, save the current monitor holder for future // acquisition failures to use in sampled logging. if (gDvm.lockProfThreshold > 0) { mon->ownerMethod = NULL; mon->ownerPc = 0; if (self->interpSave.curFrame == NULL) { return; } const StackSaveArea* saveArea = SAVEAREA_FROM_FP(self->interpSave.curFrame); if (saveArea == NULL) { return; } mon->ownerMethod = saveArea->method; mon->ownerPc = (saveArea->xtra.currentPc - saveArea->method->insns); } }