Skip to content

Commit 1bf2d8e

Browse files
committed
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.
1 parent 98e6846 commit 1bf2d8e

File tree

8 files changed

+84
-101
lines changed

8 files changed

+84
-101
lines changed

ctl/BUILD.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ CTL_A_CHECKS = \
1818
CTL_A_DIRECTDEPS = \
1919
LIBC_INTRIN \
2020
LIBC_MEM \
21+
LIBC_NEXGEN32E \
2122
LIBC_STDIO \
2223
LIBC_STR \
2324
THIRD_PARTY_GDTOA \

libc/intrin/maps.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ struct AddrSize {
3939

4040
extern struct Maps __maps;
4141

42-
void *randaddr(void);
4342
void __maps_init(void);
4443
void __maps_lock(void);
4544
void __maps_check(void);

libc/intrin/mmap.c

Lines changed: 77 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "libc/calls/blockcancel.internal.h"
2222
#include "libc/calls/calls.h"
2323
#include "libc/calls/internal.h"
24+
#include "libc/calls/state.internal.h"
2425
#include "libc/calls/struct/sigset.internal.h"
2526
#include "libc/calls/syscall-sysv.internal.h"
2627
#include "libc/dce.h"
@@ -187,10 +188,10 @@ int __munmap(char *addr, size_t size, bool untrack_only) {
187188
!size || (uintptr_t)addr + size < size)
188189
return einval();
189190

190-
// untrack and delete mapping
191+
// untrack mappings
191192
int rc = 0;
193+
struct Dll *delete = 0;
192194
__maps_lock();
193-
StartOver:;
194195
struct Map *map = __maps.maps;
195196
struct Map **prev = &__maps.maps;
196197
while (map) {
@@ -202,30 +203,10 @@ StartOver:;
202203
if (addr <= map_addr && addr + PGUP(size) >= map_addr + PGUP(map_size)) {
203204
// remove mapping completely
204205
dll_remove(&__maps.used, &map->elem);
206+
dll_make_first(&delete, &map->elem);
205207
*prev = next;
206208
__maps.pages -= (map_size + pagesz - 1) / pagesz;
207209
__maps.count -= 1;
208-
if (untrack_only) {
209-
__maps_free(map);
210-
__maps_check();
211-
} else {
212-
__maps_unlock();
213-
if (!IsWindows()) {
214-
ASSERT(addr <= map_addr);
215-
ASSERT(map_addr + PGUP(map_size) <= addr + PGUP(size));
216-
if (sys_munmap(map_addr, map_size))
217-
rc = -1;
218-
} else {
219-
if (!UnmapViewOfFile(map_addr))
220-
rc = -1;
221-
if (!CloseHandle(map->h))
222-
rc = -1;
223-
}
224-
__maps_lock();
225-
__maps_free(map);
226-
__maps_check();
227-
goto StartOver;
228-
}
229210
map = next;
230211
continue;
231212
} else if (IsWindows()) {
@@ -240,35 +221,34 @@ StartOver:;
240221
size_t right = map_size - left;
241222
ASSERT(right > 0);
242223
ASSERT(left > 0);
243-
map->addr += left;
244-
map->size = right;
245-
if (!(map->flags & MAP_ANONYMOUS))
246-
map->off += left;
247-
__maps.pages -= (left + pagesz - 1) / pagesz;
248-
__maps_check();
249-
if (!untrack_only) {
250-
__maps_unlock();
251-
ASSERT(addr <= map_addr);
252-
ASSERT(map_addr + PGUP(left) <= addr + PGUP(size));
253-
if (sys_munmap(map_addr, left) == -1)
254-
rc = -1;
255-
__maps_lock();
256-
goto StartOver;
224+
struct Map *leftmap;
225+
if ((leftmap = __maps_alloc())) {
226+
map->addr += left;
227+
map->size = right;
228+
if (!(map->flags & MAP_ANONYMOUS))
229+
map->off += left;
230+
__maps.pages -= (left + pagesz - 1) / pagesz;
231+
__maps_check();
232+
leftmap->addr = map_addr;
233+
leftmap->size = left;
234+
dll_make_first(&delete, &leftmap->elem);
235+
} else {
236+
rc = -1;
257237
}
258238
} else if (addr + PGUP(size) >= map_addr + PGUP(map_size)) {
259239
// shave off righthand side of mapping
260240
size_t left = addr - map_addr;
261241
size_t right = map_addr + map_size - addr;
262-
map->size = left;
263-
__maps.pages -= (right + pagesz - 1) / pagesz;
264-
__maps_check();
265-
if (!untrack_only) {
266-
__maps_unlock();
267-
ASSERT(PGUP(right) <= PGUP(size));
268-
if (sys_munmap(addr, right) == -1)
269-
rc = -1;
270-
__maps_lock();
271-
goto StartOver;
242+
struct Map *rightmap;
243+
if ((rightmap = __maps_alloc())) {
244+
map->size = left;
245+
__maps.pages -= (right + pagesz - 1) / pagesz;
246+
__maps_check();
247+
rightmap->addr = addr;
248+
rightmap->size = right;
249+
dll_make_first(&delete, &rightmap->elem);
250+
} else {
251+
rc = -1;
272252
}
273253
} else {
274254
// punch hole in mapping
@@ -277,27 +257,28 @@ StartOver:;
277257
size_t right = map_size - middle - left;
278258
struct Map *leftmap;
279259
if ((leftmap = __maps_alloc())) {
280-
leftmap->next = map;
281-
leftmap->addr = map_addr;
282-
leftmap->size = left;
283-
leftmap->off = map->off;
284-
leftmap->prot = map->prot;
285-
leftmap->flags = map->flags;
286-
map->addr += left + middle;
287-
map->size = right;
288-
if (!(map->flags & MAP_ANONYMOUS))
289-
map->off += left + middle;
290-
dll_make_first(&__maps.used, &leftmap->elem);
291-
*prev = leftmap;
292-
__maps.pages -= (middle + pagesz - 1) / pagesz;
293-
__maps.count += 1;
294-
__maps_check();
295-
if (!untrack_only) {
296-
__maps_unlock();
297-
if (sys_munmap(addr, size) == -1)
298-
rc = -1;
299-
__maps_lock();
300-
goto StartOver;
260+
struct Map *middlemap;
261+
if ((middlemap = __maps_alloc())) {
262+
leftmap->next = map;
263+
leftmap->addr = map_addr;
264+
leftmap->size = left;
265+
leftmap->off = map->off;
266+
leftmap->prot = map->prot;
267+
leftmap->flags = map->flags;
268+
map->addr += left + middle;
269+
map->size = right;
270+
if (!(map->flags & MAP_ANONYMOUS))
271+
map->off += left + middle;
272+
dll_make_first(&__maps.used, &leftmap->elem);
273+
*prev = leftmap;
274+
__maps.pages -= (middle + pagesz - 1) / pagesz;
275+
__maps.count += 1;
276+
__maps_check();
277+
middlemap->addr = addr;
278+
middlemap->size = size;
279+
dll_make_first(&delete, &middlemap->elem);
280+
} else {
281+
rc = -1;
301282
}
302283
} else {
303284
rc = -1;
@@ -309,6 +290,34 @@ StartOver:;
309290
}
310291
__maps_unlock();
311292

293+
// delete mappings
294+
for (struct Dll *e = dll_first(delete); e; e = dll_next(delete, e)) {
295+
map = MAP_CONTAINER(e);
296+
if (!untrack_only) {
297+
if (!IsWindows()) {
298+
if (sys_munmap(map->addr, map->size))
299+
rc = -1;
300+
} else {
301+
if (!UnmapViewOfFile(map->addr))
302+
rc = -1;
303+
if (!CloseHandle(map->h))
304+
rc = -1;
305+
}
306+
}
307+
}
308+
309+
// free mappings
310+
if (!dll_is_empty(delete)) {
311+
__maps_lock();
312+
struct Dll *e;
313+
while ((e = dll_first(delete))) {
314+
dll_remove(&delete, e);
315+
__maps_free(MAP_CONTAINER(e));
316+
}
317+
__maps_check();
318+
__maps_unlock();
319+
}
320+
312321
return rc;
313322
}
314323

libc/intrin/randaddr.c

Lines changed: 0 additions & 25 deletions
This file was deleted.

libc/intrin/reservefd.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,9 @@ int __reservefd_unlocked(int start) {
6464
int fd, f1, f2;
6565
for (;;) {
6666
f1 = atomic_load_explicit(&g_fds.f, memory_order_acquire);
67-
for (fd = MAX(start, f1); fd < g_fds.n; ++fd) {
68-
if (!g_fds.p[fd].kind) {
67+
for (fd = MAX(start, f1); fd < g_fds.n; ++fd)
68+
if (!g_fds.p[fd].kind)
6969
break;
70-
}
71-
}
7270
fd = __ensurefds_unlocked(fd);
7371
bzero(g_fds.p + fd, sizeof(*g_fds.p));
7472
if (_cmpxchg(&g_fds.p[fd].kind, kFdEmpty, kFdReserved)) {

libc/runtime/zipos-open.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static struct ZiposHandle *__zipos_alloc(struct Zipos *zipos, size_t size) {
5858
granularity = __granularity();
5959
mapsize = sizeof(struct ZiposHandle) + size;
6060
mapsize = (mapsize + granularity - 1) & -granularity;
61-
if ((h = __mmap(randaddr(), mapsize, PROT_READ | PROT_WRITE,
61+
if ((h = __mmap(0, mapsize, PROT_READ | PROT_WRITE,
6262
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) != MAP_FAILED) {
6363
h->size = size;
6464
h->zipos = zipos;

test/ctl/BUILD.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ TEST_CTL_DIRECTDEPS = \
1717
LIBC_INTRIN \
1818
LIBC_LOG \
1919
LIBC_MEM \
20+
LIBC_NEXGEN32E \
2021
LIBC_STDIO \
2122
LIBC_STDIO \
2223
LIBC_THREAD \

tool/cosmocc/package.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ fetch() {
9090
OLD=$PWD
9191
cd "$OUTDIR/"
9292
if [ ! -x bin/x86_64-linux-cosmo-gcc ]; then
93-
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.44/aarch64-gcc.zip
93+
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.45/aarch64-gcc.zip
9494
unzip aarch64-gcc.zip
9595
rm -f aarch64-gcc.zip
96-
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.44/x86_64-gcc.zip
96+
fetch https://github.com/ahgamut/superconfigure/releases/download/z0.0.45/x86_64-gcc.zip
9797
unzip x86_64-gcc.zip
9898
rm -f x86_64-gcc.zip
9999
fi

0 commit comments

Comments
 (0)