Search in sources :

Example 21 with Unpreemptible

use of org.vmmagic.pragma.Unpreemptible 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 22 with Unpreemptible

use of org.vmmagic.pragma.Unpreemptible 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 23 with Unpreemptible

use of org.vmmagic.pragma.Unpreemptible 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)

Example 24 with Unpreemptible

use of org.vmmagic.pragma.Unpreemptible in project JikesRVM by JikesRVM.

the class RVMThread method blockAllMutatorsForGC.

/**
 * Stop all mutator threads. This is current intended to be run by a single thread.
 *
 * Fixpoint until there are no threads that we haven't blocked. Fixpoint is needed to
 * catch the (unlikely) case that a thread spawns another thread while we are waiting.
 */
@NoCheckStore
@Unpreemptible
public static void blockAllMutatorsForGC() {
    RVMThread.handshakeLock.lockNoHandshake();
    while (true) {
        // (1) Find all the threads that need to be blocked for GC
        RVMThread.acctLock.lockNoHandshake();
        int numToHandshake = 0;
        for (int i = 0; i < RVMThread.numThreads; i++) {
            RVMThread t = RVMThread.threads[i];
            if (!t.isCollectorThread() && !t.ignoreHandshakesAndGC()) {
                RVMThread.handshakeThreads[numToHandshake++] = t;
            }
        }
        RVMThread.acctLock.unlock();
        // (2) Remove any threads that have already been blocked from the list.
        for (int i = 0; i < numToHandshake; i++) {
            RVMThread t = RVMThread.handshakeThreads[i];
            t.monitor().lockNoHandshake();
            if (t.blockedFor(RVMThread.gcBlockAdapter) || RVMThread.notRunning(t.asyncBlock(RVMThread.gcBlockAdapter))) {
                // Already blocked or not running, remove.
                RVMThread.handshakeThreads[i--] = RVMThread.handshakeThreads[--numToHandshake];
                // help GC
                RVMThread.handshakeThreads[numToHandshake] = null;
            }
            t.monitor().unlock();
        }
        // terminating).
        if (numToHandshake == 0)
            break;
        // (4) Request a block for GC from all other threads.
        for (int i = 0; i < numToHandshake; i++) {
            if (false)
                VM.sysWriteln("Waiting for ", RVMThread.handshakeThreads[i].getThreadSlot(), " to block.");
            RVMThread t = RVMThread.handshakeThreads[i];
            RVMThread.observeExecStatusAtSTW(t.block(RVMThread.gcBlockAdapter));
            // help GC
            RVMThread.handshakeThreads[i] = null;
        }
    }
    RVMThread.handshakeLock.unlock();
    // Deal with terminating threads to ensure that all threads are either dead to MMTk or stopped above.
    RVMThread.processAboutToTerminate();
}
Also used : Entrypoint(org.vmmagic.pragma.Entrypoint) Unpreemptible(org.vmmagic.pragma.Unpreemptible) NoCheckStore(org.vmmagic.pragma.NoCheckStore)

Example 25 with Unpreemptible

use of org.vmmagic.pragma.Unpreemptible in project JikesRVM by JikesRVM.

the class RVMThread method block.

/**
 * Attempts to block the thread, and return the state it is in after the
 * attempt. If we're blocking ourselves, this will always return IN_JAVA. If
 * the thread signals to us the intention to die as we are trying to block it,
 * this will return TERMINATED. NOTE: the thread's execStatus will not
 * actually be TERMINATED at that point yet.
 * <p>
 * Note that this method is ridiculously dangerous, especially if you pass
 * asynchronous==false.  Waiting for another thread to stop is not in itself
 * interruptible - so if you ask another thread to block and they ask you
 * to block, you might deadlock.
 *
 * @param ba the adapter to block on
 * @param asynchronous {@code true} if the request is asynchronous (i.e. the
 *  receiver is only notified), {@code false} if the caller waits for the
 *  receiver to block
 * @return the new state of the thread
 */
