From 788675b0916e4f26853cd31d1841b29a04bd3ccd Mon Sep 17 00:00:00 2001
From: normalcoder <normalcoder@gmail.com>
Date: Sun, 19 Dec 2021 20:39:35 +0300
Subject: [PATCH] Add arbitraryHeapStart flag. It allows to allocate the memory
 block anywhere, not only above the 8 GB. Without it we can get an inifite
 loop in osReserveHeapMemory because ios sometimes doesn't allocate memory
 below the 8 GB

---
 libraries/base/src/GHC/RTS/Flags.hsc | 3 +++
 rts/RtsFlags.c                       | 6 ++++++
 rts/include/rts/Flags.h              | 1 +
 rts/posix/OSMem.c                    | 4 +++-
 4 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/libraries/base/src/GHC/RTS/Flags.hsc b/libraries/base/src/GHC/RTS/Flags.hsc
index 2424a4f2c439..0999dcbfcf9d 100644
--- a/libraries/base/src/GHC/RTS/Flags.hsc
+++ b/libraries/base/src/GHC/RTS/Flags.hsc
@@ -144,6 +144,7 @@ data GCFlags = GCFlags
     , minOldGenSize         :: Word32
     , heapSizeSuggestion    :: Word32
     , heapSizeSuggestionAuto :: Bool
+    , arbitraryHeapStart    :: Bool
     , oldGenFactor          :: Double
     , returnDecayFactor     :: Double
     , pcFreeHeap            :: Double
@@ -462,6 +463,8 @@ getGCFlags = do
           <*> #{peek GC_FLAGS, heapSizeSuggestion} ptr
           <*> (toBool <$>
                 (#{peek GC_FLAGS, heapSizeSuggestionAuto} ptr :: IO CBool))
+          <*> (toBool <$>
+                (#{peek GC_FLAGS, arbitraryHeapStart} ptr :: IO CBool))
           <*> #{peek GC_FLAGS, oldGenFactor} ptr
           <*> #{peek GC_FLAGS, returnDecayFactor} ptr
           <*> #{peek GC_FLAGS, pcFreeHeap} ptr
diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c
index 8c384ad43272..6e841d838f9f 100644
--- a/rts/RtsFlags.c
+++ b/rts/RtsFlags.c
@@ -162,6 +162,7 @@ void initRtsFlagsDefaults(void)
     RtsFlags.GcFlags.heapLimitGrace     = (1024 * 1024);
     RtsFlags.GcFlags.heapSizeSuggestion = 0;    /* none */
     RtsFlags.GcFlags.heapSizeSuggestionAuto = false;
+    RtsFlags.GcFlags.arbitraryHeapStart = false;
     RtsFlags.GcFlags.pcFreeHeap         = 3;    /* 3% */
     RtsFlags.GcFlags.oldGenFactor       = 2;
     RtsFlags.GcFlags.returnDecayFactor  = 4;
@@ -1055,6 +1056,11 @@ error = true;
                        OPTION_UNSAFE;
                        RtsFlags.HpcFlags.writeTixFile = false;
                   }
+                  else if (strequal("arbitrary-heap-start",
+                               &rts_argv[arg][2])) {
+                      OPTION_UNSAFE;
+                      RtsFlags.GcFlags.arbitraryHeapStart = true;
+                  }
 #if defined(THREADED_RTS)
 #if defined(mingw32_HOST_OS)
                   else if (!strncmp("io-manager-threads",
diff --git a/rts/include/rts/Flags.h b/rts/include/rts/Flags.h
index e4405463311d..5ef7273aace5 100644
--- a/rts/include/rts/Flags.h
+++ b/rts/include/rts/Flags.h
@@ -49,6 +49,7 @@ typedef struct _GC_FLAGS {
     uint32_t     minOldGenSize;      /* in *blocks* */
     uint32_t     heapSizeSuggestion; /* in *blocks* */
     bool heapSizeSuggestionAuto;
+    bool arbitraryHeapStart;
     double  oldGenFactor;
     double  returnDecayFactor;
     double  pcFreeHeap;
diff --git a/rts/posix/OSMem.c b/rts/posix/OSMem.c
index a6eabfcdeedc..c9ad67d2a725 100644
--- a/rts/posix/OSMem.c
+++ b/rts/posix/OSMem.c
@@ -608,9 +608,11 @@ void *osReserveHeapMemory(void *startAddressPtr, W_ *len)
             // physical memory but a 511GB ulimit). See #14492.
             *len -= *len / 8;
             // debugBelch("Limit hit, reduced len: %zu\n", *len);
-        } else if ((W_)at >= minimumAddress) {
+        } else if (RtsFlags.GcFlags.arbitraryHeapStart || (W_)at >= minimumAddress) {
             // Success! We were given a block of memory starting above the 8 GB
             // mark, which is what we were looking for.
+            // Or we allow to allocate the block anywhere by setting
+            // arbitraryHeapStart flag.
 
             break;
         } else {
-- 
GitLab