diff --git a/arch/sysv_x86-64/thread-entry.asm b/arch/sysv_x86-64/thread-entry.asm index df61895..6bea7e2 100644 --- a/arch/sysv_x86-64/thread-entry.asm +++ b/arch/sysv_x86-64/thread-entry.asm @@ -43,6 +43,11 @@ _cia_start_thread: pop rax ; thread_fn pop rdi ; ctx call rax + ; Make return value the first arg and call exit syscall + mov rdi, rax + mov rax, 60 + syscall + ; Just to be sure... hlt .exit: ret diff --git a/cia.c b/cia.c index ed5852e..edbc8d4 100644 --- a/cia.c +++ b/cia.c @@ -1,6 +1,10 @@ #include +// Base includes +#include +#include + // Platform-dependent sources #include _CIA_OS_CONF diff --git a/include/cia/internal.h b/include/cia/internal.h new file mode 100644 index 0000000..da71abc --- /dev/null +++ b/include/cia/internal.h @@ -0,0 +1,23 @@ + +#pragma once + +#include +#include + +struct Cia_CRT_Params typedef Cia_CRT_Params; +struct Cia_CRT_Params { + u64 stack_size; + u64 tls_image_size; + void *tls_image_base; +}; + +struct Cia_TCB typedef Cia_TCB; +struct Cia_TCB { + u64 thread_id; + u64 parent_id; + u64 pad0[3]; + u64 stack_canary; + u64 pad1[2]; +}; + + diff --git a/include/errno.h b/include/errno.h index 9d99853..dfba625 100644 --- a/include/errno.h +++ b/include/errno.h @@ -1,6 +1,8 @@ #pragma once +extern _Thread_local int errno; + // errno-base.h #define EPERM 1 #define ENOENT 2 diff --git a/include/tinyrt.h b/include/tinyrt.h index 870a0d3..09d85eb 100644 --- a/include/tinyrt.h +++ b/include/tinyrt.h @@ -55,7 +55,7 @@ struct _RT_Thread { void *handle; }; static _RT_Status _rt_thread_current(_RT_Thread *thread); -static _RT_Status _rt_thread_create(_RT_Thread *thread, void (*thread_fn)(void *ctx), void *ctx); +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_detach(_RT_Thread *thread); static _RT_Status _rt_thread_terminate(_RT_Thread *thread); diff --git a/loader/loader.c b/loader/loader.c index 70c3af4..aef90a4 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -15,6 +15,8 @@ #include #include "../os/linux/tinyrt.c" +#include + #include #include "../src/cia-mem/util.c" #include "../src/cia-mem/allocator.c" @@ -23,14 +25,6 @@ #include "stack.c" -struct Thread_Control_Block typedef Thread_Control_Block; -struct Thread_Control_Block { - u64 thread_id; - u64 pad0[4]; - u64 stack_canary; - u64 pad1[2]; -}; - struct Elf_Image typedef Elf_Image; struct Elf_Image { Cia_Arena arena; @@ -107,6 +101,7 @@ struct Stage3_Info_Struct { Elf_Image *ldso; void *stack_base; u64 stack_size; + void *tls_image; u64 tls_size; }; @@ -356,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 - Thread_Control_Block *tcb = cia_ptr_alignf((u8*)info->stack_base + info->tls_size, 1*MB); + Cia_TCB *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 @@ -377,6 +372,7 @@ static void ld_stage3_entry(u64 has_new_stack, void *ctx) { for(int i = 0; i < tls_image_size; ++i) { tls_image[i] = tls_image_base[i]; } + info->tls_image = tls_image_base; } } // Set up the thread pointer @@ -386,6 +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"); - void (*crt_entry)() = elf_addr(info->app, ((Elf64_Ehdr *)info->app->base)->e_entry); - crt_entry(); + Cia_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); + crt_entry(¶ms); } diff --git a/os/linux/conf.h b/os/linux/conf.h index 9091388..3419014 100644 --- a/os/linux/conf.h +++ b/os/linux/conf.h @@ -1,6 +1,10 @@ #pragma once +static u64 cia_stack_size; +static u64 cia_tls_image_size; +static void *cia_tls_image_base; + #include #include #include @@ -9,4 +13,5 @@ #include "entry.c" #include #include "tinyrt.c" +#include "tinyrt-threads.c" diff --git a/os/linux/entry.c b/os/linux/entry.c index fe63f79..d79f847 100644 --- a/os/linux/entry.c +++ b/os/linux/entry.c @@ -14,7 +14,10 @@ void __stack_chk_fail(void) { extern int main(int argc, char **argv, char **envp); static void _fileapi_init(); -void _start() { +void _start(Cia_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; // Get the envp // char **envp = argv + (argc + 1); // init(argc, argv, envp); diff --git a/os/linux/tinyrt-threads.c b/os/linux/tinyrt-threads.c new file mode 100644 index 0000000..fc03e51 --- /dev/null +++ b/os/linux/tinyrt-threads.c @@ -0,0 +1,71 @@ + +extern i64 _cia_start_thread( + u64 flags, + void *stack_base, + int *parent_tid, + int *child_tid, + void *tls, + int (*thread_fn)(void *ctx), + void *ctx +); + +static _RT_Status _rt_thread_current(_RT_Thread *thread) { + return _RT_ERROR_NOT_IMPLEMENTED; +} + +static _RT_Status _rt_thread_create(_RT_Thread *thread, int (*thread_fn)(void *ctx), void *ctx) { + // Create the memory for stack + u64 mmap_prot = PROT_READ|PROT_WRITE; + u64 mmap_flags = MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE; + void *stack_base = sys_mmap(0, 2*cia_stack_size, mmap_prot, mmap_flags, -1, 0); + if((i64)stack_base < 0) { + return _RT_ERROR_GENERIC; + } + 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)); + tcb->stack_canary = 0x12345678deadbeef; + u8 *tls_base = (u8 *)tcb - cia_tls_image_size; + for(int i = 0; i < cia_tls_image_size; ++i) { + tls_base[i] = ((u8 *)cia_tls_image_base)[i]; + } + // Create the new thread + u64 flags = 0; + // flags |= CLONE_CHILD_CLEARTID; + // flags |= CLONE_PARENT_SETTID; + flags |= CLONE_FS; + flags |= CLONE_FILES; + flags |= CLONE_SIGHAND; + flags |= CLONE_THREAD; + flags |= CLONE_VM; + flags |= CLONE_SYSVSEM; + int *child_tid = (int *)&tcb->thread_id; + 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); + 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; +} + +static _RT_Status _rt_thread_detach(_RT_Thread *thread) { + return _RT_ERROR_NOT_IMPLEMENTED; +} + +static _RT_Status _rt_thread_terminate(_RT_Thread *thread) { + return _RT_ERROR_NOT_IMPLEMENTED; +} + +static _RT_Status _rt_thread_sleep(u64 time) { + return _RT_ERROR_NOT_IMPLEMENTED; +} + +static _RT_Status _rt_thread_get_timer_freq(u64 *freq) { + return _RT_ERROR_NOT_IMPLEMENTED; +} diff --git a/os/linux/tinyrt.c b/os/linux/tinyrt.c index b79ea88..92e5027 100644 --- a/os/linux/tinyrt.c +++ b/os/linux/tinyrt.c @@ -1,76 +1,10 @@ // See src/tinyrt.h file for the interface this file implements -extern i64 _cia_start_thread( - u64 flags, - void *stack_base, - int *parent_tid, - int *child_tid, - void *tls, - void (*thread_fn)(void *ctx), - void *ctx -); - _Noreturn static void _rt_program_exit(int code) { sys_exit(code); } -static _RT_Status _rt_thread_current(_RT_Thread *thread) { - return _RT_ERROR_NOT_IMPLEMENTED; -} - -static _RT_Status _rt_thread_create(_RT_Thread *thread, void (*thread_fn)(void *ctx), void *ctx) { - // Create the memory for stack - u64 mmap_prot = PROT_READ|PROT_WRITE; - u64 mmap_flags = MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE; - u64 stack_size = 0x10000; - void *stack_base = sys_mmap(0, stack_size, mmap_prot, mmap_flags, -1, 0); - if((i64)stack_base < 0) { - return _RT_ERROR_GENERIC; - } - void *stack = (u8*)stack_base + stack_size; - // Create the new thread - u64 flags = 0; - // flags |= CLONE_CHILD_CLEARTID; - // flags |= CLONE_PARENT_SETTID; - flags |= CLONE_FS; - flags |= CLONE_FILES; - flags |= CLONE_SIGHAND; - flags |= CLONE_THREAD; - flags |= CLONE_VM; - flags |= CLONE_SYSVSEM; - int *temp_permanent_storage = stack_base; - int *child_tid = &temp_permanent_storage[0]; - int *parent_tid = &temp_permanent_storage[1]; - *child_tid = 1; - *parent_tid = 0; - i64 ret = _cia_start_thread(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; -} - -static _RT_Status _rt_thread_detach(_RT_Thread *thread) { - return _RT_ERROR_NOT_IMPLEMENTED; -} - -static _RT_Status _rt_thread_terminate(_RT_Thread *thread) { - return _RT_ERROR_NOT_IMPLEMENTED; -} - -static _RT_Status _rt_thread_sleep(u64 time) { - return _RT_ERROR_NOT_IMPLEMENTED; -} - -static _RT_Status _rt_thread_get_timer_freq(u64 *freq) { - return _RT_ERROR_NOT_IMPLEMENTED; -} - static _RT_Status _rt_file_std_handles_init() { _rt_file_stdin.fd = 0; _rt_file_stdin.flags = _RT_FILE_READ; diff --git a/src/stdlib-thread/thread.c b/src/stdlib-thread/thread.c index 6065a91..152ab02 100644 --- a/src/stdlib-thread/thread.c +++ b/src/stdlib-thread/thread.c @@ -1,6 +1,6 @@ int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { - _RT_Status status = _rt_thread_create(&thr->thread, (void (*)(void *))func, arg); + _RT_Status status = _rt_thread_create(&thr->thread, (int (*)(void *))func, arg); if(status == _RT_STATUS_OK) { return thrd_success; } diff --git a/tests/threaded.c b/tests/threaded.c index 12dab2b..3ef6952 100644 --- a/tests/threaded.c +++ b/tests/threaded.c @@ -57,7 +57,6 @@ int thrd_func(void *arg) { print_int(counter); print_char('\n'); cia_mutex_unlock(&g_print_mutex); - exit(1); return 0; }