use of org.vmmagic.pragma.Unpreemptible in project JikesRVM by JikesRVM.
the class RVMThread method yieldpointFromPrologue.
/*
* Support for yieldpoints
*/
/**
* Yieldpoint taken in prologue.
*/
@BaselineSaveLSRegisters
// Save all non-volatile registers in prologue
@NoOptCompile
@NoInline
// TODO fix this -- related to SaveVolatile
@Entrypoint
@Unpreemptible("Becoming another thread interrupts the current thread, avoid preemption in the process")
public static void yieldpointFromPrologue() {
Address fp = Magic.getFramePointer();
yieldpoint(PROLOGUE, fp);
}
use of org.vmmagic.pragma.Unpreemptible in project JikesRVM by JikesRVM.
the class RVMThread method safeBlock.
@Unpreemptible
private int safeBlock(BlockAdapter ba, boolean asynchronous) {
if (VM.VerifyAssertions)
VM._assert(getCurrentThread() != this);
beginPairWithCurrent();
int result = block(ba, asynchronous);
endPairWithCurrent();
return result;
}
use of org.vmmagic.pragma.Unpreemptible 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");
}
use of org.vmmagic.pragma.Unpreemptible in project JikesRVM by JikesRVM.
the class RVMThread method softHandshake.
/**
* Tell each thread to take a yieldpoint and wait until all of them have done
* so at least once. Additionally, call the visitor on each thread when making
* the yieldpoint request; the purpose of the visitor is to set any additional
* fields as needed to make specific requests to the threads that yield. Note
* that the visitor's <code>visit()</code> method is called with both the
* thread's monitor held, and the <code>softHandshakeDataLock</code> held.
* <p>
* Currently we only use this mechanism for code patch isync requests on PPC,
* but this mechanism is powerful enough to be used by sliding-views style
* concurrent GC.
*
* @param v the visitor to use for the handshake
*/
@NoCheckStore
@Unpreemptible("Does not perform actions that lead to blocking, but may wait for threads to rendezvous with the soft handshake")
public static void softHandshake(SoftHandshakeVisitor v) {
handshakeLock.lockWithHandshake();
/*
* prevent multiple (soft or hard) handshakes
* from proceeding concurrently
*/
int numToHandshake = snapshotHandshakeThreads(v);
if (VM.VerifyAssertions)
VM._assert(softHandshakeLeft == 0);
// request one
for (int i = 0; i < numToHandshake; ++i) {
RVMThread t = handshakeThreads[i];
// help GC
handshakeThreads[i] = null;
t.monitor().lockNoHandshake();
boolean waitForThisThread = false;
if (!t.isAboutToTerminate && v.checkAndSignal(t)) {
// CAS the execStatus field
t.setBlockedExecStatus();
// confident that the thread's state is blocked from changing.
if (t.isInJava()) {
// the thread is currently executing Java code, so we must ensure
// that it either:
// 1) takes the next yieldpoint and rendezvous with this soft
// handshake request (see yieldpoint), or
// 2) performs the rendezvous when leaving Java code
// (see enterNativeBlocked, checkBlock, and addAboutToTerminate)
// either way, we will wait for it to get there before exiting
// this call, since the caller expects that after softHandshake()
// returns, no thread will be running Java code without having
// acknowledged.
t.softHandshakeRequested = true;
t.takeYieldpoint = 1;
waitForThisThread = true;
} else {
// the thread is not in Java code (it may be blocked or it may be
// in native), so we don't have to wait for it since it will
// do the Right Thing before returning to Java code. essentially,
// the thread cannot go back to running Java without doing whatever
// was requested because:
// A) we've set the execStatus to blocked, and
// B) we're holding its lock.
v.notifyStuckInNative(t);
}
}
t.monitor().unlock();
if (waitForThisThread) {
softHandshakeDataLock.lockNoHandshake();
softHandshakeLeft++;
softHandshakeDataLock.unlock();
}
}
// wait for all threads to reach the handshake
softHandshakeDataLock.lockNoHandshake();
if (VM.VerifyAssertions)
VM._assert(softHandshakeLeft >= 0);
while (softHandshakeLeft > 0) {
// wait and tell the world that we're off in native land. this way
// if someone tries to block us at this point (suspend() or GC),
// they'll know not to wait for us.
softHandshakeDataLock.waitWithHandshake();
}
if (VM.VerifyAssertions)
VM._assert(softHandshakeLeft == 0);
softHandshakeDataLock.unlock();
processAboutToTerminate();
handshakeLock.unlock();
}
use of org.vmmagic.pragma.Unpreemptible in project JikesRVM by JikesRVM.
the class RVMThread method hardHandshakeSuspend.
@Unpreemptible
@NoCheckStore
public static void hardHandshakeSuspend(BlockAdapter ba, HardHandshakeVisitor hhv) {
long before = sysCall.sysNanoTime();
RVMThread current = getCurrentThread();
handshakeLock.lockWithHandshake();
int numLockedLocks = 0;
for (int i = 0; i < nextSlot; ++i) {
Monitor l = communicationLockBySlot[i];
if (l != null) {
l.lockWithHandshake();
numLockedLocks++;
}
}
// while we're waiting. that is unlikely but possible.
for (; ; ) {
acctLock.lockNoHandshake();
int numToHandshake = 0;
for (int i = 0; i < numThreads; ++i) {
RVMThread t = threads[i];
if (t != current && !t.ignoreHandshakesAndGC() && hhv.includeThread(t)) {
handshakeThreads[numToHandshake++] = t;
}
}
acctLock.unlock();
for (int i = 0; i < numToHandshake; ++i) {
RVMThread t = handshakeThreads[i];
t.monitor().lockNoHandshake();
if (t.blockedFor(ba) || notRunning(t.asyncBlock(ba))) {
// already blocked or not running, remove
handshakeThreads[i--] = handshakeThreads[--numToHandshake];
// help GC
handshakeThreads[numToHandshake] = null;
}
t.monitor().unlock();
}
// terminating).
if (numToHandshake == 0)
break;
for (int i = 0; i < numToHandshake; ++i) {
RVMThread t = handshakeThreads[i];
observeExecStatusAtSTW(t.block(ba));
// help GC
handshakeThreads[i] = null;
}
}
processAboutToTerminate();
/*
* ensure that any threads that died while
* we were stopping the world notify us
* that they had stopped.
*/
int numUnlockedLocks = 0;
for (int i = 0; i < nextSlot; ++i) {
Monitor l = communicationLockBySlot[i];
if (l != null) {
l.unlock();
numUnlockedLocks++;
}
}
if (VM.VerifyAssertions)
VM._assert(numLockedLocks == numUnlockedLocks);
handshakeLock.unlock();
if (false) {
long after = sysCall.sysNanoTime();
totalSuspendTime += after - before;
VM.sysWriteln("Stopping the world took ", (after - before), " ns (", totalSuspendTime, " ns total)");
}
}
Aggregations