Buckets:
| /* | |
| * Copyright 2022 The Emscripten Authors. All rights reserved. | |
| * Emscripten is available under two separate licenses, the MIT license and the | |
| * University of Illinois/NCSA Open Source License. Both these licenses can be | |
| * found in the LICENSE file. | |
| */ | |
| struct map { | |
| void* addr; | |
| long length; | |
| int allocated; | |
| int fd; | |
| int flags; | |
| off_t offset; | |
| int prot; | |
| struct map* next; | |
| } __attribute__((aligned (1))); | |
| // Linked list of all mapping, guarded by a musl-style lock (LOCK/UNLOCK) | |
| static volatile int lock[1]; | |
| static struct map* mappings; | |
| static struct map* find_mapping(intptr_t addr, struct map** prev) { | |
| struct map* map = mappings; | |
| while (map) { | |
| if (map->addr == (void*)addr) { | |
| return map; | |
| } | |
| if (prev) { | |
| *prev = map; | |
| } | |
| map = map->next; | |
| } | |
| return map; | |
| } | |
| int __syscall_munmap(intptr_t addr, size_t length) { | |
| LOCK(lock); | |
| struct map* prev = NULL; | |
| struct map* map = find_mapping(addr, &prev); | |
| if (!map || !length) { | |
| UNLOCK(lock); | |
| return -EINVAL; | |
| } | |
| // We don't support partial munmapping. | |
| if (map->length != length) { | |
| UNLOCK(lock); | |
| return -EINVAL; | |
| } | |
| // Remove map from linked list | |
| if (prev) { | |
| prev->next = map->next; | |
| } else { | |
| mappings = map->next; | |
| } | |
| UNLOCK(lock); | |
| if (!(map->flags & MAP_ANONYMOUS)) { | |
| _munmap_js(addr, length, map->prot, map->flags, map->fd, map->offset); | |
| } | |
| // Release the memory. | |
| if (map->allocated) { | |
| emscripten_builtin_free(map->addr); | |
| } | |
| if (!(map->flags & MAP_ANONYMOUS)) { | |
| emscripten_builtin_free(map); | |
| } | |
| // Success! | |
| return 0; | |
| } | |
| int __syscall_msync(intptr_t addr, size_t len, int flags) { | |
| LOCK(lock); | |
| struct map* map = find_mapping(addr, NULL); | |
| UNLOCK(lock); | |
| if (!map) { | |
| return -EINVAL; | |
| } | |
| if (map->flags & MAP_ANONYMOUS) { | |
| return 0; | |
| } | |
| return _msync_js(addr, len, map->prot, map->flags, map->fd, map->offset); | |
| } | |
| intptr_t __syscall_mmap2(intptr_t addr, size_t len, int prot, int flags, int fd, off_t offset) { | |
| if (addr != 0) { | |
| // We don't currently support location hints for the address of the mapping | |
| return -EINVAL; | |
| } | |
| offset *= SYSCALL_MMAP2_UNIT; | |
| struct map* new_map; | |
| // 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) { | |
| size_t alloc_len = ALIGN_TO(len, 16); | |
| // For anonymous maps, allocate that mapping at the end of the region. | |
| void* ptr = emscripten_builtin_memalign(WASM_PAGE_SIZE, alloc_len + sizeof(struct map)); | |
| if (!ptr) { | |
| return -ENOMEM; | |
| } | |
| memset(ptr, 0, alloc_len); | |
| new_map = (struct map*)((char*)ptr + alloc_len); | |
| new_map->addr = ptr; | |
| new_map->fd = -1; | |
| new_map->allocated = true; | |
| } else { | |
| new_map = emscripten_builtin_malloc(sizeof(struct map)); | |
| int rtn = | |
| _mmap_js(len, prot, flags, fd, offset, &new_map->allocated, &new_map->addr); | |
| if (rtn < 0) { | |
| emscripten_builtin_free(new_map); | |
| return rtn; | |
| } | |
| new_map->fd = fd; | |
| } | |
| new_map->length = len; | |
| new_map->flags = flags; | |
| new_map->offset = offset; | |
| new_map->prot = prot; | |
| LOCK(lock); | |
| new_map->next = mappings; | |
| mappings = new_map; | |
| UNLOCK(lock); | |
| return (long)new_map->addr; | |
| } | |
Xet Storage Details
- Size:
- 3.65 kB
- Xet hash:
- c3f8b01f3723797aaaff1f996bfb8cb5e150ffee61b07171ef00c9953b65cb64
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.