mirror of https://github.com/flysand7/ciabatta.git
fix joins & detaches
This commit is contained in:
parent
00d284215c
commit
35f10c78b7
|
@ -2,7 +2,9 @@
|
|||
bits 64
|
||||
|
||||
section .text
|
||||
global _cia_start_thread
|
||||
global _rt_thread_start
|
||||
|
||||
extern _rt_thread_finish
|
||||
|
||||
; flags, &stack[-2], &parent_tid, &child_tid, 0
|
||||
|
||||
|
@ -23,7 +25,7 @@ global _cia_start_thread
|
|||
; 0 if returning as a parent
|
||||
; 1 if returning as a child
|
||||
; negative value if there was an error making the thread
|
||||
_cia_start_thread:
|
||||
_rt_thread_start:
|
||||
mov r10, rcx
|
||||
; Setup child stack
|
||||
sub rsi, 24
|
||||
|
@ -43,10 +45,9 @@ _cia_start_thread:
|
|||
pop rax ; thread_fn
|
||||
pop rdi ; ctx
|
||||
call rax
|
||||
; Make return value the first arg and call exit syscall
|
||||
; Make return value the first arg and call thread finish routine
|
||||
mov rdi, rax
|
||||
mov rax, 60
|
||||
syscall
|
||||
call _rt_thread_finish
|
||||
; Just to be sure...
|
||||
hlt
|
||||
.exit:
|
||||
|
|
1
cia.c
1
cia.c
|
@ -3,7 +3,6 @@
|
|||
|
||||
// Base includes
|
||||
#include <cia/def.h>
|
||||
#include <cia/internal.h>
|
||||
|
||||
// Platform-dependent sources
|
||||
#include _CIA_OS_CONF
|
||||
|
|
|
@ -11,13 +11,28 @@ struct Cia_CRT_Params {
|
|||
void *tls_image_base;
|
||||
};
|
||||
|
||||
// These control how the thread should behave once it's terminated
|
||||
// if the main thread didn't call join nor detach, the thread
|
||||
// would just wait until one of them is set.
|
||||
// If the thread is joined,
|
||||
// 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
|
||||
|
||||
struct Cia_TCB typedef Cia_TCB;
|
||||
struct Cia_TCB {
|
||||
u64 thread_id;
|
||||
u64 parent_id;
|
||||
u64 pad0[3];
|
||||
u64 stack_canary;
|
||||
u64 pad1[2];
|
||||
/* +0x00 */ u64 thread_id;
|
||||
/* +0x08 */ u64 parent_id;
|
||||
/* +0x10 */ u32 thread_behaviour; /* One of the CIA_THREAD_BEHAVIOR_* constants */
|
||||
/* +0x14 */ u32 thread_finished;
|
||||
/* +0x18 */ u32 pad0;
|
||||
/* +0x1c */ i32 exit_code;
|
||||
/* +0x20 */ u64 pad1;
|
||||
/* +0x28 */ u64 stack_canary;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -17,3 +17,5 @@ enum {
|
|||
};
|
||||
|
||||
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
|
||||
int thrd_join(thrd_t thr, int *out_exit_code);
|
||||
int thrd_detach(thrd_t thr);
|
|
@ -55,7 +55,7 @@ struct _RT_Thread {
|
|||
};
|
||||
static _RT_Status _rt_thread_current(_RT_Thread *thread);
|
||||
static _RT_Status _rt_thread_create(_RT_Thread *thread, int (*thread_fn)(void *ctx), void *ctx);
|
||||
static _RT_Status _rt_thread_join(_RT_Thread *thread);
|
||||
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_terminate(_RT_Thread *thread);
|
||||
static _RT_Status _rt_thread_sleep(u64 time);
|
||||
|
|
|
@ -5,6 +5,8 @@ static u64 cia_stack_size;
|
|||
static u64 cia_tls_image_size;
|
||||
static void *cia_tls_image_base;
|
||||
|
||||
#include <cia/internal.h>
|
||||
|
||||
#include <linux/futex.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
extern i64 _cia_start_thread(
|
||||
extern i64 _rt_thread_start(
|
||||
u64 flags,
|
||||
void *stack_base,
|
||||
int *parent_tid,
|
||||
|
@ -33,6 +33,7 @@ static _RT_Status _rt_thread_create(_RT_Thread *thread, int (*thread_fn)(void *c
|
|||
// Initialize the _RT_Thread handle, which would point to
|
||||
// the TCB
|
||||
thread->handle = tcb;
|
||||
tcb->thread_finished = 0;
|
||||
// Create the new thread
|
||||
u64 flags = 0;
|
||||
// flags |= CLONE_CHILD_CLEARTID;
|
||||
|
@ -47,19 +48,52 @@ static _RT_Status _rt_thread_create(_RT_Thread *thread, int (*thread_fn)(void *c
|
|||
int *parent_tid = (int *)&tcb->parent_id;
|
||||
*child_tid = 1;
|
||||
*parent_tid = 0;
|
||||
i64 ret = _cia_start_thread(flags, stack, parent_tid, child_tid, 0, thread_fn, ctx);
|
||||
i64 ret = _rt_thread_start(flags, stack, parent_tid, child_tid, 0, thread_fn, ctx);
|
||||
if(ret < 0) {
|
||||
return _RT_ERROR_GENERIC;
|
||||
}
|
||||
return _RT_STATUS_OK;
|
||||
}
|
||||
|
||||
static _RT_Status _rt_thread_join(_RT_Thread *thread) {
|
||||
return _RT_ERROR_NOT_IMPLEMENTED;
|
||||
void _rt_thread_finish(int exit_code) {
|
||||
Cia_TCB *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);
|
||||
}
|
||||
if(tcb->thread_behaviour == _CIA_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
|
||||
// after the thread_finished is set and before exit_code is set, the main thread
|
||||
// will proceed to fetch an invalid exit code from the thread.
|
||||
tcb->thread_finished = 1;
|
||||
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) {
|
||||
// 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;
|
||||
// Signal the thread that we want it to be joined
|
||||
tcb->thread_behaviour = _CIA_THREAD_BEHAVIOUR_JOIN;
|
||||
// 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);
|
||||
}
|
||||
// Set the exit code
|
||||
*out_exit_code = tcb->exit_code;
|
||||
return _RT_STATUS_OK;
|
||||
}
|
||||
|
||||
static _RT_Status _rt_thread_detach(_RT_Thread *thread) {
|
||||
return _RT_ERROR_NOT_IMPLEMENTED;
|
||||
Cia_TCB *tcb = thread->handle;
|
||||
tcb->thread_behaviour = _CIA_THREAD_BEHAVIOUR_DETACH;
|
||||
return _RT_STATUS_OK;
|
||||
}
|
||||
|
||||
static _RT_Status _rt_thread_terminate(_RT_Thread *thread) {
|
||||
|
|
|
@ -5,4 +5,20 @@ int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) {
|
|||
return thrd_success;
|
||||
}
|
||||
return thrd_error;
|
||||
}
|
||||
}
|
||||
|
||||
int thrd_detach(thrd_t thr) {
|
||||
_RT_Status status = _rt_thread_detach(&thr.thread);
|
||||
if(status == _RT_STATUS_OK) {
|
||||
return thrd_success;
|
||||
}
|
||||
return thrd_error;
|
||||
}
|
||||
|
||||
int thrd_join(thrd_t thr, int *out_exit_code) {
|
||||
_RT_Status status = _rt_thread_join(&thr.thread, out_exit_code);
|
||||
if(status == _RT_STATUS_OK) {
|
||||
return thrd_success;
|
||||
}
|
||||
return thrd_error;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,6 @@ static void print_int(i64 number) {
|
|||
|
||||
static Cia_Mutex g_print_mutex;
|
||||
static Cia_Mutex g_mutex;
|
||||
static volatile _Atomic i64 n_completed = 0;
|
||||
static volatile i64 counter = 0;
|
||||
|
||||
int thrd_func(void *arg) {
|
||||
|
@ -46,12 +45,6 @@ int thrd_func(void *arg) {
|
|||
counter += 1;
|
||||
cia_mutex_unlock(&g_mutex);
|
||||
}
|
||||
atomic_fetch_add(&n_completed, 1);
|
||||
for(;;) {
|
||||
if(n_completed == 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cia_mutex_lock(&g_print_mutex);
|
||||
print_string("child thread: counter = ");
|
||||
print_int(counter);
|
||||
|
@ -76,12 +69,8 @@ int main() {
|
|||
counter += 1;
|
||||
cia_mutex_unlock(&g_mutex);
|
||||
}
|
||||
atomic_fetch_add(&n_completed, 1);
|
||||
for(;;) {
|
||||
if(n_completed == 2) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
int exit_code;
|
||||
thrd_join(thrd, &exit_code);
|
||||
cia_mutex_lock(&g_print_mutex);
|
||||
print_string("main thread: counter = ");
|
||||
print_int(counter);
|
||||
|
|
Loading…
Reference in New Issue