mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 05:42:29 +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
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -36,6 +36,7 @@ TEST_LIBC_NEXGEN32E_DIRECTDEPS = \
|
|||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_THREAD \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_X \
|
||||
TOOL_VIZ_LIB \
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
|
|
|
@ -34,6 +34,7 @@ TEST_LIBC_SOCK_DIRECTDEPS = \
|
|||
LIBC_STR \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_LOG \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_TESTLIB \
|
||||
LIBC_X \
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue