/** * Complete the task of acquiring the heavy lock, assuming that the mutex is already acquired * (locked). */ @Unpreemptible public boolean lockHeavyLocked(Object o) { if (lockedObject != o) { // lock disappeared before we got here mutex.unlock(); // thread switching benign return false; } if (STATS) lockOperations++; RVMThread me = RVMThread.getCurrentThread(); int threadId = me.getLockingId(); if (ownerId == threadId) { recursionCount++; } else if (ownerId == 0) { ownerId = threadId; recursionCount = 1; } else { entering.enqueue(me); mutex.unlock(); me.monitor().lockNoHandshake(); while (entering.isQueued(me)) { me.monitor().waitWithHandshake(); // this may spuriously return } me.monitor().unlock(); return false; } mutex.unlock(); // thread-switching benign return true; }
/** * Releases this heavy-weight lock on the indicated object. * * @param o the object to be unlocked */ @Unpreemptible public void unlockHeavy(Object o) { boolean deflated = false; mutex.lock(); // Note: thread switching is not allowed while mutex is held. RVMThread me = RVMThread.getCurrentThread(); if (ownerId != me.getLockingId()) { mutex.unlock(); // thread-switching benign raiseIllegalMonitorStateException("heavy unlocking", o); } recursionCount--; if (0 < recursionCount) { mutex.unlock(); // thread-switching benign return; } if (STATS) unlockOperations++; ownerId = 0; RVMThread toAwaken = entering.dequeue(); if (toAwaken == null && entering.isEmpty() && waiting.isEmpty()) { // heavy lock can be deflated // Possible project: decide on a heuristic to control when lock should be deflated Offset lockOffset = Magic.getObjectType(o).getThinLockOffset(); if (!lockOffset.isMax()) { // deflate heavy lock deflate(o, lockOffset); deflated = true; } } mutex.unlock(); // does a Magic.sync(); (thread-switching benign) if (toAwaken != null) { toAwaken.monitor().lockedBroadcastNoHandshake(); } }