mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-14 23:09:16 +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,8 +20,6 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/notice.inc"
|
||||
|
||||
#define INITIAL_CAPACITY 4
|
||||
|
||||
nop
|
||||
|
||||
// Invokes deferred function calls.
|
||||
|
@ -34,9 +32,12 @@
|
|||
//
|
||||
// @param rax,rdx,xmm0,xmm1,st0,st1 is return value
|
||||
// @see test/libc/runtime/gc_test.c
|
||||
__gc: decq __garbage(%rip)
|
||||
mov __garbage(%rip),%r8
|
||||
mov __garbage+16(%rip),%r9
|
||||
// @threadsafe
|
||||
__gc: mov %fs:0,%rcx # __get_tls()
|
||||
mov 0x18(%rcx),%rcx # cthread_t::garbages
|
||||
decl (%rcx) # ++g->i
|
||||
mov (%rcx),%r8d # r8 = g->i
|
||||
mov 8(%rcx),%r9 # r9 = g->p
|
||||
js 9f
|
||||
shl $5,%r8
|
||||
lea (%r9,%r8),%r8
|
||||
|
@ -55,25 +56,5 @@ __gc: decq __garbage(%rip)
|
|||
mov -8(%rbp),%rax
|
||||
leave
|
||||
ret
|
||||
9: hlt
|
||||
9: ud2
|
||||
.endfn __gc,globl,hidden
|
||||
|
||||
.bss
|
||||
.align 8
|
||||
__garbage:
|
||||
.quad 0 # garbage.i
|
||||
.quad 0 # garbage.n
|
||||
.quad 0 # garbage.p
|
||||
.rept INITIAL_CAPACITY
|
||||
.quad 0 # garbage.p[𝑖].frame
|
||||
.quad 0 # garbage.p[𝑖].fn
|
||||
.quad 0 # garbage.p[𝑖].arg
|
||||
.quad 0 # garbage.p[𝑖].ret
|
||||
.endr
|
||||
.endobj __garbage,globl,hidden
|
||||
.previous
|
||||
|
||||
.init.start 100,_init_garbage
|
||||
movb $INITIAL_CAPACITY,__garbage+8(%rip)
|
||||
movl $__garbage+24,__garbage+16(%rip)
|
||||
.init.end 100,_init_garbage
|
||||
|
|
|
@ -12,13 +12,10 @@ struct Garbage {
|
|||
};
|
||||
|
||||
struct Garbages {
|
||||
size_t i, n;
|
||||
int i, n;
|
||||
struct Garbage *p;
|
||||
struct Garbage initmem[1];
|
||||
};
|
||||
|
||||
extern struct Garbages __garbage;
|
||||
|
||||
int64_t __gc(void);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -28,29 +28,33 @@
|
|||
// @param esi is returned by setjmp() invocation (coerced nonzero)
|
||||
// @assume system five nexgen32e abi conformant
|
||||
// @see examples/ctrlc.c
|
||||
// @threadsafe
|
||||
// @noreturn
|
||||
_gclongjmp:
|
||||
push %rbp
|
||||
mov %rsp,%rbp
|
||||
.profilable
|
||||
lea __garbage(%rip),%r12
|
||||
mov (%r12),%r13 # garbage.i
|
||||
test %r13,%r13
|
||||
mov %fs:0,%r12 # __get_tls()
|
||||
mov 0x18(%r12),%r12 # cthread_t::garbages
|
||||
test %r12,%r12
|
||||
jz 0f
|
||||
movl (%r12),%r13d # garbages.i
|
||||
test %r13d,%r13d
|
||||
jnz .L.unwind.destructors
|
||||
0: jmp longjmp
|
||||
.L.unwind.destructors:
|
||||
push %rdi
|
||||
push %rsi
|
||||
mov 16(%r12),%r14 # garbage.p
|
||||
mov 8(%r12),%r14 # garbages.p
|
||||
mov (%rdi),%r15 # jmp_buf[0] is new %rsp
|
||||
shl $5,%r13 # log2(sizeof(struct Garbage))
|
||||
1: sub $32,%r13 # 𝑖--
|
||||
js 2f
|
||||
cmp (%r14,%r13),%r15 # new %rsp > garbage.p[𝑖].frame
|
||||
cmp (%r14,%r13),%r15 # new %rsp > garbages.p[𝑖].frame
|
||||
jbe 2f
|
||||
mov 16(%r14,%r13),%rdi # garbage.p[𝑖].arg
|
||||
callq *8(%r14,%r13) # garbage.p[𝑖].fn
|
||||
decq (%r12) # garbage.i--
|
||||
mov 16(%r14,%r13),%rdi # garbages.p[𝑖].arg
|
||||
callq *8(%r14,%r13) # garbages.p[𝑖].fn
|
||||
decl (%r12) # garbages.i--
|
||||
jmp 1b
|
||||
2: pop %rsi
|
||||
pop %rdi
|
||||
|
|
|
@ -7,6 +7,7 @@ extern int __threaded;
|
|||
extern bool __tls_enabled;
|
||||
extern unsigned __tls_index;
|
||||
|
||||
void TlsIsRequired(void);
|
||||
void *__initialize_tls(char[64]);
|
||||
void __install_tls(char[64]);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue