Search in sources :

Example 46 with Word

use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.

the class ThinLock method lock.

@NoInline
@NoNullCheck
@Unpreemptible
public static void lock(Object o, Offset lockOffset) {
    if (STATS)
        fastLocks++;
    Word threadId = Word.fromIntZeroExtend(RVMThread.getCurrentThread().getLockingId());
    for (int cnt = 0; ; cnt++) {
        Word old = Magic.getWordAtOffset(o, lockOffset);
        Word stat = old.and(TL_STAT_MASK);
        boolean tryToInflate = false;
        if (stat.EQ(TL_STAT_BIASABLE)) {
            Word id = old.and(TL_THREAD_ID_MASK);
            if (id.isZero()) {
                if (ENABLE_BIASED_LOCKING) {
                    // lock is unbiased, bias it in our favor and grab it
                    if (Synchronization.tryCompareAndSwap(o, lockOffset, old, old.or(threadId).plus(TL_LOCK_COUNT_UNIT))) {
                        if (!VM.MagicAttemptImpliesStoreLoadBarrier)
                            Magic.fence();
                        return;
                    }
                } else {
                    // a thin lock
                    if (Synchronization.tryCompareAndSwap(o, lockOffset, old, old.or(threadId).or(TL_STAT_THIN))) {
                        if (!VM.MagicAttemptImpliesStoreLoadBarrier)
                            Magic.fence();
                        return;
                    }
                }
            } else if (id.EQ(threadId)) {
                // lock is biased in our favor
                Word changed = old.plus(TL_LOCK_COUNT_UNIT);
                if (!changed.and(TL_LOCK_COUNT_MASK).isZero()) {
                    setDedicatedU16(o, lockOffset, changed);
                    Magic.combinedLoadBarrier();
                    return;
                } else {
                    tryToInflate = true;
                }
            } else {
                if (casFromBiased(o, lockOffset, old, biasBitsToThinBits(old), cnt)) {
                    // don't spin, since it's thin now
                    continue;
                }
            }
        } else if (stat.EQ(TL_STAT_THIN)) {
            Word id = old.and(TL_THREAD_ID_MASK);
            if (id.isZero()) {
                if (Synchronization.tryCompareAndSwap(o, lockOffset, old, old.or(threadId))) {
                    if (!VM.MagicAttemptImpliesStoreLoadBarrier)
                        Magic.fence();
                    return;
                }
            } else if (id.EQ(threadId)) {
                Word changed = old.plus(TL_LOCK_COUNT_UNIT);
                if (changed.and(TL_LOCK_COUNT_MASK).isZero()) {
                    tryToInflate = true;
                } else if (Synchronization.tryCompareAndSwap(o, lockOffset, old, changed)) {
                    if (!VM.MagicAttemptImpliesStoreLoadBarrier)
                        Magic.fence();
                    return;
                }
            } else if (cnt > retryLimit) {
                tryToInflate = true;
            }
        } else {
            if (VM.VerifyAssertions)
                VM._assert(stat.EQ(TL_STAT_FAT));
            // lock is fat.  contend on it.
            if (Lock.getLock(getLockIndex(old)).lockHeavy(o)) {
                return;
            }
        }
        if (tryToInflate) {
            if (STATS)
                slowLocks++;
            // Right Thing if the lock is biased to someone else.
            if (inflateAndLock(o, lockOffset)) {
                return;
            }
        } else {
            Magic.combinedLoadBarrier();
            RVMThread.yieldNoHandshake();
        }
    }
}
Also used : Word(org.vmmagic.unboxed.Word) Entrypoint(org.vmmagic.pragma.Entrypoint) Unpreemptible(org.vmmagic.pragma.Unpreemptible) NoNullCheck(org.vmmagic.pragma.NoNullCheck) NoInline(org.vmmagic.pragma.NoInline)

Example 47 with Word

use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.

the class ThinLock method unlock.

@NoInline
@NoNullCheck
@Unpreemptible
public static void unlock(Object o, Offset lockOffset) {
    Word threadId = Word.fromIntZeroExtend(RVMThread.getCurrentThread().getLockingId());
    for (int cnt = 0; ; cnt++) {
        Word old = Magic.getWordAtOffset(o, lockOffset);
        Word stat = old.and(TL_STAT_MASK);
        if (stat.EQ(TL_STAT_BIASABLE)) {
            Word id = old.and(TL_THREAD_ID_MASK);
            if (id.EQ(threadId)) {
                if (old.and(TL_LOCK_COUNT_MASK).isZero()) {
                    RVMThread.raiseIllegalMonitorStateException("biased unlocking: we own this object but the count is already zero", o);
                }
                setDedicatedU16(o, lockOffset, old.minus(TL_LOCK_COUNT_UNIT));
                Magic.fence();
                return;
            } else {
                RVMThread.raiseIllegalMonitorStateException("biased unlocking: we don't own this object", o);
            }
        } else if (stat.EQ(TL_STAT_THIN)) {
            Word id = old.and(TL_THREAD_ID_MASK);
            if (id.EQ(threadId)) {
                Word changed;
                if (old.and(TL_LOCK_COUNT_MASK).isZero()) {
                    changed = old.and(TL_UNLOCK_MASK).or(TL_STAT_THIN);
                } else {
                    changed = old.minus(TL_LOCK_COUNT_UNIT);
                }
                Magic.combinedLoadBarrier();
                if (Synchronization.tryCompareAndSwap(o, lockOffset, old, changed)) {
                    if (!VM.MagicAttemptImpliesStoreLoadBarrier)
                        Magic.fence();
                    return;
                }
            } else {
                if (false) {
                    VM.sysWriteln("threadId = ", threadId);
                    VM.sysWriteln("id = ", id);
                }
                RVMThread.raiseIllegalMonitorStateException("thin unlocking: we don't own this object", o);
            }
        } else {
            if (VM.VerifyAssertions)
                VM._assert(stat.EQ(TL_STAT_FAT));
            // fat unlock
            Lock.getLock(getLockIndex(old)).unlockHeavy(o);
            return;
        }
    }
}
Also used : Word(org.vmmagic.unboxed.Word) Entrypoint(org.vmmagic.pragma.Entrypoint) Unpreemptible(org.vmmagic.pragma.Unpreemptible) NoNullCheck(org.vmmagic.pragma.NoNullCheck) NoInline(org.vmmagic.pragma.NoInline)

Example 48 with Word

use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.

the class ThinLock method inlineUnlock.

@Inline
@NoNullCheck
@Unpreemptible
@Entrypoint
public static void inlineUnlock(Object o, Offset lockOffset) {
    // FIXME: bad for PPC?
    Word old = Magic.prepareWord(o, lockOffset);
    Word id = old.and(TL_THREAD_ID_MASK.or(TL_STAT_MASK));
    Word tid = Word.fromIntSignExtend(RVMThread.getCurrentThread().getLockingId());
    if (id.EQ(tid)) {
        if (!old.and(TL_LOCK_COUNT_MASK).isZero()) {
            setDedicatedU16(o, lockOffset, old.minus(TL_LOCK_COUNT_UNIT));
            Magic.fence();
            return;
        }
    } else if (old.xor(tid).rshl(TL_LOCK_COUNT_SHIFT).EQ(TL_STAT_THIN.rshl(TL_LOCK_COUNT_SHIFT))) {
        Magic.combinedLoadBarrier();
        if (Magic.attemptWord(o, lockOffset, old, old.and(TL_UNLOCK_MASK).or(TL_STAT_THIN))) {
            if (!VM.MagicAttemptImpliesStoreLoadBarrier)
                Magic.fence();
            return;
        }
    }
    unlock(o, lockOffset);
}
Also used : Word(org.vmmagic.unboxed.Word) Unpreemptible(org.vmmagic.pragma.Unpreemptible) Entrypoint(org.vmmagic.pragma.Entrypoint) NoNullCheck(org.vmmagic.pragma.NoNullCheck) Inline(org.vmmagic.pragma.Inline) NoInline(org.vmmagic.pragma.NoInline)

Example 49 with Word

use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.

the class ThinLock method casFromBiased.

@NoInline
@Unpreemptible
public static boolean casFromBiased(Object o, Offset lockOffset, Word oldLockWord, Word changed, int cnt) {
    RVMThread me = RVMThread.getCurrentThread();
    Word id = oldLockWord.and(TL_THREAD_ID_MASK);
    if (id.isZero()) {
        if (false)
            VM.sysWriteln("id is zero - easy case.");
        return Synchronization.tryCompareAndSwap(o, lockOffset, oldLockWord, changed);
    } else {
        if (false)
            VM.sysWriteln("id = ", id);
        int slot = id.toInt() >> TL_THREAD_ID_SHIFT;
        if (false)
            VM.sysWriteln("slot = ", slot);
        RVMThread owner = RVMThread.threadBySlot[slot];
        if (owner == me || /* I own it, so I can unbias it trivially.  This occurs
                       when we are inflating due to, for example, wait() */
        owner == null) /* the thread that owned it is dead, so it's safe to
                         unbias. */
        {
            // be unbiasing.
            return Synchronization.tryCompareAndSwap(o, lockOffset, oldLockWord, changed);
        } else {
            boolean result = false;
            // goofy.
            if (false)
                VM.sysWriteln("entering pair handshake");
            owner.beginPairHandshake();
            if (false)
                VM.sysWriteln("done with that");
            Word newLockWord = Magic.getWordAtOffset(o, lockOffset);
            result = Synchronization.tryCompareAndSwap(o, lockOffset, oldLockWord, changed);
            owner.endPairHandshake();
            if (false)
                VM.sysWriteln("that worked.");
            return result;
        }
    }
}
Also used : Word(org.vmmagic.unboxed.Word) Entrypoint(org.vmmagic.pragma.Entrypoint) Unpreemptible(org.vmmagic.pragma.Unpreemptible) NoInline(org.vmmagic.pragma.NoInline)

Example 50 with Word

use of org.vmmagic.unboxed.Word in project JikesRVM by JikesRVM.

the class ThinLock method attemptToInflate.

/**
 * 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.
 * @param l the lock to attempt to inflate
 * @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
    }
}
Also used : Word(org.vmmagic.unboxed.Word) Entrypoint(org.vmmagic.pragma.Entrypoint) Unpreemptible(org.vmmagic.pragma.Unpreemptible) NoNullCheck(org.vmmagic.pragma.NoNullCheck)

Aggregations

Word (org.vmmagic.unboxed.Word)62 Inline (org.vmmagic.pragma.Inline)15 Address (org.vmmagic.unboxed.Address)14 NoInline (org.vmmagic.pragma.NoInline)11 Offset (org.vmmagic.unboxed.Offset)10 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)8 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)8 CodeConstantOperand (org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand)8 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)8 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)8 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)8 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)8 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)8 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)8 ObjectConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand)8 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)8 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)8 TIBConstantOperand (org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand)8 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)8 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)8