Skip to content

Commit a3fe47e

Browse files
authored
[wasm] stop using mmap/munmap (#108512)
1 parent 3db28cd commit a3fe47e

File tree

9 files changed

+53
-618
lines changed

9 files changed

+53
-618
lines changed

src/mono/browser/browser.proj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@
209209
<EmccExportedFunction Include="_malloc" />
210210
<EmccExportedFunction Include="_sbrk" />
211211
<EmccExportedFunction Include="_memalign" />
212+
<EmccExportedFunction Include="_posix_memalign" />
212213
<EmccExportedFunction Include="_memset" />
213214
<EmccExportedFunction Include="_ntohs" />
214215
<EmccExportedFunction Include="stackAlloc" />

src/mono/mono/sgen/sgen-los.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,12 @@ get_los_section_memory (size_t size)
334334
section->next = los_sections;
335335
los_sections = section;
336336

337+
#ifdef HOST_WASM
338+
// on WASM there is no mmap and alignment has large overhead
339+
sgen_los_memory_usage_total += LOS_SECTION_SIZE + LOS_SECTION_SIZE;
340+
#else
337341
sgen_los_memory_usage_total += LOS_SECTION_SIZE;
342+
#endif
338343
++los_num_sections;
339344

340345
goto retry;
@@ -542,7 +547,12 @@ sgen_los_sweep (void)
542547
sgen_memgov_release_space (LOS_SECTION_SIZE, SPACE_LOS);
543548
section = next;
544549
--los_num_sections;
550+
#ifdef HOST_WASM
551+
// on WASM there is no mmap and alignment has large overhead
552+
sgen_los_memory_usage_total -= LOS_SECTION_SIZE + LOS_SECTION_SIZE;
553+
#else
545554
sgen_los_memory_usage_total -= LOS_SECTION_SIZE;
555+
#endif
546556
continue;
547557
}
548558

src/mono/mono/sgen/sgen-marksweep.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,13 @@ static int ms_block_size;
4949
* Don't allocate single blocks, but alloc a contingent of this many
5050
* blocks in one swoop. This must be a power of two.
5151
*/
52+
#ifndef TARGET_WASM
5253
#define MS_BLOCK_ALLOC_NUM 32
54+
#else
55+
// WASM doesn't support partial munmap, so we can't free individual blocks
56+
// we use posix_memalign and free the whole block at once
57+
#define MS_BLOCK_ALLOC_NUM 1
58+
#endif
5359

5460
#define MS_NUM_MARK_WORDS ((ms_block_size / SGEN_ALLOC_ALIGN + sizeof (guint32) * 8 - 1) / (sizeof (guint32) * 8))
5561

@@ -2140,9 +2146,6 @@ major_free_swept_blocks (size_t section_reserve)
21402146
* a VirtualAlloc ()-ed block.
21412147
*/
21422148
return;
2143-
#elif defined(HOST_WASM)
2144-
if (!mono_opt_wasm_mmap)
2145-
return;
21462149
#endif
21472150

