From 4f89acc640409f656255d42d376a485695e738de Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Wed, 13 Sep 2023 15:54:00 +0300 Subject: [PATCH] Fix race in initializing state --- .../oracle/svm/core/heap/PhysicalMemory.java | 65 +++++++++---------- 1 file changed, 32 insertions(+), 33 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/PhysicalMemory.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/PhysicalMemory.java index 799374a0a0ba..cafd44f44c5a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/PhysicalMemory.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/PhysicalMemory.java @@ -86,43 +86,42 @@ public static UnsignedWord size() { throw VMError.shouldNotReachHere("Accessing the physical memory size may require allocation and synchronization"); } - int initState = INITIALIZATION_STATE.get(); - if (initState != INITIALIZED) { - if (initState == INITIALIZING) { - /* - * Recursive initializations need to wait for the one initializing thread to - * finish so as to get correct reads of the cachedSize value. - */ - try { - boolean expired = !CACHED_SIZE_AVAIL_LATCH.await(1L, TimeUnit.SECONDS); - if (expired) { - throw new InternalError("expired latch!"); - } - VMError.guarantee(cachedSize != UNSET_SENTINEL, "Expected chached size to be set"); - return cachedSize; - } catch (InterruptedException e) { - throw VMError.shouldNotReachHere("Interrupt on countdown latch!"); + if (INITIALIZATION_STATE.compareAndSet(NOT_INITIALIZED, INITIALIZING)) { + try { + long memoryLimit = SubstrateOptions.MaxRAM.getValue(); + if (memoryLimit > 0) { + cachedSize = WordFactory.unsigned(memoryLimit); + } else { + memoryLimit = Containers.memoryLimitInBytes(); + cachedSize = memoryLimit > 0 + ? WordFactory.unsigned(memoryLimit) + : ImageSingletons.lookup(PhysicalMemorySupport.class).size(); } + // Now that we have set the cachedSize let other threads know it's + // available to use. + CACHED_SIZE_AVAIL_LATCH.countDown(); + INITIALIZATION_STATE.set(INITIALIZED); + } catch (Throwable t) { + INITIALIZATION_STATE.set(NOT_INITIALIZED); } - if (INITIALIZATION_STATE.compareAndSet(NOT_INITIALIZED, INITIALIZING)) { - try { - long memoryLimit = SubstrateOptions.MaxRAM.getValue(); - if (memoryLimit > 0) { - cachedSize = WordFactory.unsigned(memoryLimit); - } else { - memoryLimit = Containers.memoryLimitInBytes(); - cachedSize = memoryLimit > 0 - ? WordFactory.unsigned(memoryLimit) - : ImageSingletons.lookup(PhysicalMemorySupport.class).size(); - } - // Now that we have set the cachedSize let other threads know it's - // available to use. - CACHED_SIZE_AVAIL_LATCH.countDown(); - INITIALIZATION_STATE.set(INITIALIZED); - } catch (Throwable t) { - INITIALIZATION_STATE.set(NOT_INITIALIZED); + } else if (INITIALIZATION_STATE.get() == INITIALIZING) { + /* + * Recursive initializations need to wait for the one initializing thread to + * finish so as to get correct reads of the cachedSize value. + */ + try { + boolean expired = !CACHED_SIZE_AVAIL_LATCH.await(1L, TimeUnit.SECONDS); + if (expired) { + throw new InternalError("expired latch!"); } + VMError.guarantee(cachedSize != UNSET_SENTINEL, "Expected chached size to be set"); + return cachedSize; + } catch (InterruptedException e) { + throw VMError.shouldNotReachHere("Interrupt on countdown latch!"); } + } else { + VMError.guarantee(INITIALIZATION_STATE.get() == INITIALIZED, "Expected initialization state to be initialized"); + VMError.guarantee(cachedSize != UNSET_SENTINEL, "Expected chached size to be set"); } return cachedSize;