mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 16:28:30 +00:00
Make garbage collection thread safe
- You can now use _gc(malloc()) in multithreaded programs - This change fixes a bug where fork() on NT disabled TLS - Fixed TLS code morphing on XNU/NT, for R8-R15 registers
This commit is contained in:
parent
571c2c3c69
commit
0e2b1bfeed
37 changed files with 310 additions and 189 deletions
|
@ -20,12 +20,14 @@
|
|||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/gc.internal.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/runtime/gc.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/ezbench.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/thread/spawn.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
#define GC(x) _defer(Free, x)
|
||||
|
@ -77,6 +79,45 @@ TEST(gclongjmp, test) {
|
|||
free(x);
|
||||
}
|
||||
|
||||
void crawl(const char *path) {
|
||||
const char *dir;
|
||||
if (!strcmp(path, "/") || !strcmp(path, ".")) return;
|
||||
crawl(_gc(xdirname(path)));
|
||||
}
|
||||
|
||||
int Worker(void *arg, int tid) {
|
||||
crawl("a/b/c/d/a/b/c/d/a/b/c/d/a/b/c/d/a/b/c/d/a/b/c/d");
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(gc, torture) {
|
||||
int i, n = 32;
|
||||
struct spawn *t = gc(malloc(sizeof(struct spawn) * n));
|
||||
for (i = 0; i < n; ++i) ASSERT_SYS(0, 0, _spawn(Worker, 0, t + i));
|
||||
for (i = 0; i < n; ++i) EXPECT_SYS(0, 0, _join(t + i));
|
||||
}
|
||||
|
||||
void crawl2(jmp_buf jb, const char *path) {
|
||||
const char *dir;
|
||||
if (!strcmp(path, "/") || !strcmp(path, ".")) _gclongjmp(jb, 1);
|
||||
crawl2(jb, _gc(xdirname(path)));
|
||||
}
|
||||
|
||||
int Worker2(void *arg, int tid) {
|
||||
jmp_buf jb;
|
||||
if (!setjmp(jb)) {
|
||||
crawl2(jb, "a/b/c/d/a/b/c/d/a/b/c/d/a/b/c/d/a/b/c/d/a/b/c/d");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST(_gclongjmp, torture) {
|
||||
int i, n = 32;
|
||||
struct spawn *t = gc(malloc(sizeof(struct spawn) * n));
|
||||
for (i = 0; i < n; ++i) ASSERT_SYS(0, 0, _spawn(Worker2, 0, t + i));
|
||||
for (i = 0; i < n; ++i) EXPECT_SYS(0, 0, _join(t + i));
|
||||
}
|
||||
|
||||
dontinline void F1(void) {
|
||||
/* 3x slower than F2() but sooo worth it */
|
||||
gc(malloc(16));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue