From 7c65447a9a94da07c67479bc6332152f0cd91c55 Mon Sep 17 00:00:00 2001 From: flysand7 Date: Sun, 10 Sep 2023 14:38:27 +1100 Subject: [PATCH] Move tcb to include/cia-ld. Fix deadlock due to no spurious wakeup --- include/{cia/internal.h => cia-ld/tcb.h} | 19 +++++++++---------- loader/loader.c | 8 ++++---- os/linux/conf.h | 2 +- os/linux/entry.c | 2 +- os/linux/tinyrt-threads.c | 21 +++++++++++---------- 5 files changed, 26 insertions(+), 26 deletions(-) rename include/{cia/internal.h => cia-ld/tcb.h} (72%) diff --git a/include/cia/internal.h b/include/cia-ld/tcb.h similarity index 72% rename from include/cia/internal.h rename to include/cia-ld/tcb.h index 499d37a..95b2e08 100644 --- a/include/cia/internal.h +++ b/include/cia-ld/tcb.h @@ -1,11 +1,11 @@ + #pragma once #include -#include -struct Cia_CRT_Params typedef Cia_CRT_Params; -struct Cia_CRT_Params { +struct _LD_CRT_Params typedef _LD_CRT_Params; +struct _LD_CRT_Params { u64 stack_size; u64 tls_image_size; void *tls_image_base; @@ -18,13 +18,13 @@ struct Cia_CRT_Params { // would signal main thread that it has finished and exit without // cleaning up the resources (thrd_join does that for us) // If the thread is detached, it would clear it's resources and exit -#define _CIA_THREAD_BEHAVIOUR_NOT_SET 0x0 -#define _CIA_THREAD_BEHAVIOUR_JOIN 0x1 -#define _CIA_THREAD_BEHAVIOUR_DETACH 0x2 -#define _CIA_THREAD_BEHAVIOUR_FINISH 0x3 +#define _LD_THREAD_BEHAVIOUR_NOT_SET 0x0 +#define _LD_THREAD_BEHAVIOUR_JOIN 0x1 +#define _LD_THREAD_BEHAVIOUR_DETACH 0x2 +#define _LD_THREAD_BEHAVIOUR_FINISH 0x3 -struct Cia_TCB typedef Cia_TCB; -struct Cia_TCB { +struct _LD_Thread_Block typedef _LD_Thread_Block; +struct _LD_Thread_Block { /* +0x00 */ u64 thread_id; /* +0x08 */ u64 parent_id; /* +0x10 */ u32 thread_behaviour; /* One of the CIA_THREAD_BEHAVIOR_* constants */ @@ -35,4 +35,3 @@ struct Cia_TCB { /* +0x28 */ u64 stack_canary; }; - diff --git a/loader/loader.c b/loader/loader.c index aef90a4..088ff68 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -15,7 +15,7 @@ #include #include "../os/linux/tinyrt.c" -#include +#include #include #include "../src/cia-mem/util.c" @@ -351,7 +351,7 @@ static void ld_stage3_entry(u64 has_new_stack, void *ctx) { Stage3_Info_Struct *info = ctx; _dbg_printf("Stack: %x-%x\n", info->stack_base, (u8 *)info->stack_base+info->stack_size); // Set up the thread control block - Cia_TCB *tcb = cia_ptr_alignf((u8*)info->stack_base + info->tls_size, info->stack_size/2); + _LD_Thread_Block *tcb = cia_ptr_alignf((u8*)info->stack_base + info->tls_size, info->stack_size/2); tcb->thread_id = 0; tcb->stack_canary = 0x12345678fedcba98; // Copy TLS initialization image below TCB @@ -382,10 +382,10 @@ static void ld_stage3_entry(u64 has_new_stack, void *ctx) { sys_exit(1); } _dbg_printf("Entered loader stage 3. Entering main executable\n"); - Cia_CRT_Params params; + _LD_CRT_Params params; params.stack_size = info->stack_size/2; params.tls_image_size = info->tls_size; params.tls_image_base = info->tls_image; - void (*crt_entry)(Cia_CRT_Params *params) = elf_addr(info->app, ((Elf64_Ehdr *)info->app->base)->e_entry); + void (*crt_entry)(_LD_CRT_Params *params) = elf_addr(info->app, ((Elf64_Ehdr *)info->app->base)->e_entry); crt_entry(¶ms); } diff --git a/os/linux/conf.h b/os/linux/conf.h index 3a344be..36b47e3 100644 --- a/os/linux/conf.h +++ b/os/linux/conf.h @@ -5,7 +5,7 @@ static u64 cia_stack_size; static u64 cia_tls_image_size; static void *cia_tls_image_base; -#include +#include #include #include diff --git a/os/linux/entry.c b/os/linux/entry.c index d79f847..c2d67a0 100644 --- a/os/linux/entry.c +++ b/os/linux/entry.c @@ -14,7 +14,7 @@ void __stack_chk_fail(void) { extern int main(int argc, char **argv, char **envp); static void _fileapi_init(); -void _start(Cia_CRT_Params *params) { +void _start(_LD_CRT_Params *params) { cia_stack_size = params->stack_size; cia_tls_image_size = params->tls_image_size; cia_tls_image_base = params->tls_image_base; diff --git a/os/linux/tinyrt-threads.c b/os/linux/tinyrt-threads.c index ba7e0c5..3f778b8 100644 --- a/os/linux/tinyrt-threads.c +++ b/os/linux/tinyrt-threads.c @@ -24,7 +24,7 @@ static _RT_Status _rt_thread_create(_RT_Thread *thread, int (*thread_fn)(void *c } void *stack = (u8*)stack_base + 2*cia_stack_size; // Find the TLS base and initialize the tls - Cia_TCB *tcb = (void *)((u64)((u8 *)stack - 1) & ~(cia_stack_size - 1)); + _LD_Thread_Block *tcb = (void *)((u64)((u8 *)stack - 1) & ~(cia_stack_size - 1)); tcb->stack_canary = 0x12345678deadbeef; u8 *tls_base = (u8 *)tcb - cia_tls_image_size; for(int i = 0; i < cia_tls_image_size; ++i) { @@ -56,12 +56,12 @@ static _RT_Status _rt_thread_create(_RT_Thread *thread, int (*thread_fn)(void *c } void _rt_thread_finish(int exit_code) { - Cia_TCB *tcb = (void *)((u64)__builtin_frame_address(0) & ~(cia_stack_size - 1)); + _LD_Thread_Block *tcb = (void *)((u64)__builtin_frame_address(0) & ~(cia_stack_size - 1)); // Wait until the main thread decides what to do with the child thread - while(tcb->thread_behaviour == _CIA_THREAD_BEHAVIOUR_NOT_SET) { - syscall(SYS_futex, &tcb->thread_behaviour, FUTEX_WAIT, _CIA_THREAD_BEHAVIOUR_NOT_SET, NULL, 0, 0); + while(tcb->thread_behaviour == _LD_THREAD_BEHAVIOUR_NOT_SET) { + syscall(SYS_futex, &tcb->thread_behaviour, FUTEX_WAIT, _LD_THREAD_BEHAVIOUR_NOT_SET, NULL, 0, 0); } - if(tcb->thread_behaviour == _CIA_THREAD_BEHAVIOUR_JOIN) { + if(tcb->thread_behaviour == _LD_THREAD_BEHAVIOUR_JOIN) { tcb->exit_code = exit_code; // Idk if a memory barrier should be here, because we don't want the compiler // to reorder these two lines. If that happens, and we get a spurious wake up @@ -71,16 +71,17 @@ void _rt_thread_finish(int exit_code) { syscall(SYS_futex, &tcb->thread_finished, FUTEX_WAKE, 0, NULL, 0, 0); sys_exit(exit_code); } - else if(tcb->thread_behaviour == _CIA_THREAD_BEHAVIOUR_DETACH) { + else if(tcb->thread_behaviour == _LD_THREAD_BEHAVIOUR_DETACH) { // TODO: clean up the thread resources sys_exit(exit_code); } } static _RT_Status _rt_thread_join(_RT_Thread *thread, int *out_exit_code) { - Cia_TCB *tcb = thread->handle; + _LD_Thread_Block *tcb = thread->handle; // Signal the thread that we want it to be joined - tcb->thread_behaviour = _CIA_THREAD_BEHAVIOUR_JOIN; + tcb->thread_behaviour = _LD_THREAD_BEHAVIOUR_JOIN; + syscall(SYS_futex, &tcb->thread_behaviour, FUTEX_WAKE, 0, NULL, 0, 0); // Wait until the thread signals that it has completed the execution while(tcb->thread_finished != 1) { syscall(SYS_futex, &tcb->thread_finished, FUTEX_WAIT, 0, NULL, 0, 0); @@ -91,8 +92,8 @@ static _RT_Status _rt_thread_join(_RT_Thread *thread, int *out_exit_code) { } static _RT_Status _rt_thread_detach(_RT_Thread *thread) { - Cia_TCB *tcb = thread->handle; - tcb->thread_behaviour = _CIA_THREAD_BEHAVIOUR_DETACH; + _LD_Thread_Block *tcb = thread->handle; + tcb->thread_behaviour = _LD_THREAD_BEHAVIOUR_DETACH; return _RT_STATUS_OK; }