21482151
{

src/mono/mono/utils/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ set(utils_arch_sources "${utils_arch_sources};mono-hwcap-riscv.c")
204204
elseif(TARGET_S390X)
205205
set(utils_arch_sources "${utils_arch_sources};mono-hwcap-s390x.c")
206206
elseif(TARGET_WASM)
207-
set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c;mono-mmap-wasm.c;mono-wasm-pagemgr.c")
207+
set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c;mono-mmap-wasm.c")
208208
elseif(TARGET_WASI)
209209
set(utils_arch_sources "${utils_arch_sources};mono-hwcap-wasm.c")
210210
elseif(TARGET_POWERPC OR TARGET_POWERPC64)

src/mono/mono/utils/lock-free-alloc.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ typedef struct {
4646
} MonoLockFreeAllocator;
4747

4848
#ifdef HOST_WASM
49-
#define LOCK_FREE_ALLOC_SB_MAX_SIZE (mono_opt_wasm_mmap ? 65536 : 16384)
49+
#define LOCK_FREE_ALLOC_SB_MAX_SIZE 16384 * 32
5050
#else
5151
#define LOCK_FREE_ALLOC_SB_MAX_SIZE 16384
5252
#endif

src/mono/mono/utils/mono-mmap-wasm.c

Lines changed: 30 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
#include <mono/utils/atomic.h>
2525
#include <mono/utils/options.h>
2626

27-
#include "mono-wasm-pagemgr.h"
28-
2927
#define BEGIN_CRITICAL_SECTION do { \
3028
MonoThreadInfo *__info = mono_thread_info_current_unchecked (); \
3129
if (__info) __info->inside_critical_region = TRUE; \
@@ -37,22 +35,7 @@
3735
int
3836
mono_pagesize (void)
3937
{
40-
if (mono_opt_wasm_mmap)
41-
return MWPM_PAGE_SIZE;
42-
43-
static int saved_pagesize = 0;
44-
45-
if (saved_pagesize)
46-
return saved_pagesize;
47-
48-
// Prefer sysconf () as it's signal safe.
49-
#if defined (HAVE_SYSCONF) && defined (_SC_PAGESIZE)
50-
saved_pagesize = sysconf (_SC_PAGESIZE);
51-
#else
52-
saved_pagesize = getpagesize ();
53-
#endif
54-
55-
return saved_pagesize;
38+
return 16384;
5639
}
5740

5841
int
@@ -96,122 +79,50 @@ mono_setmmapjit (int flag)
9679
/* Ignored on HOST_WASM */
9780
}
9881

99-
static void*
100-
valloc_impl (void *addr, size_t size, int flags, MonoMemAccountType type)
101-
{
102-
void *ptr;
103-
int mflags = 0;
104-
int prot = prot_from_flags (flags);
105-
106-
if (!mono_valloc_can_alloc (size))
107-
return NULL;
108-
109-
if (size == 0)
110-
/* emscripten throws an exception on 0 length */
111-
return NULL;
112-
113-
mflags |= MAP_ANONYMOUS;
114-
mflags |= MAP_PRIVATE;
115-
116-
BEGIN_CRITICAL_SECTION;
117-
if (mono_opt_wasm_mmap) {
118-
// FIXME: Make this work if the requested address range is free
119-
if ((flags & MONO_MMAP_FIXED) && addr)
120-
return NULL;
121-
122-
ptr = mwpm_alloc_range (size, (flags & MONO_MMAP_NOZERO) == 0);
123-
if (!ptr)
124-
return NULL;
125-
} else
126-
ptr = mmap (addr, size, prot, mflags, -1, 0);
127-
END_CRITICAL_SECTION;
128-
129-
if (ptr == MAP_FAILED)
130-
return NULL;
131-
132-
mono_account_mem (type, (ssize_t)size);
133-
134-
return ptr;
135-
}
13682

13783
void*
138-
mono_valloc (void *addr, size_t size, int flags, MonoMemAccountType type)
84+
mono_valloc (void *addr, size_t length, int flags, MonoMemAccountType type)
13985
{
140-
#if HOST_WASI
141-
// WASI implements mmap using malloc, so the returned address is not page aligned
142-
// and our code depends on it
143-
g_assert (!addr);
144-
return mono_valloc_aligned (size, mono_pagesize (), flags, type);
145-
#else
146-
return valloc_impl (addr, size, flags, type);
147-
#endif
86+
g_assert (addr == NULL);
87+
return mono_valloc_aligned (length, mono_pagesize (), flags, type);
14888
}
14989

