|
9 | 9 | #include <errno.h>
|
10 | 10 | #include <stdlib.h>
|
11 | 11 | #include <string.h>
|
| 12 | +#include <sys/mman.h> |
| 13 | +#include <malloc.h> |
12 | 14 | #include <time.h>
|
13 | 15 | #include <unistd.h>
|
14 | 16 |
|
|
17 | 19 | #include <wasi/api.h>
|
18 | 20 | #include <wasi/wasi-helpers.h>
|
19 | 21 |
|
| 22 | +#include "lock.h" |
| 23 | + |
20 | 24 | /*
|
21 | 25 | * WASI support code. These are compiled with the program, and call out
|
22 | 26 | * using wasi APIs, which can be provided either by a wasi VM or by our
|
@@ -59,15 +63,73 @@ int clock_getres(clockid_t clk_id, struct timespec *tp) {
|
59 | 63 | // mmap support is nonexistent. TODO: emulate simple mmaps using
|
60 | 64 | // stdio + malloc, which is slow but may help some things?
|
61 | 65 |
|
62 |
| -long __map_file(int x, int y) { |
63 |
| - return -ENOSYS; |
| 66 | +const unsigned char * __map_file(const char *pathname, size_t *size) { |
| 67 | + errno = ENOSYS; |
| 68 | + return NULL; |
64 | 69 | }
|
65 | 70 |
|
66 |
| -long __syscall_munmap(int x, int y) { |
67 |
| - return -ENOSYS; |
| 71 | +struct map { |
| 72 | + void* addr; |
| 73 | + long length; |
| 74 | + struct map* next; |
| 75 | +} __attribute__((aligned (1))); |
| 76 | + |
| 77 | +static volatile int lock[1]; |
| 78 | +static struct map* mappings; |
| 79 | + |
| 80 | +long __syscall_munmap(long addr, long length) { |
| 81 | + LOCK(lock); |
| 82 | + struct map* map = mappings; |
| 83 | + struct map* prev = NULL; |
| 84 | + while (map) { |
| 85 | + if (map->addr == (void*)addr) { |
| 86 | + // We don't support partial munmapping. |
| 87 | + if (map->length != length) { |
| 88 | + map = NULL; |
| 89 | + break; |
| 90 | + } |
| 91 | + if (prev) { |
| 92 | + prev->next = map->next; |
| 93 | + } else { |
| 94 | + mappings = map->next; |
| 95 | + } |
| 96 | + break; |
| 97 | + } |
| 98 | + prev = map; |
| 99 | + map = map->next; |
| 100 | + } |
| 101 | + UNLOCK(lock); |
| 102 | + |
| 103 | + if (map) { |
| 104 | + // Release the memory. |
| 105 | + free(map->addr); |
| 106 | + // Success! |
| 107 | + return 0; |
| 108 | + } |
| 109 | + |
| 110 | + errno = EINVAL; |
| 111 | + return -1; |
68 | 112 | }
|
69 | 113 |
|
70 | 114 | long __syscall_mmap2(long addr, long len, long prot, long flags, long fd, long off) {
|
| 115 | + // MAP_ANONYMOUS (aka MAP_ANON) isn't actually defined by POSIX spec, |
| 116 | + // but it is widely used way to allocate memory pages on Linux, BSD and Mac. |
| 117 | + // In this case fd argument is ignored. |
| 118 | + if (flags & MAP_ANONYMOUS) { |
| 119 | + void* ptr = memalign(WASM_PAGE_SIZE, len + sizeof(struct map)); |
| 120 | + if (!ptr) { |
| 121 | + return -ENOMEM; |
| 122 | + } |
| 123 | + memset(ptr, 0, len); |
| 124 | + struct map* new_map = (struct map*)((char*)ptr + len); |
| 125 | + new_map->addr = ptr; |
| 126 | + new_map->length = len; |
| 127 | + LOCK(lock); |
| 128 | + new_map->next = mappings; |
| 129 | + mappings = new_map; |
| 130 | + UNLOCK(lock); |
| 131 | + return (long)ptr; |
| 132 | + } |
71 | 133 | return -ENOSYS;
|
72 | 134 | }
|
73 | 135 |
|
|
0 commit comments