@Unpreemptible("Only blocks if the receiver is the current thread, or if asynchronous is set to false and the thread is not already blocked")
int block(BlockAdapter ba, boolean asynchronous) {
    int result;
    if (traceBlock)
        VM.sysWriteln("Thread #", getCurrentThread().threadSlot, " is requesting that thread #", threadSlot, " blocks.");
    monitor().lockNoHandshake();
    int token = ba.requestBlock(this);
    if (getCurrentThread() == this) {
        if (traceBlock)
            VM.sysWriteln("Thread #", threadSlot, " is blocking.");
        checkBlock();
        result = getExecStatus();
    } else {
        if (traceBlock)
            VM.sysWriteln("Thread #", threadSlot, " is being told to block.");
        if (isAboutToTerminate) {
            if (traceBlock)
                VM.sysWriteln("Thread #", threadSlot, " is terminating, returning as if blocked in TERMINATED state.");
            result = TERMINATED;
        } else {
            takeYieldpoint = 1;
            // CAS the execStatus field
            int newState = setBlockedExecStatus();
            result = newState;
            if (traceReallyBlock)
                VM.sysWriteln("Thread #", getCurrentThreadSlot(), " is blocking thread #", threadSlot, " which is in state ", newState);
            // this broadcast serves two purposes: notifies threads that are
            // IN_JAVA but waiting on monitor() that they should awake and
            // acknowledge the block request; or notifies anyone
            // waiting for this thread to block that the thread is
            // BLOCKED_IN_NATIVE or BLOCKED_IN_JNI. in the latter case the
            // broadcast() happens _before_ the setting of the flags that the
            // other threads would be awaiting, but that is fine, since we're
            // still holding the lock anyway.
            monitor().broadcast();
            if (newState == IN_JAVA_TO_BLOCK) {
                if (!asynchronous) {
                    if (traceBlock)
                        VM.sysWriteln("Thread #", getCurrentThread().threadSlot, " is waiting for thread #", threadSlot, " to block.");
                    while (ba.hasBlockRequest(this, token) && !ba.isBlocked(this) && !isAboutToTerminate) {
                        if (traceBlock)
                            VM.sysWriteln("Thread #", getCurrentThread().threadSlot, " is calling wait until thread #", threadSlot, " blocks.");
                        // will this deadlock when the thread dies?
                        if (VM.VerifyAssertions) {
                            // do a timed wait, and assert that the thread did not disappear
                            // into native in the meantime
                            // 1 sec
                            monitor().timedWaitRelativeNoHandshake(1000L * 1000L * 1000L);
                            if (traceReallyBlock) {
                                VM.sysWriteln("Thread #", threadSlot, "'s status is ", READABLE_EXEC_STATUS[getExecStatus()]);
                            }
                            assertUnacceptableStates(IN_NATIVE);
                        } else {
                            monitor().waitNoHandshake();
                        }
                        if (traceBlock)
                            VM.sysWriteln("Thread #", getCurrentThread().threadSlot, " has returned from the wait call.");
                    }
                    if (isAboutToTerminate) {
                        result = TERMINATED;
                    } else {
                        result = getExecStatus();
                    }
                }
            } else if (newState == BLOCKED_IN_NATIVE || newState == BLOCKED_IN_JNI) {
                // state accordingly and tell anyone who is waiting.
                if (traceBlock)
                    VM.sysWriteln("Thread #", getCurrentThread().threadSlot, " has seen thread #", threadSlot, " in native; changing its status accordingly.");
                ba.clearBlockRequest(this);
                ba.setBlocked(this, true);
            }
        }
    }
    monitor().unlock();
    if (traceReallyBlock)
        VM.sysWriteln("Thread #", getCurrentThread().threadSlot, " is done telling thread #", threadSlot, " to block.");
    return result;
}
Also used : Entrypoint(org.vmmagic.pragma.Entrypoint) Unpreemptible(org.vmmagic.pragma.Unpreemptible)

Aggregations

Unpreemptible (org.vmmagic.pragma.Unpreemptible)34 Entrypoint (org.vmmagic.pragma.Entrypoint)23 NoInline (org.vmmagic.pragma.NoInline)14 Address (org.vmmagic.unboxed.Address)12 RVMThread (org.jikesrvm.scheduler.RVMThread)7 Offset (org.vmmagic.unboxed.Offset)6 Word (org.vmmagic.unboxed.Word)6 NoCheckStore (org.vmmagic.pragma.NoCheckStore)5 NoNullCheck (org.vmmagic.pragma.NoNullCheck)5 OptCompiledMethod (org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod)4 Inline (org.vmmagic.pragma.Inline)4 BaselineSaveLSRegisters (org.vmmagic.pragma.BaselineSaveLSRegisters)3 NoOptCompile (org.vmmagic.pragma.NoOptCompile)3 NormalMethod (org.jikesrvm.classloader.NormalMethod)2 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)2 GPR (org.jikesrvm.ia32.RegisterConstants.GPR)2 AbstractRegisters (org.jikesrvm.architecture.AbstractRegisters)1 RVMArray (org.jikesrvm.classloader.RVMArray)1 RVMMethod (org.jikesrvm.classloader.RVMMethod)1 RVMType (org.jikesrvm.classloader.RVMType)1