mirror of https://github.com/flysand7/ciabatta.git
Move tcb to include/cia-ld. Fix deadlock due to no spurious wakeup
This commit is contained in:
parent
8c563ec1b2
commit
7c65447a9a
|
@ -1,11 +1,11 @@
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cia/def.h>
|
#include <cia/def.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
struct Cia_CRT_Params typedef Cia_CRT_Params;
|
struct _LD_CRT_Params typedef _LD_CRT_Params;
|
||||||
struct Cia_CRT_Params {
|
struct _LD_CRT_Params {
|
||||||
u64 stack_size;
|
u64 stack_size;
|
||||||
u64 tls_image_size;
|
u64 tls_image_size;
|
||||||
void *tls_image_base;
|
void *tls_image_base;
|
||||||
|
@ -18,13 +18,13 @@ struct Cia_CRT_Params {
|
||||||
// would signal main thread that it has finished and exit without
|
// would signal main thread that it has finished and exit without
|
||||||
// cleaning up the resources (thrd_join does that for us)
|
// cleaning up the resources (thrd_join does that for us)
|
||||||
// If the thread is detached, it would clear it's resources and exit
|
// If the thread is detached, it would clear it's resources and exit
|
||||||
#define _CIA_THREAD_BEHAVIOUR_NOT_SET 0x0
|
#define _LD_THREAD_BEHAVIOUR_NOT_SET 0x0
|
||||||
#define _CIA_THREAD_BEHAVIOUR_JOIN 0x1
|
#define _LD_THREAD_BEHAVIOUR_JOIN 0x1
|
||||||
#define _CIA_THREAD_BEHAVIOUR_DETACH 0x2
|
#define _LD_THREAD_BEHAVIOUR_DETACH 0x2
|
||||||
#define _CIA_THREAD_BEHAVIOUR_FINISH 0x3
|
#define _LD_THREAD_BEHAVIOUR_FINISH 0x3
|
||||||
|
|
||||||
struct Cia_TCB typedef Cia_TCB;
|
struct _LD_Thread_Block typedef _LD_Thread_Block;
|
||||||
struct Cia_TCB {
|
struct _LD_Thread_Block {
|
||||||
/* +0x00 */ u64 thread_id;
|
/* +0x00 */ u64 thread_id;
|
||||||
/* +0x08 */ u64 parent_id;
|
/* +0x08 */ u64 parent_id;
|
||||||
/* +0x10 */ u32 thread_behaviour; /* One of the CIA_THREAD_BEHAVIOR_* constants */
|
/* +0x10 */ u32 thread_behaviour; /* One of the CIA_THREAD_BEHAVIOR_* constants */
|
||||||
|
@ -35,4 +35,3 @@ struct Cia_TCB {
|
||||||
/* +0x28 */ u64 stack_canary;
|
/* +0x28 */ u64 stack_canary;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#include <tinyrt.h>
|
#include <tinyrt.h>
|
||||||
#include "../os/linux/tinyrt.c"
|
#include "../os/linux/tinyrt.c"
|
||||||
|
|
||||||
#include <cia/internal.h>
|
#include <cia-ld/tcb.h>
|
||||||
|
|
||||||
#include <cia/mem.h>
|
#include <cia/mem.h>
|
||||||
#include "../src/cia-mem/util.c"
|
#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;
|
Stage3_Info_Struct *info = ctx;
|
||||||
_dbg_printf("Stack: %x-%x\n", info->stack_base, (u8 *)info->stack_base+info->stack_size);
|
_dbg_printf("Stack: %x-%x\n", info->stack_base, (u8 *)info->stack_base+info->stack_size);
|
||||||
// Set up the thread control block
|
// 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->thread_id = 0;
|
||||||
tcb->stack_canary = 0x12345678fedcba98;
|
tcb->stack_canary = 0x12345678fedcba98;
|
||||||
// Copy TLS initialization image below TCB
|
// Copy TLS initialization image below TCB
|
||||||
|
@ -382,10 +382,10 @@ static void ld_stage3_entry(u64 has_new_stack, void *ctx) {
|
||||||
sys_exit(1);
|
sys_exit(1);
|
||||||
}
|
}
|
||||||
_dbg_printf("Entered loader stage 3. Entering main executable\n");
|
_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.stack_size = info->stack_size/2;
|
||||||
params.tls_image_size = info->tls_size;
|
params.tls_image_size = info->tls_size;
|
||||||
params.tls_image_base = info->tls_image;
|
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);
|
crt_entry(¶ms);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ static u64 cia_stack_size;
|
||||||
static u64 cia_tls_image_size;
|
static u64 cia_tls_image_size;
|
||||||
static void *cia_tls_image_base;
|
static void *cia_tls_image_base;
|
||||||
|
|
||||||
#include <cia/internal.h>
|
#include <cia-ld/tcb.h>
|
||||||
|
|
||||||
#include <linux/futex.h>
|
#include <linux/futex.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
|
@ -14,7 +14,7 @@ void __stack_chk_fail(void) {
|
||||||
extern int main(int argc, char **argv, char **envp);
|
extern int main(int argc, char **argv, char **envp);
|
||||||
static void _fileapi_init();
|
static void _fileapi_init();
|
||||||
|
|
||||||
void _start(Cia_CRT_Params *params) {
|
void _start(_LD_CRT_Params *params) {
|
||||||
cia_stack_size = params->stack_size;
|
cia_stack_size = params->stack_size;
|
||||||
cia_tls_image_size = params->tls_image_size;
|
cia_tls_image_size = params->tls_image_size;
|
||||||
cia_tls_image_base = params->tls_image_base;
|
cia_tls_image_base = params->tls_image_base;
|
||||||
|
|
|
@ -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;
|
void *stack = (u8*)stack_base + 2*cia_stack_size;
|
||||||
// Find the TLS base and initialize the tls
|
// 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;
|
tcb->stack_canary = 0x12345678deadbeef;
|
||||||
u8 *tls_base = (u8 *)tcb - cia_tls_image_size;
|
u8 *tls_base = (u8 *)tcb - cia_tls_image_size;
|
||||||
for(int i = 0; i < cia_tls_image_size; ++i) {
|
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) {
|
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
|
// Wait until the main thread decides what to do with the child thread
|
||||||
while(tcb->thread_behaviour == _CIA_THREAD_BEHAVIOUR_NOT_SET) {
|
while(tcb->thread_behaviour == _LD_THREAD_BEHAVIOUR_NOT_SET) {
|
||||||
syscall(SYS_futex, &tcb->thread_behaviour, FUTEX_WAIT, _CIA_THREAD_BEHAVIOUR_NOT_SET, NULL, 0, 0);
|
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;
|
tcb->exit_code = exit_code;
|
||||||
// Idk if a memory barrier should be here, because we don't want the compiler
|
// 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
|
// 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);
|
syscall(SYS_futex, &tcb->thread_finished, FUTEX_WAKE, 0, NULL, 0, 0);
|
||||||
sys_exit(exit_code);
|
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
|
// TODO: clean up the thread resources
|
||||||
sys_exit(exit_code);
|
sys_exit(exit_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static _RT_Status _rt_thread_join(_RT_Thread *thread, int *out_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
|
// 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
|
// Wait until the thread signals that it has completed the execution
|
||||||
while(tcb->thread_finished != 1) {
|
while(tcb->thread_finished != 1) {
|
||||||
syscall(SYS_futex, &tcb->thread_finished, FUTEX_WAIT, 0, NULL, 0, 0);
|
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) {
|
static _RT_Status _rt_thread_detach(_RT_Thread *thread) {
|
||||||
Cia_TCB *tcb = thread->handle;
|
_LD_Thread_Block *tcb = thread->handle;
|
||||||
tcb->thread_behaviour = _CIA_THREAD_BEHAVIOUR_DETACH;
|
tcb->thread_behaviour = _LD_THREAD_BEHAVIOUR_DETACH;
|
||||||
return _RT_STATUS_OK;
|
return _RT_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue