Search in sources :

Example 31 with NoInline

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

the class SpinLock method handleMicrocontention.

/**
 * An attempt to lock or unlock a processor lock has failed,
 * presumably due to contention with another processor.  Backoff a
 * little to increase the likelihood that a subsequent retry will
 * succeed.
 *
 * @param n the number of attempts
 */
@NoInline
private void handleMicrocontention(int n) {
    // reduce overhead of spin wait on IA
    Magic.pause();
    // method call overhead is delay enough
    if (n <= 0)
        return;
    if (n > 100) {
        // PNT: FIXME: we're dying here ... maybe we're deadlocking?
        VM.sysWriteln("Unexpectedly large spin lock contention on ", Magic.objectAsAddress(this));
        RVMThread t = latestContender;
        if (t == null) {
            VM.sysWriteln("Unexpectedly large spin lock contention in ", RVMThread.getCurrentThreadSlot(), "; lock held by nobody");
        } else {
            VM.sysWriteln("Unexpectedly large spin lock contention in ", RVMThread.getCurrentThreadSlot(), "; lock held by ", t.getThreadSlot());
            if (t != RVMThread.getCurrentThread()) {
                VM.sysWriteln("But -- at least the spin lock is held by a different thread.");
            }
        }
        RVMThread.dumpStack();
        VM.sysFail("Unexpectedly large spin lock contention");
    }
    // PNT: this is weird.
    // delay a different amount in each thread
    int pid = RVMThread.getCurrentThread().getThreadSlot();
    delayIndex = (delayIndex + pid) % delayCount.length;
    // pseudorandom backoff component
    int delay = delayCount[delayIndex] * delayMultiplier;
    // exponential backoff component
    delay += delayBase << (n - 1);
    // delay a different amount of time on each thread
    for (int i = delay; i > 0; i--) ;
}
Also used : Entrypoint(org.vmmagic.pragma.Entrypoint) NoInline(org.vmmagic.pragma.NoInline)

Example 32 with NoInline

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

the class RVMThread method saveThreadState.

/**
 * Save the current thread state.  Call this prior to calling enterNative().  You must
 * be in a method that is marked BaselineSaveLSRegisters.
 */
@NoInline
public static void saveThreadState() {
    Address curFP = Magic.getFramePointer();
    getCurrentThread().contextRegisters.setInnermost(Magic.getReturnAddressUnchecked(curFP), Magic.getCallerFramePointer(curFP));
}
Also used : Address(org.vmmagic.unboxed.Address) NoInline(org.vmmagic.pragma.NoInline)

Example 33 with NoInline

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

the class RVMThread method checkBlockNoSaveContext.

/**
 * A variant of checkBlock() that does not save the thread state.
 */
