Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] Add custom mmap/munmap implementation for anonymous mappings #101871

Merged
merged 24 commits into from
May 10, 2024
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
8 changes: 6 additions & 2 deletions src/mono/mono/sgen/sgen-internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ sgen_report_internal_mem_usage (void)
void
sgen_init_internal_allocator (void)
{
int i, size;
int i;

for (i = 0; i < INTERNAL_MEM_MAX; ++i)
fixed_type_allocator_indexes [i] = -1;
Expand All @@ -284,7 +284,10 @@ sgen_init_internal_allocator (void)
mono_lock_free_allocator_init_allocator (&allocators [i], &size_classes [i], MONO_MEM_ACCOUNT_SGEN_INTERNAL);
}

for (size = mono_pagesize (); size <= LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) {
// FIXME: This whole algorithm is broken on WASM due to its 64KB page size.
// Previously SB_MAX_SIZE was < mono_pagesize, so none of this ran.
#ifndef HOST_WASM
for (int size = mono_pagesize (); size <= LOCK_FREE_ALLOC_SB_MAX_SIZE; size <<= 1) {
int max_size = (LOCK_FREE_ALLOC_SB_USABLE_SIZE (size) / 2) & ~(SIZEOF_VOID_P - 1);
/*
* we assert that allocator_sizes contains the biggest possible object size
Expand All @@ -297,6 +300,7 @@ sgen_init_internal_allocator (void)
if (size < LOCK_FREE_ALLOC_SB_MAX_SIZE)
g_assert (block_size (max_size + 1) == size << 1);
}
#endif
}

#endif
6 changes: 5 additions & 1 deletion src/mono/mono/sgen/sgen-marksweep.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "mono/sgen/sgen-client.h"
#include "mono/utils/mono-memory-model.h"
#include "mono/utils/mono-proclib.h"
#include "mono/utils/options.h"

static int ms_block_size;

Expand Down Expand Up @@ -2133,12 +2134,15 @@ major_free_swept_blocks (size_t section_reserve)
{
SGEN_ASSERT (0, sweep_state == SWEEP_STATE_SWEPT, "Sweeping must have finished before freeing blocks");

#if defined(HOST_WIN32) || defined(HOST_ORBIS) || defined (HOST_WASM)
#if defined(HOST_WIN32) || defined(HOST_ORBIS)
/*
* sgen_free_os_memory () asserts in mono_vfree () because windows doesn't like freeing the middle of
* a VirtualAlloc ()-ed block.
*/
return;
#elif defined(HOST_WASM)
if (!mono_opt_wasm_mmap)
return;
#endif

{
Expand Down
2 changes: 1 addition & 1 deletion src/mono/mono/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ set(utils_arch_sources "${utils_arch_sources};mono-hwcap-riscv.c")
elseif(TARGET_S390X)
set(utils_arch_sources "${utils_arch_sources};mono-hwcap-s390x.c")
elseif(TARGET_WASM)
set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c;mono-mmap-wasm.c")
set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c;mono-mmap-wasm.c;mono-wasm-pagemgr.c")
elseif(TARGET_WASI)
set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c")
elseif(TARGET_POWERPC OR TARGET_POWERPC64)
Expand Down
1 change: 1 addition & 0 deletions src/mono/mono/utils/lock-free-alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ typedef struct {
MonoMemAccountType account_type;
} MonoLockFreeAllocator;

// FIXME: On WASM the page size is 64KB, so this isn't enough.
#define LOCK_FREE_ALLOC_SB_MAX_SIZE 16384
#define LOCK_FREE_ALLOC_SB_HEADER_SIZE (sizeof (gpointer))
#define LOCK_FREE_ALLOC_SB_USABLE_SIZE(block_size) ((block_size) - LOCK_FREE_ALLOC_SB_HEADER_SIZE)
Expand Down
34 changes: 31 additions & 3 deletions src/mono/mono/utils/mono-mmap-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#include "mono-proclib.h"
#include <mono/utils/mono-threads.h>
#include <mono/utils/atomic.h>
#include <mono/utils/options.h>

#include "mono-wasm-pagemgr.h"

#define BEGIN_CRITICAL_SECTION do { \
MonoThreadInfo *__info = mono_thread_info_current_unchecked (); \
Expand All @@ -34,6 +37,9 @@
int
mono_pagesize (void)
{
if (mono_opt_wasm_mmap)
return MWPM_PAGE_SIZE;

static int saved_pagesize = 0;

if (saved_pagesize)
Expand Down Expand Up @@ -108,7 +114,16 @@ valloc_impl (void *addr, size_t size, int flags, MonoMemAccountType type)
mflags |= MAP_PRIVATE;

BEGIN_CRITICAL_SECTION;
ptr = mmap (addr, size, prot, mflags, -1, 0);
if (mono_opt_wasm_mmap) {
// FIXME: Make this work if the requested address range is free
if ((flags & MONO_MMAP_FIXED) && addr)
return NULL;

ptr = mwpm_alloc_range (size, 1);
if (!ptr)
return NULL;
} else
ptr = mmap (addr, size, prot, mflags, -1, 0);
END_CRITICAL_SECTION;

if (ptr == MAP_FAILED)
Expand Down Expand Up @@ -142,6 +157,10 @@ typedef struct {
void*
mono_valloc_aligned (size_t size, size_t alignment, int flags, MonoMemAccountType type)
{
// We don't need padding if the alignment is compatible with the page size
if (mono_opt_wasm_mmap && ((MWPM_PAGE_SIZE % alignment) == 0))
return valloc_impl (NULL, size, flags, type);

/* Allocate twice the memory to be able to put the block on an aligned address */
char *mem = (char *) valloc_impl (NULL, size + alignment, flags, type);
char *aligned;
Expand Down Expand Up @@ -175,13 +194,22 @@ mono_vfree (void *addr, size_t length, MonoMemAccountType type)
* mono_valloc_align (), free the original mapping.
*/
BEGIN_CRITICAL_SECTION;
munmap (info->addr, info->size);
if (mono_opt_wasm_mmap)
pavelsavara marked this conversation as resolved.
Show resolved Hide resolved
mwpm_free_range (info->addr, info->size);
else
munmap (info->addr, info->size);
END_CRITICAL_SECTION;
g_free (info);
g_hash_table_remove (valloc_hash, addr);
} else {
// FIXME: We could be trying to unmap part of an aligned mapping, in which case the
// hash lookup failed because addr isn't exactly the start of the mapping.
// Ideally if the custom page manager is enabled, we won't have done aligned alloc.
BEGIN_CRITICAL_SECTION;
munmap (addr, length);
if (mono_opt_wasm_mmap)
mwpm_free_range (addr, length);
else
munmap (addr, length);
END_CRITICAL_SECTION;
}

Expand Down
3 changes: 2 additions & 1 deletion src/mono/mono/utils/mono-mmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ enum {
MONO_MMAP_ANON = 1 << 6,
MONO_MMAP_FIXED = 1 << 7,
MONO_MMAP_32BIT = 1 << 8,
MONO_MMAP_JIT = 1 << 9
MONO_MMAP_JIT = 1 << 9,
MONO_MMAP_NOZERO = 1 << 10,
};

typedef enum {
Expand Down
Loading