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--) ;
}
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));
}
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");
}
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->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);
}
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();
}
Aggregations