@Uninterruptible @NoNullCheck public static boolean holdsLock(Object o, Offset lockOffset, RVMThread thread) { for (int cnt = 0; ; ++cnt) { int tid = thread.getLockingId(); Word bits = Magic.getWordAtOffset(o, lockOffset); if (bits.and(TL_STAT_MASK).EQ(TL_STAT_BIASABLE)) { // if locked, then it is locked with a thin lock return bits.and(TL_THREAD_ID_MASK).toInt() == tid && !bits.and(TL_LOCK_COUNT_MASK).isZero(); } else if (bits.and(TL_STAT_MASK).EQ(TL_STAT_THIN)) { return bits.and(TL_THREAD_ID_MASK).toInt() == tid; } else { if (VM.VerifyAssertions) VM._assert(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)); if (l != null) { l.mutex.lock(); boolean result = (l.getOwnerId() == tid && l.getLockedObject() == o); l.mutex.unlock(); return result; } } RVMThread.yield(); } }
/** * 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 } }