Skip to content

Commit bb0af71

Browse files
committed
[GR-53451] Eagerly initialize libsvm_container
PullRequest: graal/18521
2 parents 1ff744c + 6a26167 commit bb0af71

File tree

11 files changed

+136
-129
lines changed

11 files changed

+136
-129
lines changed

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@
2626

2727
import java.util.concurrent.atomic.AtomicBoolean;
2828

29-
import jdk.graal.compiler.api.replacements.Fold;
30-
import jdk.graal.compiler.nodes.PauseNode;
3129
import org.graalvm.nativeimage.Platform;
3230
import org.graalvm.nativeimage.Platforms;
3331
import org.graalvm.word.UnsignedWord;
@@ -42,6 +40,9 @@
4240
import com.oracle.svm.core.util.UnsignedUtils;
4341
import com.oracle.svm.core.util.VMError;
4442

43+
import jdk.graal.compiler.api.replacements.Fold;
44+
import jdk.graal.compiler.nodes.PauseNode;
45+
4546
abstract class AbstractCollectionPolicy implements CollectionPolicy {
4647

4748
protected static final int MIN_SPACE_SIZE_IN_ALIGNED_CHUNKS = 8;
@@ -326,10 +327,8 @@ protected SizeParameters computeSizeParameters(SizeParameters existing) {
326327
long optionMax = SubstrateGCOptions.MaxHeapSize.getValue();
327328
if (optionMax > 0L) {
328329
maxHeap = WordFactory.unsigned(optionMax);
329-
} else if (!PhysicalMemory.isInitialized()) {
330-
maxHeap = addressSpaceSize;
331330
} else {
332-
maxHeap = PhysicalMemory.getCachedSize().unsignedDivide(100).multiply(HeapParameters.getMaximumHeapSizePercent());
331+
maxHeap = PhysicalMemory.size().unsignedDivide(100).multiply(HeapParameters.getMaximumHeapSizePercent());
333332
}
334333
UnsignedWord unadjustedMaxHeap = maxHeap;
335334
maxHeap = UnsignedUtils.clamp(alignDown(maxHeap), minAllSpaces, alignDown(addressSpaceSize));

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,12 @@ public final UnsignedWord getMaximumHeapSize() {
105105
* size of the physical memory.
106106
*/
107107
UnsignedWord addressSpaceSize = ReferenceAccess.singleton().getAddressSpaceSize();
108-
if (PhysicalMemory.isInitialized()) {
109-
UnsignedWord physicalMemorySize = PhysicalMemory.getCachedSize();
110-
int maximumHeapSizePercent = HeapParameters.getMaximumHeapSizePercent();
111-
/* Do not cache because `-Xmx` option parsing may not have happened yet. */
112-
UnsignedWord result = physicalMemorySize.unsignedDivide(100).multiply(maximumHeapSizePercent);
113-
if (result.belowThan(addressSpaceSize)) {
114-
return result;
115-
}
108+
UnsignedWord physicalMemorySize = PhysicalMemory.size();
109+
int maximumHeapSizePercent = HeapParameters.getMaximumHeapSizePercent();
110+
/* Do not cache because `-Xmx` option parsing may not have happened yet. */
111+
UnsignedWord result = physicalMemorySize.unsignedDivide(100).multiply(maximumHeapSizePercent);
112+
if (result.belowThan(addressSpaceSize)) {
113+
return result;
116114
}
117115
return addressSpaceSize;
118116
}

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -402,11 +402,7 @@ private void printGCBefore(GCCause cause) {
402402
if (getCollectionEpoch().equal(0)) {
403403
printGCPrefixAndTime().string("Using ").string(getName()).newline();
404404
Log log = printGCPrefixAndTime().spaces(2).string("Memory: ");
405-
if (!PhysicalMemory.isInitialized()) {
406-
log.string("unknown").newline();
407-
} else {
408-
log.rational(PhysicalMemory.getCachedSize(), M, 0).string("M").newline();
409-
}
405+
log.rational(PhysicalMemory.size(), M, 0).string("M").newline();
410406
printGCPrefixAndTime().spaces(2).string("Heap policy: ").string(getPolicy().getName()).newline();
411407
printGCPrefixAndTime().spaces(2).string("Maximum young generation size: ").rational(getPolicy().getMaximumYoungGenerationSize(), M, 0).string("M").newline();
412408
printGCPrefixAndTime().spaces(2).string("Maximum heap size: ").rational(getPolicy().getMaximumHeapSize(), M, 0).string("M").newline();

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxPhysicalMemorySupportImpl.java

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,28 @@
2424
*/
2525
package com.oracle.svm.core.posix.linux;
2626

27+
import java.io.BufferedReader;
28+
import java.io.FileReader;
29+
import java.io.IOException;
30+
import java.nio.charset.StandardCharsets;
31+
import java.util.ArrayList;
32+
import java.util.List;
33+
2734
import org.graalvm.word.UnsignedWord;
2835
import org.graalvm.word.WordFactory;
2936

37+
import com.oracle.svm.core.container.Container;
38+
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
39+
import com.oracle.svm.core.heap.PhysicalMemory;
3040
import com.oracle.svm.core.heap.PhysicalMemory.PhysicalMemorySupport;
3141
import com.oracle.svm.core.posix.headers.Unistd;
32-
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
3342
import com.oracle.svm.core.util.VMError;
3443

3544
@AutomaticallyRegisteredImageSingleton(PhysicalMemorySupport.class)
3645
class LinuxPhysicalMemorySupportImpl implements PhysicalMemorySupport {
3746

47+
private static final long K = 1024;
48+
3849
@Override
3950
public UnsignedWord size() {
4051
long numberOfPhysicalMemoryPages = Unistd.sysconf(Unistd._SC_PHYS_PAGES());
@@ -44,4 +55,63 @@ public UnsignedWord size() {
4455
}
4556
return WordFactory.unsigned(numberOfPhysicalMemoryPages).multiply(WordFactory.unsigned(sizeOfAPhysicalMemoryPage));
4657
}
58+
59+
@Override
60+
public long usedSize() {
61+
/*
62+
* Note: we use getCachedMemoryLimitInBytes() because we don't want to mutate the state, and
63+
* we assume that the memory limits have be queried before calling this method.
64+
*/
65+
assert !(Container.singleton().isContainerized() && Container.singleton().getCachedMemoryLimitInBytes() > 0) : "Should be using OperatingSystemMXBean";
66+
/* Non-containerized Linux uses /proc/meminfo. */
67+
return getUsedSizeFromProcMemInfo();
68+
}
69+
70+
private static long getUsedSizeFromProcMemInfo() {
71+
try {
72+
List<String> lines = readAllLines("/proc/meminfo");
73+
for (String line : lines) {
74+
if (line.contains("MemAvailable")) {
75+
return PhysicalMemory.size().rawValue() - parseFirstNumber(line) * K;
76+
}
77+
}
78+
} catch (Exception e) {
79+
/* Nothing to do. */
80+
}
81+
return -1L;
82+
}
83+
84+
private static List<String> readAllLines(String fileName) throws IOException {
85+
List<String> lines = new ArrayList<>();
86+
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(fileName, StandardCharsets.UTF_8))) {
87+
String line;
88+
while ((line = bufferedReader.readLine()) != null) {
89+
lines.add(line);
90+
}
91+
}
92+
return lines;
93+
}
94+
95+
/** Parses the first number in the String as a long value. */
96+
private static long parseFirstNumber(String str) {
97+
int firstDigit = -1;
98+
int lastDigit = -1;
99+
100+
for (int i = 0; i < str.length(); i++) {
101+
if (Character.isDigit(str.charAt(i))) {
102+
if (firstDigit == -1) {
103+
firstDigit = i;
104+
}
105+
lastDigit = i;
106+
} else if (firstDigit != -1) {
107+
break;
108+
}
109+
}
110+
111+
if (firstDigit >= 0) {
112+
String number = str.substring(firstDigit, lastDigit + 1);
113+
return Long.parseLong(number);
114+
}
115+
return -1;
116+
}
47117
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/IsolateArgumentParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
@AutomaticallyRegisteredImageSingleton
5757
public class IsolateArgumentParser {
5858
private static final RuntimeOptionKey<?>[] OPTIONS = {SubstrateGCOptions.MinHeapSize, SubstrateGCOptions.MaxHeapSize, SubstrateGCOptions.MaxNewSize, SubstrateGCOptions.ReservedAddressSpaceSize,
59-
SubstrateOptions.ConcealedOptions.AutomaticReferenceHandling, SubstrateOptions.ConcealedOptions.UsePerfData};
59+
SubstrateOptions.ConcealedOptions.AutomaticReferenceHandling, SubstrateOptions.ConcealedOptions.UsePerfData, SubstrateOptions.MaxRAM};
6060
private static final int OPTION_COUNT = OPTIONS.length;
6161
private static final CGlobalData<CCharPointer> OPTION_NAMES = CGlobalDataFactory.createBytes(IsolateArgumentParser::createOptionNames);
6262
private static final CGlobalData<CIntPointer> OPTION_NAME_POSITIONS = CGlobalDataFactory.createBytes(IsolateArgumentParser::createOptionNamePosition);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateDiagnostics.java

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -506,15 +506,6 @@ private static boolean pointsIntoNativeImageCode(CodePointer possibleIp) {
506506
return CodeInfoTable.lookupCodeInfo(possibleIp).isNonNull();
507507
}
508508

509-
private static boolean isContainerized() {
510-
boolean allowInit = !SubstrateOptions.AsyncSignalSafeDiagnostics.getValue();
511-
if (Container.singleton().isInitialized() || allowInit) {
512-
return Container.singleton().isContainerized();
513-
}
514-
// uninitialized and initialization not allowed
515-
return false;
516-
}
517-
518509
public static class FatalErrorState {
519510
AtomicWord<IsolateThread> diagnosticThread;
520511
volatile int diagnosticThunkIndex;
@@ -864,7 +855,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
864855
Platform platform = ImageSingletons.lookup(Platform.class);
865856
log.string("Platform: ").string(platform.getOS()).string("/").string(platform.getArchitecture()).newline();
866857
log.string("Page size: ").unsigned(SubstrateOptions.getPageSize()).newline();
867-
log.string("Containerized: ").string(Container.singleton().isInitialized() ? String.valueOf(isContainerized()) : "unknown").newline();
858+
log.string("Containerized: ").string(String.valueOf(Container.singleton().isContainerized())).newline();
868859
log.string("CPU features used for AOT compiled code: ").string(getBuildTimeCpuFeatures()).newline();
869860
log.indent(false);
870861
}
@@ -886,7 +877,7 @@ public int maxInvocationCount() {
886877
public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLevel, int invocationCount) {
887878
log.string("Runtime information:").indent(true);
888879

889-
if (isContainerized()) {
880+
if (Container.singleton().isContainerized()) {
890881
log.string("CPU cores (container): ");
891882
int processorCount = getContainerActiveProcessorCount();
892883
if (processorCount > 0) {
@@ -904,7 +895,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
904895
log.string("unknown").newline();
905896
}
906897

907-
if (isContainerized()) {
898+
if (Container.singleton().isContainerized()) {
908899
log.string("Memory (container): ");
909900
UnsignedWord memory = getContainerPhysicalMemory();
910901
if (memory.aboveThan(0)) {

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/Container.java

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,8 @@ public static Container singleton() {
7373
return ImageSingletons.lookup(Container.class);
7474
}
7575

76-
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
77-
public boolean isInitialized() {
78-
return STATE.get().readWord(0) != State.UNINITIALIZED;
79-
}
80-
8176
/**
82-
* Determines whether the image runs containerized, potentially initializing container support
83-
* if not yet initialized. If initialization is not desired, calls to this method must be
84-
* guarded by {@link #isInitialized()}.
77+
* Determines whether the image runs containerized.
8578
*/
8679
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
8780
public boolean isContainerized() {
@@ -90,16 +83,15 @@ public boolean isContainerized() {
9083
}
9184

9285
UnsignedWord value = STATE.get().readWord(0);
93-
if (value == State.UNINITIALIZED) {
94-
value = initialize();
95-
}
96-
9786
assert value == State.CONTAINERIZED || value == State.NOT_CONTAINERIZED;
9887
return value == State.CONTAINERIZED;
9988
}
10089

10190
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
102-
private static UnsignedWord initialize() {
91+
public static void initialize() {
92+
if (!isSupported()) {
93+
return;
94+
}
10395
Pointer statePtr = STATE.get();
10496
UnsignedWord value = statePtr.compareAndSwapWord(0, State.UNINITIALIZED, State.INITIALIZING, LocationIdentity.ANY_LOCATION);
10597
if (value == State.UNINITIALIZED) {
@@ -126,12 +118,11 @@ private static UnsignedWord initialize() {
126118
VMError.guarantee(value != State.ERROR_LIBCONTAINER_TOO_OLD, "native-image tries to use a libsvm_container version that is too old");
127119
VMError.guarantee(value != State.ERROR_LIBCONTAINER_TOO_NEW, "native-image tries to use a libsvm_container version that is too new");
128120
VMError.guarantee(value == State.CONTAINERIZED || value == State.NOT_CONTAINERIZED, "unexpected libsvm_container initialize result");
129-
return value;
130121
}
131122

132123
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
133124
public int getActiveProcessorCount() {
134-
VMError.guarantee(isInitialized() && isContainerized());
125+
VMError.guarantee(isContainerized());
135126

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

144135
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
145136
public int getCachedActiveProcessorCount() {
146-
VMError.guarantee(isInitialized() && isContainerized());
137+
VMError.guarantee(isContainerized());
147138
return cachedActiveProcessorCount;
148139
}
149140

150141
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
151142
public UnsignedWord getPhysicalMemory() {
152-
VMError.guarantee(isInitialized() && isContainerized());
143+
VMError.guarantee(isContainerized());
153144

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

162153
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
163154
public UnsignedWord getCachedPhysicalMemory() {
164-
VMError.guarantee(isInitialized() && isContainerized());
155+
VMError.guarantee(isContainerized());
165156
return cachedPhysicalMemorySize;
166157
}
167158

168159
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
169160
public long getMemoryLimitInBytes() {
170-
VMError.guarantee(isInitialized() && isContainerized());
161+
VMError.guarantee(isContainerized());
171162

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

180171
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
181172
public long getCachedMemoryLimitInBytes() {
182-
VMError.guarantee(isInitialized() && isContainerized());
173+
VMError.guarantee(isContainerized());
183174
return cachedMemoryLimitInBytes;
184175
}
185176

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import com.oracle.svm.core.c.function.CEntryPointErrors;
6666
import com.oracle.svm.core.c.function.CEntryPointNativeFunctions;
6767
import com.oracle.svm.core.code.CodeInfoTable;
68+
import com.oracle.svm.core.container.Container;
6869
import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider;
6970
import com.oracle.svm.core.graal.nodes.CEntryPointEnterNode;
7071
import com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode;
@@ -231,6 +232,7 @@ private static int createIsolate(CEntryPointCreateIsolateParameters providedPara
231232
if (parameters.reservedSpaceSize().equal(0)) {
232233
parameters.setReservedSpaceSize(WordFactory.unsigned(parsedArgs.read(IsolateArgumentParser.getOptionIndex(SubstrateGCOptions.ReservedAddressSpaceSize))));
233234
}
235+
Container.initialize();
234236

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

310312
@NeverInline("GR-24649")
311313
private static int initializeIsolateInterruptibly1(CEntryPointCreateIsolateParameters parameters) {
314+
/*
315+
* Initialize the physical memory size. This must be done as early as possible because we
316+
* must not trigger GC before PhysicalMemory is initialized.
317+
*/
318+
PhysicalMemory.initialize();
319+
312320
/*
313321
* The VM operation thread must be started early as no VM operations can be scheduled before
314322
* this thread is fully started. The isolate teardown may also use VM operations.
@@ -388,9 +396,6 @@ private static int initializeIsolateInterruptibly1(CEntryPointCreateIsolateParam
388396
/* Adjust stack overflow boundary of main thread. */
389397
StackOverflowCheck.singleton().updateStackOverflowBoundary();
390398

391-
/* Initialize the physical memory size. */
392-
PhysicalMemory.size();
393-
394399
assert !isolateInitialized;
395400
isolateInitialized = true;
396401

0 commit comments

Comments
 (0)