mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Further improve mmap() locking story
The way to use double linked lists, is to remove all the things you want to work on, insert them into a new list on the stack. Then once you have all the work items, you release the lock, do your work, and then lock it again, to add the shelled out items back to a global freelist.
This commit is contained in:
parent
98e684622b
commit
1bf2d8e308
8 changed files with 84 additions and 101 deletions
|
@ -18,6 +18,7 @@ CTL_A_CHECKS = \
|
|||
CTL_A_DIRECTDEPS = \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
THIRD_PARTY_GDTOA \
|
||||
|
|
|
@ -39,7 +39,6 @@ struct AddrSize {
|
|||
|
||||
extern struct Maps __maps;
|
||||
|
||||
void *randaddr(void);
|
||||
void __maps_init(void);
|
||||
void __maps_lock(void);
|
||||
void __maps_check(void);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/blockcancel.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/state.internal.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
@ -187,10 +188,10 @@ int __munmap(char *addr, size_t size, bool untrack_only) {
|
|||
!size || (uintptr_t)addr + size < size)
|
||||
return einval();
|
||||
|
||||
// untrack and delete mapping
|
||||
// untrack mappings
|
||||
int rc = 0;
|
||||
struct Dll *delete = 0;
|
||||
__maps_lock();
|
||||
StartOver:;
|
||||
struct Map *map = __maps.maps;
|
||||
struct Map **prev = &__maps.maps;
|
||||
while (map) {
|
||||
|
@ -202,30 +203,10 @@ StartOver:;
|
|||
if (addr <= map_addr && addr + PGUP(size) >= map_addr + PGUP(map_size)) {
|
||||
// remove mapping completely
|
||||
dll_remove(&__maps.used, &map->elem);
|
||||
dll_make_first(&delete, &map->elem);
|
||||
*prev = next;
|
||||
__maps.pages -= (map_size + pagesz - 1) / pagesz;
|
||||
__maps.count -= 1;
|
||||
if (untrack_only) {
|
||||
__maps_free(map);
|
||||
__maps_check();
|
||||
} else {
|
||||
__maps_unlock();
|
||||
if (!IsWindows()) {
|
||||
ASSERT(addr <= map_addr);
|
||||
ASSERT(map_addr + PGUP(map_size) <= addr + PGUP(size));
|
||||
if (sys_munmap(map_addr, map_size))
|
||||
rc = -1;
|
||||
} else {
|
||||
if (!UnmapViewOfFile(map_addr))
|
||||
rc = -1;
|
||||
if (!CloseHandle(map->h))
|
||||
rc = -1;
|
||||
}
|
||||
__maps_lock();
|
||||
__maps_free(map);
|
||||
__maps_check();
|
||||
goto StartOver;
|
||||
}
|
||||
map = next;
|
||||
continue;
|
||||
} else if (IsWindows()) {
|
||||
|
@ -240,35 +221,34 @@ StartOver:;
|
|||
size_t right = map_size - left;
|
||||
ASSERT(right > 0);
|
||||
ASSERT(left > 0);
|
||||
struct Map *leftmap;
|
||||
if ((leftmap = __maps_alloc())) {
|
||||
map->addr += left;
|
||||
map->size = right;
|
||||
if (!(map->flags & MAP_ANONYMOUS))
|
||||
map->off += left;
|
||||
__maps.pages -= (left + pagesz - 1) / pagesz;
|
||||
__maps_check();
|
||||
if (!untrack_only) {
|
||||
__maps_unlock();
|
||||
ASSERT(addr <= map_addr);
|
||||
ASSERT(map_addr + PGUP(left) <= addr + PGUP(size));
|
||||
if (sys_munmap(map_addr, left) == -1)
|
||||
leftmap->addr = map_addr;
|
||||
leftmap->size = left;
|
||||
dll_make_first(&delete, &leftmap->elem);
|
||||
} else {
|
||||
rc = -1;
|
||||
__maps_lock();
|
||||
goto StartOver;
|
||||
}
|
||||
} else if (addr + PGUP(size) >= map_addr + PGUP(map_size)) {
|
||||
// shave off righthand side of mapping
|
||||
size_t left = addr - map_addr;
|
||||
size_t right = map_addr + map_size - addr;
|
||||
struct Map *rightmap;
|
||||
if ((rightmap = __maps_alloc())) {
|
||||
map->size = left;
|
||||
__maps.pages -= (right + pagesz - 1) / pagesz;
|
||||
__maps_check();
|
||||
if (!untrack_only) {
|
||||
__maps_unlock();
|
||||
ASSERT(PGUP(right) <= PGUP(size));
|
||||
if (sys_munmap(addr, right) == -1)
|
||||
rightmap->addr = addr;
|
||||
rightmap->size = right;
|
||||
dll_make_first(&delete, &rightmap->elem);
|
||||
} else {
|
||||
rc = -1;
|
||||
__maps_lock();
|
||||
goto StartOver;
|
||||
}
|
||||
} else {
|
||||
// punch hole in mapping
|
||||
|
@ -277,6 +257,8 @@ StartOver:;
|
|||
size_t right = map_size - middle - left;
|
||||
struct Map *leftmap;
|
||||
if ((leftmap = __maps_alloc())) {
|
||||
struct Map *middlemap;
|
||||
if ((middlemap = __maps_alloc())) {
|
||||
leftmap->next = map;
|
||||
leftmap->addr = map_addr;
|
||||
leftmap->size = left;
|
||||
|
@ -292,12 +274,11 @@ StartOver:;
|
|||
__maps.pages -= (middle + pagesz - 1) / pagesz;
|
||||
__maps.count += 1;
|
||||
__maps_check();
|
||||
if (!untrack_only) {
|
||||
__maps_unlock();
|
||||
if (sys_munmap(addr, size) == -1)
|
||||
middlemap->addr = addr;
|
||||
middlemap->size = size;
|
||||
dll_make_first(&delete, &middlemap->elem);
|
||||
} else {
|
||||
rc = -1;
|
||||
__maps_lock();
|
||||
goto StartOver;
|
||||
}
|
||||
} else {
|
||||
rc = -1;
|
||||
|
@ -309,6 +290,34 @@ StartOver:;
|
|||
}
|
||||
__maps_unlock();
|
||||
|
||||
// delete mappings
|
||||
for (struct Dll *e = dll_first(delete); e; e = dll_next(delete, e)) {
|
||||
map = MAP_CONTAINER(e);
|
||||
if (!untrack_only) {
|
||||
if (!IsWindows()) {
|
||||
if (sys_munmap(map->addr, map->size))
|
||||
rc = -1;
|
||||
} else {
|
||||
if (!UnmapViewOfFile(map->addr))
|
||||
rc = -1;
|
||||
if (!CloseHandle(map->h))
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free mappings
|
||||
if (!dll_is_empty(delete)) {
|
||||
__maps_lock();
|
||||
struct Dll *e;
|
||||
while ((e = dll_first(delete))) {
|
||||
dll_remove(&delete, e);
|
||||
__maps_free(MAP_CONTAINER(e));
|
||||
}
|
||||
__maps_check();
|
||||
__maps_unlock();
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2024 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
void *randaddr(void) {
|
||||
static unsigned long lcg = 1;
|
||||
lcg *= 6364136223846793005;
|
||||
lcg += 1442695040888963407;
|
||||
return (void *)(lcg >> 48 << 28);
|
||||
}
|
|
@ -64,11 +64,9 @@ int __reservefd_unlocked(int start) {
|
|||
int fd, f1, f2;
|
||||
for (;;) {
|
||||
f1 = atomic_load_explicit(&g_fds.f, memory_order_acquire);
|
||||
for (fd = MAX(start, f1); fd < g_fds.n; ++fd) {
|
||||
if (!g_fds.p[fd].kind) {
|
||||
for (fd = MAX(start, f1); fd < g_fds.n; ++fd)
|
||||
if (!g_fds.p[fd].kind)
|
||||
break;
|
||||
}
|
||||
}
|
||||
fd = __ensurefds_unlocked(fd);
|
||||
bzero(g_fds.p + fd, sizeof(*g_fds.p));
|
||||
if (_cmpxchg(&g_fds.p[fd].kind, kFdEmpty, kFdReserved)) {
|
||||
|
|
|
@ -58,7 +58,7 @@ static struct ZiposHandle *__zipos_alloc(struct Zipos *zipos, size_t size) {
|
|||
granularity = __granularity();
|
||||
mapsize = sizeof(struct ZiposHandle) + size;
|
||||
mapsize = (mapsize + granularity - 1) & -granularity;
|
||||
if ((h = __mmap(randaddr(), mapsize, PROT_READ | PROT_WRITE,
|
||||
if ((h = __mmap(0, mapsize, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED) {
|
||||
h->size = size;
|
||||
h->zipos = zipos;
|
||||
|
|
|
@ -17,6 +17,7 @@ TEST_CTL_DIRECTDEPS = \
|
|||
LIBC_INTRIN \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STDIO \
|
||||
LIBC_STDIO \
|
||||
LIBC_THREAD \
|
||||
|
|
|
@ -90,10 +90,10 @@ fetch() {
|
|||
OLD=$PWD
|
||||
cd "$OUTDIR/"
|
||||
if [ ! -x bin/x86_64-linux-cosmo-gcc ]; then
|
||||
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.44/aarch64-gcc.zip
|
||||
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.45/aarch64-gcc.zip
|
||||
unzip aarch64-gcc.zip
|
||||
rm -f aarch64-gcc.zip
|
||||
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.44/x86_64-gcc.zip
|
||||
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.45/x86_64-gcc.zip
|
||||
unzip x86_64-gcc.zip
|
||||
rm -f x86_64-gcc.zip
|
||||
fi
|
||||
|
|
Loading…
Reference in a new issue