diff --git a/build.py b/build.py index 2dcbb54..97326d9 100755 --- a/build.py +++ b/build.py @@ -161,7 +161,10 @@ try: print(colors.red, f" ERROR: library config doesn't contain configuration for platform {target}", colors.reset, sep='') for include in platform_config['includes']: include_path = platform_config['path'] - ciabatta_header.write(f'#include "{include_path}/{include}"\n') + ciabatta_header.write(f'#include <{include}>\n') + for source in platform_config['sources']: + source_path = platform_config['path'] + ciabatta_header.write(f'#include "{source_path}/{source}"\n') ciabatta_header.write(f'#include "{target}/tinyrt-iface.h"\n') ciabatta_header.write(f'#include \n') for tinyrt_source in platform_config['tinyrt']: diff --git a/src/impl/stdlib-program/program.c b/src/impl/stdlib-program/program.c index e73c60c..3679de2 100644 --- a/src/impl/stdlib-program/program.c +++ b/src/impl/stdlib-program/program.c @@ -32,7 +32,7 @@ _Noreturn void abort(void) { } _Noreturn void exit(int code) { - for(u64 i = n_atexit_handlers-1; i-- != 0; ) { + for(i64 i = n_atexit_handlers-1; i-- > 0; ) { void (*handler)(void) = atexit_handlers[i]; handler(); } @@ -48,7 +48,7 @@ _Noreturn void _Exit(int code) { } _Noreturn void quick_exit(int code) { - for(u64 i = n_at_quick_exit_handlers-1; i-- != 0; ) { + for(i64 i = n_at_quick_exit_handlers-1; i-- > 0; ) { void (*handler)(void) = at_quick_exit_handlers[i]; handler(); } diff --git a/src/impl/stdlib-thread/thread.c b/src/impl/stdlib-thread/thread.c new file mode 100644 index 0000000..6065a91 --- /dev/null +++ b/src/impl/stdlib-thread/thread.c @@ -0,0 +1,8 @@ + +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg) { + _RT_Status status = _rt_thread_create(&thr->thread, (void (*)(void *))func, arg); + if(status == _RT_STATUS_OK) { + return thrd_success; + } + return thrd_error; +} \ No newline at end of file diff --git a/src/include/linux/sched.h b/src/include/linux/sched.h new file mode 100644 index 0000000..0402336 --- /dev/null +++ b/src/include/linux/sched.h @@ -0,0 +1,37 @@ + +#pragma once + +#define CLONE_NEWTIME 0x00000080 +#define CLONE_VM 0x00000100 +#define CLONE_FS 0x00000200 +#define CLONE_FILES 0x00000400 +#define CLONE_SIGHAND 0x00000800 +#define CLONE_PIDFD 0x00001000 +#define CLONE_PTRACE 0x00002000 +#define CLONE_VFORK 0x00004000 +#define CLONE_PARENT 0x00008000 +#define CLONE_THREAD 0x00010000 +#define CLONE_NEWNS 0x00020000 +#define CLONE_SYSVSEM 0x00040000 +#define CLONE_SETTLS 0x00080000 +#define CLONE_PARENT_SETTID 0x00100000 +#define CLONE_CHILD_CLEARTID 0x00200000 +#define CLONE_DETACHED 0x00400000 +#define CLONE_UNTRACED 0x00800000 +#define CLONE_CHILD_SETTID 0x01000000 +#define CLONE_NEWCGROUP 0x02000000 +#define CLONE_NEWUTS 0x04000000 +#define CLONE_NEWIPC 0x08000000 +#define CLONE_NEWUSER 0x10000000 +#define CLONE_NEWPID 0x20000000 +#define CLONE_NEWNET 0x40000000 +#define CLONE_IO 0x80000000 + +#define SCHED_OTHER 0 +#define SCHED_FIFO 1 +#define SCHED_RR 2 +#define SCHED_BATCH 3 +#define SCHED_ISO 4 +#define SCHED_IDLE 5 +#define SCHED_DEADLINE 6 +#define SCHED_RESET_ON_FORK 0x40000000 diff --git a/src/include/threads.h b/src/include/threads.h new file mode 100644 index 0000000..56a3372 --- /dev/null +++ b/src/include/threads.h @@ -0,0 +1,19 @@ + +#pragma once + +typedef int (*thrd_start_t)(void *); + +struct thrd_t typedef thrd_t; +struct thrd_t { + _RT_Thread thread; +}; + +enum { + thrd_success = 0, + thrd_nomem = -1, + thrd_timedout = -2, + thrd_busy = -3, + thrd_error = -4 +}; + +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg); diff --git a/src/include/tinyrt.h b/src/include/tinyrt.h index 6dc2d87..7c50a0e 100644 --- a/src/include/tinyrt.h +++ b/src/include/tinyrt.h @@ -45,6 +45,22 @@ static _RT_Status _rt_deinit(); _Noreturn static void _rt_program_exit(int code); #endif +// Thread API +struct _RT_Thread typedef _RT_Thread; +struct _RT_Thread { + u64 tid; + void *handle; +}; +#if _RT_API_THREAD == 1 + 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_join(_RT_Thread *thread); + 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); + static _RT_Status _rt_thread_get_timer_freq(u64 *freq); +#endif + // Environment API #if _RT_API_ENVIRONMENT == 1 static _RT_Status _rt_shell_exec(char const *cmd); diff --git a/src/library.json b/src/library.json index 0aa9a3c..194d50e 100644 --- a/src/library.json +++ b/src/library.json @@ -24,6 +24,7 @@ includes: [ "stdlib.h", "stdio.h", + "threads.h", "cia-mem.h", ], @@ -32,10 +33,13 @@ platforms: [ name: "linux", path: "linux", includes: [ - "entry.c", + "sys/mman.h", "errno.h", - "mman.h", - "fcntl.h" + "fcntl.h", + "sched.h", + ], + sources: [ + "entry.c", ], tinyrt: [ "tinyrt.c" @@ -44,7 +48,7 @@ platforms: [ { name: "windows", path: "windows", - includes: [ + sources: [ "windows.c" ], tinyrt: [ @@ -79,6 +83,16 @@ apis: [ "cia_memory", ] }, + { + name: "stdlib_threads", + path: "impl/stdlib-thread", + includes: [ + "thread.c", + ], + reqs: [ + "rt_api_thread" + ] + }, { name: "stdlib_file", path: "impl/stdlib-file", @@ -100,4 +114,5 @@ export: [ "cia_memory", "stdlib_program", "stdlib_file", + "stdlib_threads", ] \ No newline at end of file diff --git a/src/linux/tinyrt.c b/src/linux/tinyrt.c index 2aabcd4..8d41864 100644 --- a/src/linux/tinyrt.c +++ b/src/linux/tinyrt.c @@ -1,6 +1,68 @@ // See src/tinyrt.h file for the interface this file implements +_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; + 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; + } + u64 *stack = (void *)((u8 *)stack_base + stack_size); + stack[-1] = (u64)&&thread_return; + stack[-2] = 0; + // 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; + int parent_tid = 0; + int child_tid = 0; + i64 cur_tid = sys_clone(flags, &stack[-2], &parent_tid, &child_tid, 0); +thread_return: + if(cur_tid < 0) { + return _RT_ERROR_GENERIC; + } + if(cur_tid == child_tid) { + thread_fn(ctx); + } + 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; @@ -65,10 +127,6 @@ static _RT_Status _rt_file_close(_RT_File *file) { return _RT_STATUS_OK; } -_Noreturn static void _rt_program_exit(int code) { - sys_exit(code); -} - static _RT_Status _rt_mem_alloc(void *optional_desired_addr, u64 size, void **out_addr) { void *addr = sys_mmap((u64)optional_desired_addr, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if(addr == NULL) { @@ -84,5 +142,4 @@ static _RT_Status _rt_mem_free(void *ptr, u64 len) { return _RT_ERROR_GENERIC; } return _RT_STATUS_OK; -} - +} \ No newline at end of file diff --git a/src/linux/tinyrt.json b/src/linux/tinyrt.json index 53bb423..bfd4281 100644 --- a/src/linux/tinyrt.json +++ b/src/linux/tinyrt.json @@ -8,3 +8,4 @@ rt_api_file: true, rt_api_program: true, rt_api_shell: false, rt_api_memory: true, +rt_api_thread: true, diff --git a/src/loader/loader.c b/src/loader/loader.c index b335753..165b75d 100644 --- a/src/loader/loader.c +++ b/src/loader/loader.c @@ -6,6 +6,7 @@ #include "loader.h" #include +#include #include #include #include "../linux/tinyrt-iface.h" diff --git a/test.c b/test.c new file mode 100644 index 0000000..692a89e --- /dev/null +++ b/test.c @@ -0,0 +1,8 @@ + +#define __USE_GNU + +#include + +#ifdef CLONE_FILES + #define MYMACRO 1 +#endif diff --git a/tests/threaded.c b/tests/threaded.c new file mode 100644 index 0000000..089b374 --- /dev/null +++ b/tests/threaded.c @@ -0,0 +1,22 @@ + +#include +#include +#include + +int thrd_func(void *arg) { + char string[] = "child thread: ok!\n"; + fwrite(string, 1, sizeof string-1, stdout); + // exit(1); + for(;;); + return 0; +} + +int main() { + {char string[] = "main thred: before\n"; + fwrite(string, 1, sizeof string-1, stdout);} + thrd_t thrd; + thrd_create(&thrd, thrd_func, NULL); + {char string[] = "main thread: after!\n"; + fwrite(string, 1, sizeof string-1, stdout);} + return 0; +}