Skip to content
Open
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
6 changes: 4 additions & 2 deletions src/coreclr/gc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ set(GC_SOURCES
gcbridge.cpp
handletablecache.cpp)

if(CLR_CMAKE_HOST_UNIX)
if(CLR_CMAKE_TARGET_ARCH_WASM)
add_subdirectory(wasm)
elseif(CLR_CMAKE_HOST_UNIX)
add_subdirectory(unix)
include(unix/configure.cmake)
else()
add_subdirectory(windows)
set (GC_SOURCES
${GC_SOURCES}
windows/Native.rc)
endif(CLR_CMAKE_HOST_UNIX)
endif()

if (CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_AMD64)
add_subdirectory(vxsort)
Expand Down
36 changes: 31 additions & 5 deletions src/coreclr/gc/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -914,11 +914,19 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size,
return E_OUTOFMEMORY;
if (use_large_pages_p)
{
#ifndef HOST_64BIT
#if !defined(HOST_64BIT) && !defined(HOST_WASM)
// Large pages are not supported on 32bit
// except WASM, which uses the large-pages code path to skip decommit
assert (false);
#endif //!HOST_64BIT

#endif //!HOST_64BIT && !HOST_WASM

#ifndef HOST_WASM
// On real large-page platforms the OS pre-committed all the memory during
// reserve_initial_memory, so we tighten the hard limit to match the
// actual segment sizes. On WASM, use_large_pages_p is only a decommit-
// skip flag — the original auto-detected hard limit (75% of WASM linear
// memory max) must be preserved so that bookkeeping commits and later
// allocations have room within the limit.
if (heap_hard_limit_oh[soh])
{
heap_hard_limit_oh[soh] = soh_segment_size * number_of_heaps;
Expand All @@ -931,6 +939,7 @@ HRESULT gc_heap::initialize_gc (size_t soh_segment_size,
assert (heap_hard_limit);
heap_hard_limit = (soh_segment_size + loh_segment_size + poh_segment_size) * number_of_heaps;
}
#endif //HOST_WASM
}
#endif //USE_REGIONS

Expand Down Expand Up @@ -1280,6 +1289,10 @@ bool gc_heap::compute_hard_limit()

#ifdef HOST_64BIT
use_large_pages_p = GCConfig::GetGCLargePages();
#elif defined(HOST_WASM)
// On WASM, reserve == commit (posix_memalign allocates real memory) and there is
// no way to decommit. Enabling the large-pages path makes the GC skip VirtualDecommit.
use_large_pages_p = true;
#endif //HOST_64BIT

if (heap_hard_limit_oh[soh] || heap_hard_limit_oh[loh] || heap_hard_limit_oh[poh])
Expand Down Expand Up @@ -1368,9 +1381,11 @@ bool gc_heap::compute_hard_limit()

bool gc_heap::compute_memory_settings(bool is_initialization, uint32_t& nhp, uint32_t nhp_from_config, size_t& seg_size_from_config, size_t new_current_total_committed)
{
#ifdef HOST_64BIT
#if defined(HOST_64BIT) || defined(HOST_WASM)
// If the hard limit is specified, the user is saying even if the process is already
// running in a container, use this limit for the GC heap.
// On WASM, the linear memory has a hard ceiling set in the .wasm file, enforced by
// the engine — semantically equivalent to a container memory limit.
if (!hard_limit_config_p)
{
if (is_restricted_physical_mem)
Expand All @@ -1387,7 +1402,7 @@ bool gc_heap::compute_memory_settings(bool is_initialization, uint32_t& nhp, uin
}
}
}
#endif //HOST_64BIT
#endif //HOST_64BIT || HOST_WASM

if (heap_hard_limit && (heap_hard_limit < new_current_total_committed))
{
Expand Down Expand Up @@ -1431,6 +1446,17 @@ bool gc_heap::compute_memory_settings(bool is_initialization, uint32_t& nhp, uin
// 0 <= soh_segment_size <= 1Gb
size_t limit_to_check = (heap_hard_limit_oh[soh] ? heap_hard_limit_oh[soh] : heap_hard_limit);
soh_segment_size = max (adjust_segment_size_hard_limit (limit_to_check, nhp), seg_size_from_config);
#ifdef HOST_WASM
// On WASM, VirtualReserve allocates real memory (no virtual memory).
// Cap segment size so all 3 initial segments (SOH + LOH + POH) fit within
// the hard limit with room to grow. On 32-bit without per-OH limits,
// LOH and POH segments equal soh_segment_size, so total = 3 * soh.
{
size_t max_seg = round_down_power2 (heap_hard_limit / (3 * 2 * nhp));
max_seg = max (max_seg, (size_t)(1024 * 1024));
soh_segment_size = min (soh_segment_size, max_seg);
}
#endif //HOST_WASM
}
else
{
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/gc/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,10 @@ HRESULT GCHeap::Initialize()
#ifdef HOST_64BIT
large_seg_size = gc_heap::use_large_pages_p ? gc_heap::soh_segment_size : gc_heap::soh_segment_size * 2;
#else //HOST_64BIT
#ifndef HOST_WASM
// Large pages not supported on 32-bit (except WASM which uses it to skip decommit).
assert (!gc_heap::use_large_pages_p);
#endif //HOST_WASM
large_seg_size = gc_heap::soh_segment_size;
#endif //HOST_64BIT
pin_seg_size = large_seg_size;
Expand Down
27 changes: 6 additions & 21 deletions src/coreclr/gc/unix/gcenv.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,6 @@ typedef cpuset_t cpu_set_t;
#define SYSCONF_GET_NUMPROCS _SC_NPROCESSORS_ONLN
#endif

#ifdef __EMSCRIPTEN__
#include <emscripten/heap.h>
#endif // __EMSCRIPTEN__


// The cached total number of CPUs that can be used in the OS.
uint32_t g_totalCpuCount = 0;

Expand Down Expand Up @@ -347,7 +342,7 @@ void GCToOSInterface::Sleep(uint32_t sleepMSec)
requested.tv_nsec = (sleepMSec - requested.tv_sec * tccSecondsToMilliSeconds) * tccMilliSecondsToNanoSeconds;

timespec remaining;
while (nanosleep(&requested, &remaining) == EINTR)
while (nanosleep(&requested, &remaining) == -1 && errno == EINTR)
{
requested = remaining;
}
Expand Down Expand Up @@ -405,7 +400,7 @@ static void* VirtualReserveInner(size_t size, size_t alignment, uint32_t flags,
}

pRetVal = pAlignedRetVal;
#if defined(MADV_DONTDUMP) && !defined(TARGET_WASM)
#if defined(MADV_DONTDUMP)
// Do not include reserved uncommitted memory in coredump.
if (!committing)
{
Expand Down Expand Up @@ -453,13 +448,9 @@ bool GCToOSInterface::VirtualRelease(void* address, size_t size)
// true if it has succeeded, false if it has failed
static bool VirtualCommitInner(void* address, size_t size, uint16_t node, bool newMemory)
{
#ifndef TARGET_WASM
bool success = mprotect(address, size, PROT_WRITE | PROT_READ) == 0;
#else
bool success = true;
#endif // !TARGET_WASM

#if defined(MADV_DONTDUMP) && !defined(TARGET_WASM)
#if defined(MADV_DONTDUMP)
if (success && !newMemory)
{
// Include committed memory in coredump. New memory is included by default.
Expand Down Expand Up @@ -544,13 +535,13 @@ bool GCToOSInterface::VirtualDecommit(void* address, size_t size)
#endif
bool bRetVal = mmap(address, size, PROT_NONE, mmapFlags, -1, 0) != MAP_FAILED;

#if defined(MADV_DONTDUMP) && !defined(TARGET_WASM)
#if defined(MADV_DONTDUMP)
if (bRetVal)
{
// Do not include freed memory in coredump.
madvise(address, size, MADV_DONTDUMP);
}
#endif // defined(MADV_DONTDUMP) && !defined(TARGET_WASM)
#endif // defined(MADV_DONTDUMP)

return bRetVal;
}
Expand All @@ -565,9 +556,6 @@ bool GCToOSInterface::VirtualDecommit(void* address, size_t size)
// true if it has succeeded, false if it has failed
bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock)
{
#ifdef TARGET_WASM
return true;
#else // !TARGET_WASM
int st = EINVAL;

#ifdef MADV_DONTDUMP
Expand All @@ -586,7 +574,6 @@ bool GCToOSInterface::VirtualReset(void * address, size_t size, bool unlock)
#endif // MADV_FREE

return (st == 0);
#endif // !TARGET_WASM
}

// Check if the OS supports write watching
Expand Down Expand Up @@ -836,7 +823,7 @@ static uint64_t GetMemorySizeMultiplier(char units)
return 1;
}

#if !defined(__APPLE__) && !defined(__HAIKU__) && !defined(__EMSCRIPTEN__)
#if !defined(__APPLE__) && !defined(__HAIKU__)
// Try to read the MemAvailable entry from /proc/meminfo.
// Return true if the /proc/meminfo existed, the entry was present and we were able to parse it.
static bool ReadMemAvailable(uint64_t* memAvailable)
Expand Down Expand Up @@ -1104,8 +1091,6 @@ uint64_t GetAvailablePhysicalMemory()
{
available = info.free_memory;
}
#elif defined(__EMSCRIPTEN__)
available = emscripten_get_heap_max() - emscripten_get_heap_size();
#else // Linux
static volatile bool tryReadMemInfo = true;

Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/gc/wasm/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories("../env")
include_directories("..")
include_directories("../unix")

include(../unix/configure.cmake)

set(GC_PAL_SOURCES
gcenv.cpp
../unix/events.cpp)

Comment thread
pavelsavara marked this conversation as resolved.
add_library(gc_pal OBJECT ${GC_PAL_SOURCES} ${VERSION_FILE_PATH})
Loading
Loading