@NoInline
@Unpreemptible("May block if the thread was asked to do so, but otherwise does no actions that would cause blocking")
private void checkBlockNoSaveContext() {
    assertUnacceptableStates(NEW, TERMINATED);
    if (VM.VerifyAssertions)
        VM._assert(!isAboutToTerminate);
    if (VM.VerifyAssertions)
        VM._assert(!isBlocking);
    if (traceBlock)
        VM.sysWriteln("Thread #", threadSlot, " in checkBlockNoSaveContext");
    // NB: anything this method calls CANNOT change the contextRegisters
    // or the JNI env. as well, this code will be running concurrently
    // with stop-the-world GC!
    monitor().lockNoHandshake();
    isBlocking = true;
    if (traceBlock)
        VM.sysWriteln("Thread #", threadSlot, " acquired lock and has notified everyone that we're blocked");
    // deal with requests that would require a soft handshake rendezvous
    handleHandshakeRequest();
    // check if a soft handshake has been requested, and if so, clear the
    // request
    boolean commitSoftRendezvous = softRendezvousCheckAndClear();
    if (commitSoftRendezvous) {
        // if a soft handshake had been requested, we need to acknowledge it.
        // but to acknowledge it we cannot be holding the monitor() lock.
        // it turns out that at this point in the code it is perfectly safe
        // to release it, because:
        // 1) callers of this method expect that it may, in all likelihood,
        // release the monitor() lock if they were holding it, since it
        // calls wait()
        // 2) if the block requests get cleared when we release the lock,
        // we won't call wait, since we reacquire the lock prior to checking
        // for block requests.
        int recCount = monitor().unlockCompletely();
        softRendezvousCommit();
        monitor().relockNoHandshake(recCount);
    }
    if (traceBlock)
        VM.sysWriteln("Thread #", threadSlot, " has acknowledged soft handshakes");
    boolean hadReallyBlocked = false;
    for (; ; ) {
        // deal with block requests
        acknowledgeBlockRequests();
        // are we blocked?
        if (!isBlocked()) {
            break;
        }
        if (traceReallyBlock) {
            hadReallyBlocked = true;
            VM.sysWriteln("Thread #", threadSlot, " is really blocked with status ", READABLE_EXEC_STATUS[getExecStatus()]);
            VM.sysWriteln("Thread #", threadSlot, " has fp = ", Magic.getFramePointer());
            if (dumpStackOnBlock) {
                dumpStack();
            }
        }
        // what if a GC request comes while we're here for a suspend()
        // request?
        // answer: we get awoken, reloop, and acknowledge the GC block
        // request.
        monitor().waitNoHandshake();
        if (traceBlock)
            VM.sysWriteln("Thread #", threadSlot, " has awoken; checking if we're still blocked");
    }
    if (traceBlock || (traceReallyBlock && hadReallyBlocked))
        VM.sysWriteln("Thread #", threadSlot, " is unblocking");
    // we're about to unblock, so indicate to the world that we're running
    // again.
    setExecStatus(IN_JAVA);
    // let everyone know that we're back to executing code
    isBlocking = false;
    // deal with requests that came up while we were blocked.
    handleHandshakeRequest();
    monitor().unlock();
    if (traceBlock)
        VM.sysWriteln("Thread #", threadSlot, " is unblocked");
}
Also used : Entrypoint(org.vmmagic.pragma.Entrypoint) Unpreemptible(org.vmmagic.pragma.Unpreemptible) NoInline(org.vmmagic.pragma.NoInline)

Example 34 with NoInline

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

the class RVMThread method enterNative.

/**
 * Indicate that we'd like the current thread to be executing privileged code that
 * does not require synchronization with the GC.  This call may be made on a thread
 * that is IN_JAVA or IN_JAVA_TO_BLOCK, and will result in the thread being either
 * IN_NATIVE or BLOCKED_IN_NATIVE.  In the case of an
 * IN_JAVA_TO_BLOCK-&gt;BLOCKED_IN_NATIVE transition, this call will acquire the
 * thread's lock and send out a notification to any threads waiting for this thread
 * to reach a safepoint.  This notification serves to notify them that the thread
 * is in GC-safe code, but will not reach an actual safepoint for an indetermined
 * amount of time.  This is significant, because safepoints may perform additional
 * actions (such as handling handshake requests, which may include things like
 * mutator flushes and running isync) that IN_NATIVE code will not perform until
 * returning to IN_JAVA by way of a leaveNative() call.
 */
// so we can get the fp
@NoInline
public static void enterNative() {
    RVMThread t = getCurrentThread();
    if (ALWAYS_LOCK_ON_STATE_TRANSITION) {
        t.enterNativeBlocked();
    } else {
        int oldState, newState;
        do {
            oldState = t.getExecStatus();
            if (oldState == IN_JAVA) {
                newState = IN_NATIVE;
            } else {
                t.assertAcceptableStates(IN_JAVA_TO_BLOCK);
                t.enterNativeBlocked();
                return;
            }
        } while (!(t.attemptFastExecStatusTransition(oldState, newState)));
    }
// NB this is not a correct assertion, as there is a race.  we could succeed in
// CASing the status to IN_NATIVE, but then someone else could asynchronosly
// set it to whatever they want.
// if (VM.VerifyAssertions)
// VM._assert(t.execStatus == IN_NATIVE);
}
Also used : Entrypoint(org.vmmagic.pragma.Entrypoint) NoInline(org.vmmagic.pragma.NoInline)

