Skip to content
Merged
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 @@ -26,8 +26,6 @@

import java.util.concurrent.atomic.AtomicBoolean;

import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.nodes.PauseNode;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
import org.graalvm.word.UnsignedWord;
Expand All @@ -42,6 +40,9 @@
import com.oracle.svm.core.util.UnsignedUtils;
import com.oracle.svm.core.util.VMError;

import jdk.graal.compiler.api.replacements.Fold;
import jdk.graal.compiler.nodes.PauseNode;

abstract class AbstractCollectionPolicy implements CollectionPolicy {

protected static final int MIN_SPACE_SIZE_IN_ALIGNED_CHUNKS = 8;
Expand Down Expand Up @@ -326,10 +327,8 @@ protected SizeParameters computeSizeParameters(SizeParameters existing) {
long optionMax = SubstrateGCOptions.MaxHeapSize.getValue();
if (optionMax > 0L) {
maxHeap = WordFactory.unsigned(optionMax);
} else if (!PhysicalMemory.isInitialized()) {
maxHeap = addressSpaceSize;
} else {
maxHeap = PhysicalMemory.getCachedSize().unsignedDivide(100).multiply(HeapParameters.getMaximumHeapSizePercent());
maxHeap = PhysicalMemory.size().unsignedDivide(100).multiply(HeapParameters.getMaximumHeapSizePercent());
}
UnsignedWord unadjustedMaxHeap = maxHeap;
maxHeap = UnsignedUtils.clamp(alignDown(maxHeap), minAllSpaces, alignDown(addressSpaceSize));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,14 +105,12 @@ public final UnsignedWord getMaximumHeapSize() {
* size of the physical memory.
*/
UnsignedWord addressSpaceSize = ReferenceAccess.singleton().getAddressSpaceSize();
if (PhysicalMemory.isInitialized()) {
UnsignedWord physicalMemorySize = PhysicalMemory.getCachedSize();
int maximumHeapSizePercent = HeapParameters.getMaximumHeapSizePercent();
/* Do not cache because `-Xmx` option parsing may not have happened yet. */
UnsignedWord result = physicalMemorySize.unsignedDivide(100).multiply(maximumHeapSizePercent);
if (result.belowThan(addressSpaceSize)) {
return result;
}
UnsignedWord physicalMemorySize = PhysicalMemory.size();
int maximumHeapSizePercent = HeapParameters.getMaximumHeapSizePercent();
/* Do not cache because `-Xmx` option parsing may not have happened yet. */
UnsignedWord result = physicalMemorySize.unsignedDivide(100).multiply(maximumHeapSizePercent);
if (result.belowThan(addressSpaceSize)) {
return result;
}
return addressSpaceSize;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,11 +402,7 @@ private void printGCBefore(GCCause cause) {
if (getCollectionEpoch().equal(0)) {
printGCPrefixAndTime().string("Using ").string(getName()).newline();
Log log = printGCPrefixAndTime().spaces(2).string("Memory: ");
if (!PhysicalMemory.isInitialized()) {
log.string("unknown").newline();
} else {
log.rational(PhysicalMemory.getCachedSize(), M, 0).string("M").newline();
}
log.rational(PhysicalMemory.size(), M, 0).string("M").newline();
printGCPrefixAndTime().spaces(2).string("Heap policy: ").string(getPolicy().getName()).newline();
printGCPrefixAndTime().spaces(2).string("Maximum young generation size: ").rational(getPolicy().getMaximumYoungGenerationSize(), M, 0).string("M").newline();
printGCPrefixAndTime().spaces(2).string("Maximum heap size: ").rational(getPolicy().getMaximumHeapSize(), M, 0).string("M").newline();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,28 @@
*/
package com.oracle.svm.core.posix.linux;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

import org.graalvm.word.UnsignedWord;
import org.graalvm.word.WordFactory;

import com.oracle.svm.core.container.Container;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.heap.PhysicalMemory;
import com.oracle.svm.core.heap.PhysicalMemory.PhysicalMemorySupport;
import com.oracle.svm.core.posix.headers.Unistd;
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
import com.oracle.svm.core.util.VMError;

@AutomaticallyRegisteredImageSingleton(PhysicalMemorySupport.class)
class LinuxPhysicalMemorySupportImpl implements PhysicalMemorySupport {

private static final long K = 1024;

@Override
public UnsignedWord size() {
long numberOfPhysicalMemoryPages = Unistd.sysconf(Unistd._SC_PHYS_PAGES());
Expand All @@ -44,4 +55,63 @@ public UnsignedWord size() {
}
return WordFactory.unsigned(numberOfPhysicalMemoryPages).multiply(WordFactory.unsigned(sizeOfAPhysicalMemoryPage));
}

@Override
public long usedSize() {
/*
* Note: we use getCachedMemoryLimitInBytes() because we don't want to mutate the state, and
* we assume that the memory limits have be queried before calling this method.
*/
assert !(Container.singleton().isContainerized() && Container.singleton().getCachedMemoryLimitInBytes() > 0) : "Should be using OperatingSystemMXBean";
/* Non-containerized Linux uses /proc/meminfo. */
return getUsedSizeFromProcMemInfo();
}

private static long getUsedSizeFromProcMemInfo() {
try {
List<String> lines = readAllLines("/proc/meminfo");
for (String line : lines) {
if (line.contains("MemAvailable")) {
return PhysicalMemory.size().rawValue() - parseFirstNumber(line) * K;
}
}
} catch (Exception e) {
/* Nothing to do. */
}
return -1L;
}

private static List<String> readAllLines(String fileName) throws IOException {
List<String> lines = new ArrayList<>();
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(fileName, StandardCharsets.UTF_8))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
lines.add(line);
}
}
return lines;
}

/** Parses the first number in the String as a long value. */
private static long parseFirstNumber(String str) {
int firstDigit = -1;
int lastDigit = -1;

for (int i = 0; i < str.length(); i++) {
if (Character.isDigit(str.charAt(i))) {
if (firstDigit == -1) {
firstDigit = i;
}
lastDigit = i;
} else if (firstDigit != -1) {
break;
}
}

if (firstDigit >= 0) {
String number = str.substring(firstDigit, lastDigit + 1);
return Long.parseLong(number);
}
return -1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
@AutomaticallyRegisteredImageSingleton
public class IsolateArgumentParser {
private static final RuntimeOptionKey<?>[] OPTIONS = {SubstrateGCOptions.MinHeapSize, SubstrateGCOptions.MaxHeapSize, SubstrateGCOptions.MaxNewSize, SubstrateGCOptions.ReservedAddressSpaceSize,
SubstrateOptions.ConcealedOptions.AutomaticReferenceHandling, SubstrateOptions.ConcealedOptions.UsePerfData};
SubstrateOptions.ConcealedOptions.AutomaticReferenceHandling, SubstrateOptions.ConcealedOptions.UsePerfData, SubstrateOptions.MaxRAM};
private static final int OPTION_COUNT = OPTIONS.length;
private static final CGlobalData<CCharPointer> OPTION_NAMES = CGlobalDataFactory.createBytes(IsolateArgumentParser::createOptionNames);
private static final CGlobalData<CIntPointer> OPTION_NAME_POSITIONS = CGlobalDataFactory.createBytes(IsolateArgumentParser::createOptionNamePosition);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -506,15 +506,6 @@ private static boolean pointsIntoNativeImageCode(CodePointer possibleIp) {
return CodeInfoTable.lookupCodeInfo(possibleIp).isNonNull();
}

private static boolean isContainerized() {
boolean allowInit = !SubstrateOptions.AsyncSignalSafeDiagnostics.getValue();
if (Container.singleton().isInitialized() || allowInit) {
return Container.singleton().isContainerized();
}
// uninitialized and initialization not allowed
return false;
}

public static class FatalErrorState {
AtomicWord<IsolateThread> diagnosticThread;
volatile int diagnosticThunkIndex;
Expand Down Expand Up @@ -864,7 +855,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
Platform platform = ImageSingletons.lookup(Platform.class);
log.string("Platform: ").string(platform.getOS()).string("/").string(platform.getArchitecture()).newline();
log.string("Page size: ").unsigned(SubstrateOptions.getPageSize()).newline();
log.string("Containerized: ").string(Container.singleton().isInitialized() ? String.valueOf(isContainerized()) : "unknown").newline();
log.string("Containerized: ").string(String.valueOf(Container.singleton().isContainerized())).newline();
log.string("CPU features used for AOT compiled code: ").string(getBuildTimeCpuFeatures()).newline();
log.indent(false);
}
Expand All @@ -886,7 +877,7 @@ public int maxInvocationCount() {
public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLevel, int invocationCount) {
log.string("Runtime information:").indent(true);

if (isContainerized()) {
if (Container.singleton().isContainerized()) {
log.string("CPU cores (container): ");
int processorCount = getContainerActiveProcessorCount();
if (processorCount > 0) {
Expand All @@ -904,7 +895,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
log.string("unknown").newline();
}

if (isContainerized()) {
if (Container.singleton().isContainerized()) {
log.string("Memory (container): ");
UnsignedWord memory = getContainerPhysicalMemory();
if (memory.aboveThan(0)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,8 @@ public static Container singleton() {
return ImageSingletons.lookup(Container.class);
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean isInitialized() {
return STATE.get().readWord(0) != State.UNINITIALIZED;
}

/**
* Determines whether the image runs containerized, potentially initializing container support
* if not yet initialized. If initialization is not desired, calls to this method must be
* guarded by {@link #isInitialized()}.
* Determines whether the image runs containerized.
*/
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public boolean isContainerized() {
Expand All @@ -90,16 +83,15 @@ public boolean isContainerized() {
}

UnsignedWord value = STATE.get().readWord(0);
if (value == State.UNINITIALIZED) {
value = initialize();
}

assert value == State.CONTAINERIZED || value == State.NOT_CONTAINERIZED;
return value == State.CONTAINERIZED;
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
private static UnsignedWord initialize() {
public static void initialize() {
if (!isSupported()) {
return;
}
Pointer statePtr = STATE.get();
UnsignedWord value = statePtr.compareAndSwapWord(0, State.UNINITIALIZED, State.INITIALIZING, LocationIdentity.ANY_LOCATION);
if (value == State.UNINITIALIZED) {
Expand All @@ -126,12 +118,11 @@ private static UnsignedWord initialize() {
VMError.guarantee(value != State.ERROR_LIBCONTAINER_TOO_OLD, "native-image tries to use a libsvm_container version that is too old");
VMError.guarantee(value != State.ERROR_LIBCONTAINER_TOO_NEW, "native-image tries to use a libsvm_container version that is too new");
VMError.guarantee(value == State.CONTAINERIZED || value == State.NOT_CONTAINERIZED, "unexpected libsvm_container initialize result");
return value;
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public int getActiveProcessorCount() {
VMError.guarantee(isInitialized() && isContainerized());
VMError.guarantee(isContainerized());

long currentMs = System.currentTimeMillis();
if (currentMs > activeProcessorCountTimeoutMs) {
Expand All @@ -143,13 +134,13 @@ public int getActiveProcessorCount() {

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public int getCachedActiveProcessorCount() {
VMError.guarantee(isInitialized() && isContainerized());
VMError.guarantee(isContainerized());
return cachedActiveProcessorCount;
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public UnsignedWord getPhysicalMemory() {
VMError.guarantee(isInitialized() && isContainerized());
VMError.guarantee(isContainerized());

long currentMs = System.currentTimeMillis();
if (currentMs > physicalMemoryTimeoutMs) {
Expand All @@ -161,13 +152,13 @@ public UnsignedWord getPhysicalMemory() {

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public UnsignedWord getCachedPhysicalMemory() {
VMError.guarantee(isInitialized() && isContainerized());
VMError.guarantee(isContainerized());
return cachedPhysicalMemorySize;
}

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public long getMemoryLimitInBytes() {
VMError.guarantee(isInitialized() && isContainerized());
VMError.guarantee(isContainerized());

long currentMs = System.currentTimeMillis();
if (currentMs > memoryLimitInBytesTimeoutMs) {
Expand All @@ -179,7 +170,7 @@ public long getMemoryLimitInBytes() {

@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
public long getCachedMemoryLimitInBytes() {
VMError.guarantee(isInitialized() && isContainerized());
VMError.guarantee(isContainerized());
return cachedMemoryLimitInBytes;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import com.oracle.svm.core.c.function.CEntryPointErrors;
import com.oracle.svm.core.c.function.CEntryPointNativeFunctions;
import com.oracle.svm.core.code.CodeInfoTable;
import com.oracle.svm.core.container.Container;
import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider;
import com.oracle.svm.core.graal.nodes.CEntryPointEnterNode;
import com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode;
Expand Down Expand Up @@ -231,6 +232,7 @@ private static int createIsolate(CEntryPointCreateIsolateParameters providedPara
if (parameters.reservedSpaceSize().equal(0)) {
parameters.setReservedSpaceSize(WordFactory.unsigned(parsedArgs.read(IsolateArgumentParser.getOptionIndex(SubstrateGCOptions.ReservedAddressSpaceSize))));
}
Container.initialize();

WordPointer isolatePtr = StackValue.get(WordPointer.class);
int error = Isolates.create(isolatePtr, parameters);
Expand Down Expand Up @@ -309,6 +311,12 @@ private static int initializeIsolateInterruptibly0(CEntryPointCreateIsolateParam

@NeverInline("GR-24649")
private static int initializeIsolateInterruptibly1(CEntryPointCreateIsolateParameters parameters) {
/*
* Initialize the physical memory size. This must be done as early as possible because we
* must not trigger GC before PhysicalMemory is initialized.
*/
PhysicalMemory.initialize();

/*
* The VM operation thread must be started early as no VM operations can be scheduled before
* this thread is fully started. The isolate teardown may also use VM operations.
Expand Down Expand Up @@ -388,9 +396,6 @@ private static int initializeIsolateInterruptibly1(CEntryPointCreateIsolateParam
/* Adjust stack overflow boundary of main thread. */
StackOverflowCheck.singleton().updateStackOverflowBoundary();

/* Initialize the physical memory size. */
PhysicalMemory.size();

assert !isolateInitialized;
isolateInitialized = true;

Expand Down
Loading