Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public interface AlignedHeader extends HeapChunk.Header<AlignedHeader> {

@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public static void initialize(AlignedHeader chunk, UnsignedWord chunkSize) {
assert chunk.isNonNull();
assert chunkSize.equal(HeapParameters.getAlignedHeapChunkSize()) : "expecting all aligned chunks to be the same size";
HeapChunk.initialize(chunk, AlignedHeapChunk.getObjectsStart(chunk), chunkSize);
chunk.setShouldSweepInsteadOfCompact(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
*/
package com.oracle.svm.core.genscavenge;

import jdk.graal.compiler.word.Word;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.Pointer;
Expand All @@ -36,7 +35,6 @@
import com.oracle.svm.core.genscavenge.AlignedHeapChunk.AlignedHeader;
import com.oracle.svm.core.genscavenge.HeapChunk.Header;
import com.oracle.svm.core.genscavenge.UnalignedHeapChunk.UnalignedHeader;
import com.oracle.svm.core.heap.OutOfMemoryUtil;
import com.oracle.svm.core.jdk.UninterruptibleUtils;
import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicUnsigned;
import com.oracle.svm.core.log.Log;
Expand All @@ -45,6 +43,8 @@
import com.oracle.svm.core.thread.VMThreads;
import com.oracle.svm.core.util.UnsignedUtils;

import jdk.graal.compiler.word.Word;

/**
* Allocates and frees the memory for aligned and unaligned heap chunks. The methods are
* thread-safe, so no locking is necessary when calling them.
Expand All @@ -54,10 +54,6 @@
* list. Memory for unaligned chunks is released immediately.
*/
final class HeapChunkProvider {
/** These {@link OutOfMemoryError}s are only needed for legacy code, see GR-59639. */
private static final OutOfMemoryError ALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an aligned heap chunk");
private static final OutOfMemoryError UNALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an unaligned heap chunk");

/**
* The head of the linked list of unused aligned chunks. Chunks are chained using
* {@link HeapChunk#getNext}.
Expand Down Expand Up @@ -90,10 +86,6 @@ AlignedHeader produceAlignedChunk() {
if (result.isNull()) {
/* Unused list was empty, need to allocate memory. */
result = (AlignedHeader) ChunkBasedCommittedMemoryProvider.get().allocateAlignedChunk(chunkSize, HeapParameters.getAlignedHeapChunkAlignment());
if (result.isNull()) {
throw OutOfMemoryUtil.reportOutOfMemoryError(ALIGNED_OUT_OF_MEMORY_ERROR);
}

AlignedHeapChunk.initialize(result, chunkSize);
}
assert HeapChunk.getTopOffset(result).equal(AlignedHeapChunk.getObjectsStartOffset());
Expand Down Expand Up @@ -241,10 +233,6 @@ UnalignedHeader produceUnalignedChunk(UnsignedWord objectSize) {
UnsignedWord chunkSize = UnalignedHeapChunk.getChunkSizeForObject(objectSize);

UnalignedHeader result = (UnalignedHeader) ChunkBasedCommittedMemoryProvider.get().allocateUnalignedChunk(chunkSize);
if (result.isNull()) {
throw OutOfMemoryUtil.reportOutOfMemoryError(UNALIGNED_OUT_OF_MEMORY_ERROR);
}

UnalignedHeapChunk.initialize(result, chunkSize);
assert objectSize.belowOrEqual(HeapChunk.availableObjectMemory(result)) : "UnalignedHeapChunk insufficient for requested object";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ public interface UnalignedHeader extends HeapChunk.Header<UnalignedHeader> {
}

public static void initialize(UnalignedHeader chunk, UnsignedWord chunkSize) {
assert chunk.isNonNull();
HeapChunk.initialize(chunk, UnalignedHeapChunk.getObjectStart(chunk), chunkSize);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public void unlock() {
}

@Override
@Uninterruptible(reason = "Whole critical section needs to be uninterruptible.")
@Uninterruptible(reason = "Whole critical section needs to be uninterruptible.", callerMustBe = true)
public void unlockNoTransitionUnspecifiedOwner() {
clearUnspecifiedOwner();
PthreadVMLockSupport.checkResult(Pthread.pthread_mutex_unlock(getStructPointer()), "pthread_mutex_unlock");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ public void unlock() {
}

@Override
@Uninterruptible(reason = "Whole critical section needs to be uninterruptible.")
@Uninterruptible(reason = "Whole critical section needs to be uninterruptible.", callerMustBe = true)
public void unlockNoTransitionUnspecifiedOwner() {
clearUnspecifiedOwner();
Process.NoTransitions.LeaveCriticalSection(getStructPointer());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,20 +335,9 @@ private synchronized void initializeProperty(LazySystemProperty property) {

protected abstract String osVersionValue();

protected String javaIoTmpdirValue() {
return tmpdirValue();
}

/* Should be removed, see GR-61420. */
protected String tmpdirValue() {
throw VMError.shouldNotReachHere("Subclasses must either implement javaIoTmpdirValue() or tmpdirValue().");
}
protected abstract String javaIoTmpdirValue();

/* Should be removed, see GR-61420. */
protected String javaLibraryPathValue() {
/* Fallback for platforms that don't implement this method. */
return "";
}
protected abstract String javaLibraryPathValue();

private static class LazySystemProperty {
private final String key;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,12 +125,8 @@ public void unlock() {
* Like {@linkplain #unlock()}. Only use this method if the lock was acquired via
* {@linkplain #lockNoTransitionUnspecifiedOwner()}.
*/
@Uninterruptible(reason = "Whole critical section needs to be uninterruptible.")
@Uninterruptible(reason = "Whole critical section needs to be uninterruptible.", callerMustBe = true)
public void unlockNoTransitionUnspecifiedOwner() {
/*
* Ideally, this method would be annotated with @Uninterruptible(callerMustBe = true) but
* this isn't possible because of legacy code, see GR-45784.
*/
throw VMError.shouldNotReachHere("Lock cannot be used during native image generation");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
*/
package com.oracle.svm.core.os;

import jdk.graal.compiler.word.Word;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.word.Pointer;
import org.graalvm.word.PointerBase;
Expand All @@ -37,6 +36,7 @@
import com.oracle.svm.core.thread.VMOperation;

import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.word.Word;

public abstract class ChunkBasedCommittedMemoryProvider extends AbstractCommittedMemoryProvider {
private static final OutOfMemoryError ALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an aligned heap chunk. " +
Expand All @@ -49,6 +49,7 @@ public static ChunkBasedCommittedMemoryProvider get() {
return (ChunkBasedCommittedMemoryProvider) ImageSingletons.lookup(CommittedMemoryProvider.class);
}

/** Returns a non-null value or throws a pre-allocated exception. */
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
public Pointer allocateAlignedChunk(UnsignedWord nbytes, UnsignedWord alignment) {
Pointer result = allocate(nbytes, alignment, false, NmtCategory.JavaHeap);
Expand All @@ -58,6 +59,7 @@ public Pointer allocateAlignedChunk(UnsignedWord nbytes, UnsignedWord alignment)
return result;
}

/** Returns a non-null value or throws a pre-allocated exception. */
public Pointer allocateUnalignedChunk(UnsignedWord nbytes) {
Pointer result = allocate(nbytes, getAlignmentForUnalignedChunks(), false, NmtCategory.JavaHeap);
if (result.isNull()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,9 @@ private void checkOverrides(HostedMethod method, Uninterruptible methodAnnotatio
Uninterruptible implAnnotation = Uninterruptible.Utils.getAnnotation(impl);
if (implAnnotation != null) {
if (methodAnnotation.callerMustBe() != implAnnotation.callerMustBe()) {
violations.add("callerMustBe: " + method.format("%H.%n(%p):%r") + " != " + impl.format("%H.%n(%p):%r"));
// GR-45784: temporarily disabled so that we can remove legacy code
// violations.add("callerMustBe: " + method.format("%H.%n(%p):%r") + " != " +
// impl.format("%H.%n(%p):%r"));
}
if (methodAnnotation.calleeMustBe() != implAnnotation.calleeMustBe()) {
violations.add("calleeMustBe: " + method.format("%H.%n(%p):%r") + " != " + impl.format("%H.%n(%p):%r"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;

import org.junit.Assert;
import org.junit.Test;
Expand All @@ -45,7 +46,7 @@
import jdk.jfr.consumer.RecordedEvent;

public class TestThreadCPULoadEvent extends JfrRecordingTest {
private static final int TIMEOUT = 10000;
private static final int TIMEOUT = 30000;
private static final String THREAD_NAME_1 = "Thread-1";
private static final String THREAD_NAME_2 = "Thread-2";
private static final String THREAD_NAME_3 = "Thread-3";
Expand All @@ -55,9 +56,13 @@ public void test() throws Throwable {
String[] events = new String[]{JfrEvent.ThreadCPULoad.getName()};
Recording recording = startRecording(events);

WeakReference<Thread> thread1 = createAndStartBusyWaitThread(THREAD_NAME_1, 10, 250);
WeakReference<Thread> thread2 = createAndStartBusyWaitThread(THREAD_NAME_2, 250, 10);
Thread thread3 = createAndStartBusyWaitThread(THREAD_NAME_3, 20, TIMEOUT).get();
CountDownLatch threadsStarted = new CountDownLatch(3);
WeakReference<Thread> thread1 = new WeakReference<>(createAndStartBusyWaitThread(THREAD_NAME_1, 10, 250, threadsStarted));
WeakReference<Thread> thread2 = new WeakReference<>(createAndStartBusyWaitThread(THREAD_NAME_2, 250, 10, threadsStarted));
Thread thread3 = createAndStartBusyWaitThread(THREAD_NAME_3, 20, TIMEOUT, threadsStarted);

/* Wait until all threads are started. */
threadsStarted.await();

/* For threads 1 and 2, the event is emitted when the thread exits. */
waitUntilCollected(thread1);
Expand All @@ -68,6 +73,7 @@ public void test() throws Throwable {

Assert.assertTrue(thread3.isAlive());
thread3.interrupt();
thread3.join();
}

private static void validateEvents(List<RecordedEvent> events) {
Expand All @@ -88,14 +94,15 @@ private static void validateEvents(List<RecordedEvent> events) {
assertTrue(cpuTimes.get(THREAD_NAME_1) < cpuTimes.get(THREAD_NAME_2));
}

private static WeakReference<Thread> createAndStartBusyWaitThread(String name, int busyMs, int idleMs) {
private static Thread createAndStartBusyWaitThread(String name, int busyMs, int idleMs, CountDownLatch threadsStarted) {
Thread thread = new Thread(() -> {
threadsStarted.countDown();
busyWait(busyMs);
sleep(idleMs);
});
thread.setName(name);
thread.start();
return new WeakReference<>(thread);
return thread;
}

private static void busyWait(long waitMs) {
Expand Down