Example 35 with NoInline

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

the class FinalizableProcessor method add.

/**
 * Allocate an entry in the table. This should be called from an unpreemptible
 * context so that the entry can be filled. This method is responsible for growing
 * the table if necessary.
 *
 * @param object the object to add to the table of candidates
 */
@NoInline
@UnpreemptibleNoWarn("Non-preemptible but yield when table needs to be grown")
public void add(Object object) {
    lock.acquire();
    while (maxIndex >= table.length() || maxIndex >= freeReady()) {
        int newTableSize = -1;
        int newReadyForFinalizeSize = -1;
        AddressArray newTable = null;
        Object[] newReadyForFinalize = null;
        if (maxIndex >= table.length()) {
            newTableSize = STRESS ? table.length() + 1 : (int) (table.length() * GROWTH_FACTOR);
        }
        if (maxIndex >= freeReady()) {
            newReadyForFinalizeSize = table.length() + countReady();
            if (newReadyForFinalizeSize <= readyForFinalize.length) {
                newReadyForFinalizeSize = -1;
            }
        }
        {
            lock.release();
            if (newTableSize >= 0) {
                newTable = AddressArray.create(newTableSize);
            }
            if (newReadyForFinalizeSize >= 0) {
                newReadyForFinalize = new Object[newReadyForFinalizeSize];
            }
            lock.acquire();
        }
        if (maxIndex >= table.length() && newTable != null) {
            for (int i = 0; i < table.length(); i++) {
                newTable.set(i, table.get(i));
            }
            table = newTable;
        }
        if (maxIndex >= freeReady() && newReadyForFinalize != null) {
            int j = 0;
            for (int i = nextReadyIndex; i < lastReadyIndex && i < readyForFinalize.length; i++) {
                newReadyForFinalize[j++] = readyForFinalize[i];
            }
            if (lastReadyIndex < nextReadyIndex) {
                for (int i = 0; i < lastReadyIndex; i++) {
                    newReadyForFinalize[j++] = readyForFinalize[i];
                }
            }
            lastReadyIndex = j;
            nextReadyIndex = 0;
            readyForFinalize = newReadyForFinalize;
        }
    }
    table.set(maxIndex++, Magic.objectAsAddress(object));
    lock.release();
}
Also used : AddressArray(org.vmmagic.unboxed.AddressArray) NoInline(org.vmmagic.pragma.NoInline) UnpreemptibleNoWarn(org.vmmagic.pragma.UnpreemptibleNoWarn)

Aggregations

NoInline (org.vmmagic.pragma.NoInline)46 Entrypoint (org.vmmagic.pragma.Entrypoint)23 Address (org.vmmagic.unboxed.Address)22 Unpreemptible (org.vmmagic.pragma.Unpreemptible)10 TIB (org.jikesrvm.objectmodel.TIB)9 Interruptible (org.vmmagic.pragma.Interruptible)9 RVMArray (org.jikesrvm.classloader.RVMArray)8 Word (org.vmmagic.unboxed.Word)6 NoOptCompile (org.vmmagic.pragma.NoOptCompile)5 Offset (org.vmmagic.unboxed.Offset)5 MethodReference (org.jikesrvm.classloader.MethodReference)4 CodeArray (org.jikesrvm.compilers.common.CodeArray)4 CompiledMethod (org.jikesrvm.compilers.common.CompiledMethod)4 AbstractRegisters (org.jikesrvm.architecture.AbstractRegisters)3 RVMMethod (org.jikesrvm.classloader.RVMMethod)3 BaselineCompiledMethod (org.jikesrvm.compilers.baseline.BaselineCompiledMethod)3 OptCompiledMethod (org.jikesrvm.compilers.opt.runtimesupport.OptCompiledMethod)3 BaselineSaveLSRegisters (org.vmmagic.pragma.BaselineSaveLSRegisters)3 RVMType (org.jikesrvm.classloader.RVMType)2 RVMThread (org.jikesrvm.scheduler.RVMThread)2