use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class PosixIsolates method create.
@Uninterruptible(reason = "Thread state not yet set up.")
public static int create(WordPointer isolatePointer, @SuppressWarnings("unused") CEntryPointCreateIsolateParameters parameters) {
if (!SubstrateOptions.SpawnIsolates.getValue()) {
isolatePointer.write(CEntryPointSetup.SINGLE_ISOLATE_SENTINEL);
return Errors.NO_ERROR;
}
Word begin = IMAGE_HEAP_BEGIN.get();
Word size = IMAGE_HEAP_END.get().subtract(begin);
/*
* Request an anonymous memory mapping for this isolate's clone of the image heap. The start
* address of that mapping becomes the isolate's heap base address. We want extra heap
* chunks that we allocate later to be at a higher address than the heap base so that we can
* safely consider the base-relative offsets to be unsigned. Therefore, we request the
* lowest non-zero multiple of the page size as this mapping's address. However, that
* request is only a hint unless we use MAP_FIXED, which makes things much more complex on
* our end. Observations:
*
* - Without a hint to mmap(), anonymous mappings on Linux 4.4 (openSUSE) on x86_64 are
* created just before the mapped shared objects, and subsequent mappings are assigned
* decreasing addresses. However, specifying sysconf(_SC_PAGE_SIZE) as a hint for the first
* mapping reproducingly places it at a very low address, even before the loaded executable.
* Therefore, it seems that a number of isolates can be reliably created with their image
* heap clones at low addresses and with allocated heap chunks at higher addresses.
*
* - On Darwin 13.4, anonymous mappings are created after the mapped executable (and some
* malloc regions in between). Subsequent mappings are assigned increasing addresses that
* are close to each other. Specifying hints does not have a noticeable effect. Unmapping a
* mapping makes its address space immediately reusable. Due to the increasing addresses, a
* single isolate's heap can be safely created. However, because of the address space reuse,
* a heap chunk of an isolate can be allocated at a lower address than its heap base when
* another isolate unmaps a chunk at that location.
*/
long pageSize = Unistd.NoTransitions.sysconf(Unistd._SC_PAGE_SIZE());
Pointer heap = Mman.NoTransitions.mmap(Word.pointer(pageSize), size, PROT_READ() | PROT_WRITE(), MAP_ANON() | MAP_PRIVATE(), -1, 0);
if (heap.equal(MAP_FAILED())) {
return Errors.HEAP_CLONE_FAILED;
}
LibC.memcpy(heap, begin, size);
isolatePointer.write(heap);
return Errors.NO_ERROR;
}
use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class PosixIsolates method tearDownCurrent.
@Uninterruptible(reason = "Tear-down in progress.")
public static int tearDownCurrent() {
if (SubstrateOptions.SpawnIsolates.getValue()) {
PointerBase heapBase = getHeapBase(CEntryPointContext.getCurrentIsolate());
Word size = IMAGE_HEAP_END.get().subtract(IMAGE_HEAP_BEGIN.get());
if (Mman.NoTransitions.munmap(heapBase, size) != 0) {
return Errors.UNSPECIFIED;
}
}
return Errors.NO_ERROR;
}
use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class SafepointFeature method slowPathSafepointCheck.
/**
* Stop at a safepoint.
*/
@Uninterruptible(reason = "Must not contain safepoint checks.")
private static void slowPathSafepointCheck() {
final IsolateThread myself = CEntryPointContext.getCurrentIsolateThread();
if (VMThreads.StatusSupport.isStatusIgnoreSafepoints(myself) || VMThreads.StatusSupport.isStatusExited(myself)) {
return;
}
boolean needsCallback = ThreadingSupportImpl.singleton().needsCallbackOnSafepointCheckSlowpath();
boolean wasFrozen = false;
long callbackTime = 0;
int callbackValue = 0;
do {
IsolateThread requestingThread = Master.singleton().getRequestingThread();
if (requestingThread.isNonNull()) {
if (VMOperationControl.isLockOwner()) {
/*
* This can happen when a VM operation executes so many safepoint checks that
* safepointRequested reaches zero and enters this slow path, so we just reset
* the counter and return. The counter is re-initialized after the safepoint is
* over and normal execution continues.
*/
setSafepointRequested(myself, SafepointRequestValues.RESET);
return;
}
VMError.guarantee(requestingThread != myself, "Must be the LockOwner");
if (needsCallback && !wasFrozen) {
callbackTime = System.nanoTime();
callbackValue = getSafepointRequestedValueBeforeSafepoint(myself);
wasFrozen = true;
}
Statistics.incFrozen();
freezeAtSafepoint();
Statistics.incThawed();
}
/*
* If we entered this code as slow path for a native-to-Java transition and no safepoint
* is actually pending, we have to do the transition to Java before continuing. However,
* the CAS can fail if another thread is currently initiating a safepoint and already
* brought us into state IN_SAFEPOINT, in which case we have to start over.
*/
} while (!VMThreads.StatusSupport.isStatusJava() && !VMThreads.StatusSupport.compareAndSetNativeToJava());
if (needsCallback) {
if (!wasFrozen) {
callbackTime = System.nanoTime();
callbackValue = getSafepointRequested(myself);
// NOTE: a concurrent safepoint request can have overwritten safepointRequested
}
ThreadingSupportImpl.singleton().onSafepointCheckSlowpath(callbackTime, callbackValue);
}
}
use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class VMThreads method detachThread.
/**
* Remove a {@link IsolateThread} from the list of VMThreads. This method must be the last
* method called in every thread.
*/
@Uninterruptible(reason = "Manipulates the threads list; broadcasts on changes.")
public static void detachThread(IsolateThread vmThread) {
// Manipulating the VMThread list requires the lock for
// changing the status and for notification.
VMThreads.THREAD_MUTEX.guaranteeIsLocked("Must hold the VMThreads mutex.");
// Run down the current list and remove the given VMThread.
IsolateThread previous = nullThread();
IsolateThread current = head;
while (isNonNullThread(current)) {
IsolateThread next = nextTL.get(current);
if (current == vmThread) {
// Splice the current element out of the list.
if (isNullThread(previous)) {
head = next;
} else {
nextTL.set(previous, next);
}
break;
} else {
previous = current;
current = next;
}
}
// Signal that the VMThreads list has changed.
VMThreads.THREAD_LIST_CONDITION.broadcast();
}
use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class RestrictHeapAccessCalleesFeature method aggregateMethods.
/**
* Aggregate a set of methods that are annotated with {@link RestrictHeapAccess} or with
* {@link Uninterruptible}, or methods that are called from those methods.
*/
public void aggregateMethods(Collection<AnalysisMethod> methods) {
assert !initialized : "RestrictHeapAccessCallees.aggregateMethods: Should only initialize once.";
final Map<AnalysisMethod, RestrictionInfo> aggregation = new HashMap<>();
final MethodAggregator visitor = new MethodAggregator(aggregation, assertionErrorConstructorList);
final AnalysisMethodCalleeWalker walker = new AnalysisMethodCalleeWalker();
for (AnalysisMethod method : methods) {
final RestrictHeapAccess annotation = method.getAnnotation(RestrictHeapAccess.class);
if ((annotation != null && annotation.access() != Access.UNRESTRICTED) || method.isAnnotationPresent(Uninterruptible.class)) {
for (AnalysisMethod calleeImpl : method.getImplementations()) {
walker.walkMethod(calleeImpl, visitor);
}
}
}
calleeToCallerMap = Collections.unmodifiableMap(aggregation);
initialized = true;
}
Aggregations