Skip to content

Commit

Permalink
Implement MAP_ANONYMOUS on top of malloc in STANDALONE_WASM mode (#16289
Browse files Browse the repository at this point in the history
)

This hack already exists in the JS implementation of mmap.  We could try
to unify the two but I'm not sure its worth it.

Fixes: #16280, #13312
  • Loading branch information
sbc100 authored Feb 15, 2022
1 parent 2a4e295 commit f4115eb
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 8 deletions.
70 changes: 66 additions & 4 deletions system/lib/standalone/standalone.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <malloc.h>
#include <time.h>
#include <unistd.h>

Expand All @@ -17,6 +19,8 @@
#include <wasi/api.h>
#include <wasi/wasi-helpers.h>

#include "lock.h"

/*
* WASI support code. These are compiled with the program, and call out
* using wasi APIs, which can be provided either by a wasi VM or by our
Expand Down Expand Up @@ -59,15 +63,73 @@ int clock_getres(clockid_t clk_id, struct timespec *tp) {
// mmap support is nonexistent. TODO: emulate simple mmaps using
// stdio + malloc, which is slow but may help some things?

long __map_file(int x, int y) {
return -ENOSYS;
const unsigned char * __map_file(const char *pathname, size_t *size) {
errno = ENOSYS;
return NULL;
}

long __syscall_munmap(int x, int y) {
return -ENOSYS;
struct map {
void* addr;
long length;
struct map* next;
} __attribute__((aligned (1)));

static volatile int lock[1];
static struct map* mappings;

long __syscall_munmap(long addr, long length) {
LOCK(lock);
struct map* map = mappings;
struct map* prev = NULL;
while (map) {
if (map->addr == (void*)addr) {
// We don't support partial munmapping.
if (map->length != length) {
map = NULL;
break;
}
if (prev) {
prev->next = map->next;
} else {
mappings = map->next;
}
break;
}
prev = map;
map = map->next;
}
UNLOCK(lock);

if (map) {
// Release the memory.
free(map->addr);
// Success!
return 0;
}

errno = EINVAL;
return -1;
}

long __syscall_mmap2(long addr, long len, long prot, long flags, long fd, long off) {
// MAP_ANONYMOUS (aka MAP_ANON) isn't actually defined by POSIX spec,
// but it is widely used way to allocate memory pages on Linux, BSD and Mac.
// In this case fd argument is ignored.
if (flags & MAP_ANONYMOUS) {
void* ptr = memalign(WASM_PAGE_SIZE, len + sizeof(struct map));
if (!ptr) {
return -ENOMEM;
}
memset(ptr, 0, len);
struct map* new_map = (struct map*)((char*)ptr + len);
new_map->addr = ptr;
new_map->length = len;
LOCK(lock);
new_map->next = mappings;
mappings = new_map;
UNLOCK(lock);
return (long)ptr;
}
return -ENOSYS;
}

Expand Down
9 changes: 7 additions & 2 deletions tests/core/test_mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ int main(int argc, char* argv[]) {
assert(getpagesize() == 65536);
assert(sysconf(_SC_PAGESIZE) == 65536);

int* maps[10];
for (int i = 0; i < 10; i++) {
int* map = (int*)mmap(0, 5000, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANON, -1, 0);
assert(map != MAP_FAILED);
assert(((long)map) % 65536 == 0); // aligned
assert(munmap(map, 5000) == 0);
maps[i] = map;
}

for (int i = 0; i < 10; i++) {
assert(munmap(maps[i], 5000) == 0);
}

const int NUM_BYTES = 8 * 1024 * 1024;
Expand All @@ -44,6 +49,6 @@ int main(int argc, char* argv[]) {

assert(munmap(map, NUM_BYTES) == 0);

printf("hello,world");
printf("hello,world\n");
return 0;
}
3 changes: 1 addition & 2 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -6061,13 +6061,12 @@ def test_static_variable(self):
def test_fakestat(self):
self.do_core_test('test_fakestat.c')

@also_with_standalone_wasm()
def test_mmap(self):
# ASan needs more memory, but that is set up separately
if '-fsanitize=address' not in self.emcc_args:
self.set_setting('INITIAL_MEMORY', '128mb')

# needs to flush stdio streams
self.set_setting('EXIT_RUNTIME')
self.do_core_test('test_mmap.c')

def test_mmap_file(self):
Expand Down

0 comments on commit f4115eb

Please sign in to comment.