/** RaceDet: get recursion count, assuming lock is held by current thread */ @Uninterruptible @NoNullCheck @Inline public static final int getRecursionCountLocked(Object o, Offset lockOffset) { if (VM.VerifyAssertions) { VM._assert(holdsLock(o, lockOffset, RVMThread.getCurrentThread())); } Word bits = Magic.getWordAtOffset(o, lockOffset); int count; if (bits.and(TL_STAT_MASK).EQ(TL_STAT_FAT)) { // if locked, then it is locked with a fat lock Lock l = Lock.getLock(getLockIndex(bits)); l.mutex.lock(); count = l.getRecursionCount(); l.mutex.unlock(); } else { if (VM.VerifyAssertions) { VM._assert( bits.and(TL_STAT_MASK).EQ(TL_STAT_BIASABLE) || bits.and(TL_STAT_MASK).EQ(TL_STAT_THIN)); } count = getRecCount(bits); } if (VM.VerifyAssertions) { VM._assert(count > 0); } return count; }
/** * Promotes a light-weight lock to a heavy-weight lock. If this returns the lock that you gave it, * its mutex will be locked; otherwise, its mutex will be unlocked. Hence, calls to this method * should always be followed by a condition lock() or unlock() call. * * @param o the object to get a heavy-weight lock * @param lockOffset the offset of the thin lock word in the object. * @return the inflated lock; either the one you gave, or another one, if the lock was inflated by * some other thread. */ @NoNullCheck @Unpreemptible protected static Lock attemptToInflate(Object o, Offset lockOffset, Lock l) { if (false) VM.sysWriteln("l = ", Magic.objectAsAddress(l)); l.mutex.lock(); for (int cnt = 0; ; ++cnt) { Word bits = Magic.getWordAtOffset(o, lockOffset); // check to see if another thread has already created a fat lock if (isFat(bits)) { if (trace) { VM.sysWriteln( "Thread #", RVMThread.getCurrentThreadSlot(), ": freeing lock ", Magic.objectAsAddress(l), " because we had a double-inflate"); } Lock result = Lock.getLock(getLockIndex(bits)); if (result == null || result.lockedObject != o) { continue; /* this is nasty. this will happen when a lock is deflated. */ } Lock.free(l); l.mutex.unlock(); return result; } if (VM.VerifyAssertions) VM._assert(l != null); if (attemptToMarkInflated(o, lockOffset, bits, l.index, cnt)) { l.setLockedObject(o); l.setOwnerId(getLockOwner(bits)); if (l.getOwnerId() != 0) { l.setRecursionCount(getRecCount(bits)); } else { if (VM.VerifyAssertions) VM._assert(l.getRecursionCount() == 0); } return l; } // contention detected, try again } }