Skip to content

Commit

Permalink
[GR-44810] Add an isolate data section
Browse files Browse the repository at this point in the history
PullRequest: graal/13796
  • Loading branch information
rudihorn committed Aug 7, 2023
2 parents a869fe5 + 9e6eb42 commit 39183ff
Show file tree
Hide file tree
Showing 16 changed files with 424 additions and 189 deletions.
2 changes: 2 additions & 0 deletions substratevm/mx.substratevm/suite.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@
],
"jdk.internal.vm.ci" : [
"jdk.vm.ci.code",
"jdk.vm.ci.meta",
],
},
"checkstyle": "com.oracle.svm.core",
Expand All @@ -477,6 +478,7 @@
"requiresConcealed" : {
"jdk.internal.vm.ci" : [
"jdk.vm.ci.code",
"jdk.vm.ci.meta",
],
},
"checkstyle": "com.oracle.svm.core",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ final class DarwinVMSemaphoreFeature implements InternalFeature {
private final ClassInstanceReplacer<VMSemaphore, VMSemaphore> semaphoreReplacer = new ClassInstanceReplacer<>(VMSemaphore.class) {
@Override
protected VMSemaphore createReplacement(VMSemaphore source) {
return new DarwinVMSemaphore();
return new DarwinVMSemaphore(source.getName());
}
};

Expand Down Expand Up @@ -105,7 +105,8 @@ public DarwinVMSemaphore[] getSemaphores() {
final class DarwinVMSemaphore extends VMSemaphore {

@Platforms(Platform.HOSTED_ONLY.class)
DarwinVMSemaphore() {
DarwinVMSemaphore(String name) {
super(name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,16 @@
*/
package com.oracle.svm.core.posix.linux;

import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.word.Word;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.c.struct.SizeOf;
import org.graalvm.word.UnsignedWord;
import org.graalvm.word.WordFactory;

import com.oracle.svm.core.BuildPhaseProvider.ReadyForCompilation;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.config.ObjectLayout;
import com.oracle.svm.core.BuildPhaseProvider.ReadyForCompilation;
import com.oracle.svm.core.c.CIsolateData;
import com.oracle.svm.core.c.CIsolateDataFactory;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.heap.UnknownObjectField;
Expand All @@ -47,8 +43,6 @@
import com.oracle.svm.core.posix.headers.Semaphore;
import com.oracle.svm.core.posix.pthread.PthreadVMLockSupport;

import jdk.vm.ci.meta.JavaKind;

/**
* Support of {@link VMSemaphore} in multithreaded environments on LINUX.
*/
Expand All @@ -58,7 +52,7 @@ final class LinuxVMSemaphoreFeature implements InternalFeature {
private final ClassInstanceReplacer<VMSemaphore, VMSemaphore> semaphoreReplacer = new ClassInstanceReplacer<>(VMSemaphore.class) {
@Override
protected VMSemaphore createReplacement(VMSemaphore source) {
return new LinuxVMSemaphore();
return new LinuxVMSemaphore(source.getName());
}
};

Expand All @@ -75,53 +69,18 @@ public void duringSetup(DuringSetupAccess access) {

@Override
public void beforeCompilation(BeforeCompilationAccess access) {
final int wordSize = ConfigurationValues.getTarget().wordSize;

// `alignment` should actually be: `max(alignof(pthread_mutex_t), alignof(pthread_cond_t))`.
//
// Until `alignof()` can be queried from the C compiler, we hard-code this alignment to:
// - One word on 64-bit architectures.
// - Two words on 32-bit architectures.
//
// This split is arbitrary. Actual alignment requirements depend on the architecture,
// the Pthread library implementation, and the C compiler.
// These hard-coded values will need to be adjusted to higher values if we find out
// that `pthread_mutex_t` or `pthread_cond_t` have higher alignment requirements on some
// particular architecture.
assert wordSize == 8 || wordSize == 4 : "Unsupported architecture bit width";
final int alignment = (wordSize == 8) ? wordSize : (2 * wordSize);

ObjectLayout layout = ConfigurationValues.getObjectLayout();
final int baseOffset = layout.getArrayBaseOffset(JavaKind.Byte);

// Align the first element to word boundary.
int nextIndex = NumUtil.roundUp(baseOffset, alignment) - baseOffset;

LinuxVMSemaphore[] semaphores = semaphoreReplacer.getReplacements().toArray(new LinuxVMSemaphore[0]);
int semaphoreSize = NumUtil.roundUp(SizeOf.get(Semaphore.sem_t.class), alignment);
for (LinuxVMSemaphore semaphore : semaphores) {
long offset = layout.getArrayElementOffset(JavaKind.Byte, nextIndex);
assert offset % alignment == 0;
semaphore.structOffset = WordFactory.unsigned(offset);
nextIndex += semaphoreSize;
}

LinuxVMSemaphoreSupport semaphoreSupport = (LinuxVMSemaphoreSupport) PosixVMSemaphoreSupport.singleton();
semaphoreSupport.semaphores = semaphores;
semaphoreSupport.semaphoreStructs = new byte[nextIndex];
}
}

final class LinuxVMSemaphoreSupport extends PosixVMSemaphoreSupport {

/** All semaphores, so that we can initialize them at run time when the VM starts. */
@UnknownObjectField(availability = ReadyForCompilation.class) LinuxVMSemaphore[] semaphores;

/**
* Raw memory for the semaphore lock structures. The offset into this array is stored in
* {@link LinuxVMSemaphore#structOffset}.
*/
@UnknownObjectField(availability = ReadyForCompilation.class) byte[] semaphoreStructs;
@UnknownObjectField(availability = ReadyForCompilation.class) //
LinuxVMSemaphore[] semaphores;

@Override
@Uninterruptible(reason = "Called from uninterruptible code. Too early for safepoints.")
Expand Down Expand Up @@ -150,16 +109,17 @@ public LinuxVMSemaphore[] getSemaphores() {
}

final class LinuxVMSemaphore extends VMSemaphore {
UnsignedWord structOffset;
private final CIsolateData<Semaphore.sem_t> structPointer;

@Platforms(Platform.HOSTED_ONLY.class)
LinuxVMSemaphore() {
LinuxVMSemaphore(String name) {
super(name);
structPointer = CIsolateDataFactory.createStruct("linuxSemaphore_" + name, Semaphore.sem_t.class);
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
private Semaphore.sem_t getStructPointer() {
LinuxVMSemaphoreSupport semaphoreSupport = (LinuxVMSemaphoreSupport) PosixVMSemaphoreSupport.singleton();
return (Semaphore.sem_t) Word.objectToUntrackedPointer(semaphoreSupport.semaphoreStructs).add(structOffset);
return structPointer.get();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,23 @@

import static com.oracle.svm.core.heap.RestrictHeapAccess.Access.NO_ALLOCATION;

import com.oracle.svm.core.heap.UnknownPrimitiveField;
import org.graalvm.compiler.api.replacements.Fold;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.word.Word;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.LogHandler;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.nativeimage.c.struct.SizeOf;
import org.graalvm.word.UnsignedWord;
import org.graalvm.word.WordFactory;

import com.oracle.svm.core.BuildPhaseProvider.ReadyForCompilation;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.config.ObjectLayout;
import com.oracle.svm.core.BuildPhaseProvider.ReadyForCompilation;
import com.oracle.svm.core.c.CIsolateData;
import com.oracle.svm.core.c.CIsolateDataFactory;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue;
import com.oracle.svm.core.heap.RestrictHeapAccess;

import com.oracle.svm.core.heap.UnknownObjectField;
import com.oracle.svm.core.jdk.UninterruptibleUtils;
import com.oracle.svm.core.locks.ClassInstanceReplacer;
Expand All @@ -62,8 +58,6 @@
import com.oracle.svm.core.stack.StackOverflowCheck;
import com.oracle.svm.core.thread.VMThreads.SafepointBehavior;

import jdk.vm.ci.meta.JavaKind;

/**
* Support of {@link VMMutex} and {@link VMCondition} in multi-threaded environments. Locking is
* implemented via pthreads.
Expand All @@ -81,7 +75,7 @@ protected VMMutex createReplacement(VMMutex source) {
private final ClassInstanceReplacer<VMCondition, VMCondition> conditionReplacer = new ClassInstanceReplacer<>(VMCondition.class) {
@Override
protected VMCondition createReplacement(VMCondition source) {
return new PthreadVMCondition((PthreadVMMutex) mutexReplacer.apply(source.getMutex()));
return new PthreadVMCondition((PthreadVMMutex) mutexReplacer.apply(source.getMutex()), source.getConditionName());
}
};

Expand All @@ -100,67 +94,23 @@ public void duringSetup(DuringSetupAccess access) {

@Override
public void beforeCompilation(BeforeCompilationAccess access) {
final int wordSize = ConfigurationValues.getTarget().wordSize;

// `alignment` should actually be: `max(alignof(pthread_mutex_t), alignof(pthread_cond_t))`.
//
// Until `alignof()` can be queried from the C compiler, we hard-code this alignment to:
// - One word on 64-bit architectures.
// - Two words on 32-bit architectures.
//
// This split is arbitrary. Actual alignment requirements depend on the architecture,
// the Pthread library implementation, and the C compiler.
// These hard-coded values will need to be adjusted to higher values if we find out
// that `pthread_mutex_t` or `pthread_cond_t` have higher alignment requirements on some
// particular architecture.
assert wordSize == 8 || wordSize == 4 : "Unsupported architecture bit width";
final int alignment = (wordSize == 8) ? wordSize : (2 * wordSize);

ObjectLayout layout = ConfigurationValues.getObjectLayout();
final int baseOffset = layout.getArrayBaseOffset(JavaKind.Byte);

// Align the first element to word boundary.
int nextIndex = NumUtil.roundUp(baseOffset, alignment) - baseOffset;

PthreadVMMutex[] mutexes = mutexReplacer.getReplacements().toArray(new PthreadVMMutex[0]);
int mutexSize = NumUtil.roundUp(SizeOf.get(Pthread.pthread_mutex_t.class), alignment);
for (PthreadVMMutex mutex : mutexes) {
long offset = layout.getArrayElementOffset(JavaKind.Byte, nextIndex);
assert offset % alignment == 0;
mutex.structOffset = WordFactory.unsigned(offset);
nextIndex += mutexSize;
}

PthreadVMCondition[] conditions = conditionReplacer.getReplacements().toArray(new PthreadVMCondition[0]);
int conditionSize = NumUtil.roundUp(SizeOf.get(Pthread.pthread_cond_t.class), alignment);
for (PthreadVMCondition condition : conditions) {
long offset = layout.getArrayElementOffset(JavaKind.Byte, nextIndex);
assert offset % alignment == 0;
condition.structOffset = WordFactory.unsigned(offset);
nextIndex += conditionSize;
}

PthreadVMLockSupport lockSupport = PthreadVMLockSupport.singleton();
lockSupport.mutexes = mutexes;
lockSupport.conditions = conditions;
lockSupport.pthreadStructs = new byte[nextIndex];
}
}

public final class PthreadVMLockSupport extends VMLockSupport {
/** All mutexes, so that we can initialize them at run time when the VM starts. */
@UnknownObjectField(availability = ReadyForCompilation.class) PthreadVMMutex[] mutexes;
@UnknownObjectField(availability = ReadyForCompilation.class) //
PthreadVMMutex[] mutexes;

/** All conditions, so that we can initialize them at run time when the VM starts. */
@UnknownObjectField(availability = ReadyForCompilation.class) PthreadVMCondition[] conditions;

/**
* Raw memory for the pthread lock structures. Since we know that native image objects are never
* moved, we can safely hand out pointers into the middle of this array to C code. The offset
* into this array is stored in {@link PthreadVMMutex#structOffset} and
* {@link PthreadVMCondition#structOffset}.
*/
@UnknownObjectField(availability = ReadyForCompilation.class) byte[] pthreadStructs;
@UnknownObjectField(availability = ReadyForCompilation.class) //
PthreadVMCondition[] conditions;

@Fold
public static PthreadVMLockSupport singleton() {
Expand Down Expand Up @@ -227,17 +177,17 @@ public VMSemaphore[] getSemaphores() {

final class PthreadVMMutex extends VMMutex {

@UnknownPrimitiveField(availability = ReadyForCompilation.class)//
UnsignedWord structOffset;
private final CIsolateData<Pthread.pthread_mutex_t> structPointer;

@Platforms(Platform.HOSTED_ONLY.class)
PthreadVMMutex(String name) {
super(name);
structPointer = CIsolateDataFactory.createStruct("pthreadMutex_" + name, Pthread.pthread_mutex_t.class);
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
Pthread.pthread_mutex_t getStructPointer() {
return (Pthread.pthread_mutex_t) Word.objectToUntrackedPointer(PthreadVMLockSupport.singleton().pthreadStructs).add(structOffset);
return structPointer.get();
}

@Override
Expand Down Expand Up @@ -280,17 +230,16 @@ public void unlockNoTransitionUnspecifiedOwner() {

final class PthreadVMCondition extends VMCondition {

@UnknownPrimitiveField(availability = ReadyForCompilation.class)//
UnsignedWord structOffset;
private final CIsolateData<Pthread.pthread_cond_t> structPointer;

@Platforms(Platform.HOSTED_ONLY.class)
PthreadVMCondition(PthreadVMMutex mutex) {
super(mutex);
PthreadVMCondition(PthreadVMMutex mutex, String name) {
super(mutex, name);
structPointer = CIsolateDataFactory.createStruct("pthreadCondition_" + getName(), Pthread.pthread_cond_t.class);
}

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
Pthread.pthread_cond_t getStructPointer() {
return (Pthread.pthread_cond_t) Word.objectToUntrackedPointer(PthreadVMLockSupport.singleton().pthreadStructs).add(structOffset);
return structPointer.get();
}

@Override
Expand Down
Loading

0 comments on commit 39183ff

Please sign in to comment.