150-
static GHashTable *valloc_hash;
151-
152-
typedef struct {
153-
void *addr;
154-
int size;
155-
} VallocInfo;
156-
15790
void*
15891
mono_valloc_aligned (size_t size, size_t alignment, int flags, MonoMemAccountType type)
15992
{
160-
// We don't need padding if the alignment is compatible with the page size
161-
if (mono_opt_wasm_mmap && ((MWPM_PAGE_SIZE % alignment) == 0))
162-
return valloc_impl (NULL, size, flags, type);
163-
164-
/* Allocate twice the memory to be able to put the block on an aligned address */
165-
char *mem = (char *) valloc_impl (NULL, size + alignment, flags, type);
166-
char *aligned;
93+
#ifdef DISABLE_THREADS
94+
void *old_sbrk = NULL;
95+
if ((flags & MONO_MMAP_NOZERO) == 0) {
96+
old_sbrk = sbrk (0);
97+
}
98+
#endif
16799

168-
if (!mem)
100+
void *res = NULL;
101+
if (posix_memalign (&res, alignment, size))
169102
return NULL;
170103

171-
aligned = mono_aligned_address (mem, size, alignment);
104+
#ifdef DISABLE_THREADS
105+
if ((flags & MONO_MMAP_NOZERO) == 0 && old_sbrk > res) {
106+
// this means that we got an old block, not the new block from sbrk
107+
memset (res, 0, size);
108+
}
109+
#else
110+
if ((flags & MONO_MMAP_NOZERO) == 0) {
111+
memset (res, 0, size);
112+
}
113+
#endif
172114

173-
/* The mmap implementation in emscripten cannot unmap parts of regions */
174-
/* Free the other two parts in when 'aligned' is freed */
175-
// FIXME: This doubles the memory usage
176-
if (!valloc_hash)
177-
valloc_hash = g_hash_table_new (NULL, NULL);
178-
VallocInfo *info = g_new0 (VallocInfo, 1);
179-
info->addr = mem;
180-
info->size = size + alignment;
181-
g_hash_table_insert (valloc_hash, aligned, info);
115+
mono_account_mem (type, (ssize_t)size);
182116

183-
return aligned;
117+
return res;
184118
}
185119

186120
int
187121
mono_vfree (void *addr, size_t length, MonoMemAccountType type)
188122
{
189-
VallocInfo *info = (VallocInfo*)(valloc_hash ? g_hash_table_lookup (valloc_hash, addr) : NULL);
190-
191-
if (info) {
192-
/*
193-
* We are passed the aligned address in the middle of the mapping allocated by
194-
* mono_valloc_align (), free the original mapping.
195-
*/
196-
BEGIN_CRITICAL_SECTION;
197-
if (mono_opt_wasm_mmap)
198-
mwpm_free_range (info->addr, info->size);
199-
else
200-
munmap (info->addr, info->size);
201-
END_CRITICAL_SECTION;
202-
g_free (info);
203-
g_hash_table_remove (valloc_hash, addr);
204-
} else {
205-
// FIXME: We could be trying to unmap part of an aligned mapping, in which case the
206-
// hash lookup failed because addr isn't exactly the start of the mapping.
207-
// Ideally if the custom page manager is enabled, we won't have done aligned alloc.
208-
BEGIN_CRITICAL_SECTION;
209-
if (mono_opt_wasm_mmap)
210-
mwpm_free_range (addr, length);
211-
else
212-
munmap (addr, length);
213-
END_CRITICAL_SECTION;
214-
}
123+
// NOTE: this doesn't implement partial freeing like munmap does
124+
// we set MS_BLOCK_ALLOC_NUM to 1 to avoid partial freeing
125+
g_free (addr);
215126

216127
mono_account_mem (type, -(ssize_t)length);
217128

@@ -267,6 +178,9 @@ mono_file_unmap (void *addr, void *handle)
267178
int
268179
mono_mprotect (void *addr, size_t length, int flags)
269180
{
181+
if (flags & MONO_MMAP_DISCARD) {
182+
memset (addr, 0, length);
183+
}
270184
return 0;
271185
}
272186

0 commit comments

Comments
 (0)