2023-07-23 15:33:12 +00:00
|
|
|
|
|
|
|
// See src/tinyrt.h file for the interface this file implements
|
|
|
|
|
2023-08-26 02:53:58 +00:00
|
|
|
extern i64 _cia_start_thread(
|
2023-08-25 23:36:26 +00:00
|
|
|
u64 flags,
|
|
|
|
void *stack_base,
|
|
|
|
int *parent_tid,
|
|
|
|
int *child_tid,
|
|
|
|
void *tls,
|
2023-08-26 02:53:58 +00:00
|
|
|
void (*thread_fn)(void *ctx),
|
|
|
|
void *ctx
|
2023-08-25 23:36:26 +00:00
|
|
|
);
|
|
|
|
|
2023-08-15 08:54:02 +00:00
|
|
|
_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;
|
2023-08-26 02:53:58 +00:00
|
|
|
u64 mmap_flags = MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE;
|
2023-08-15 08:54:02 +00:00
|
|
|
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;
|
|
|
|
}
|
2023-08-25 23:36:26 +00:00
|
|
|
void *stack = (u8*)stack_base + stack_size;
|
2023-08-15 08:54:02 +00:00
|
|
|
// Create the new thread
|
|
|
|
u64 flags = 0;
|
2023-08-25 23:36:26 +00:00
|
|
|
// flags |= CLONE_CHILD_CLEARTID;
|
|
|
|
// flags |= CLONE_PARENT_SETTID;
|
2023-08-15 08:54:02 +00:00
|
|
|
flags |= CLONE_FS;
|
|
|
|
flags |= CLONE_FILES;
|
|
|
|
flags |= CLONE_SIGHAND;
|
|
|
|
flags |= CLONE_THREAD;
|
|
|
|
flags |= CLONE_VM;
|
2023-08-25 23:36:26 +00:00
|
|
|
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;
|
2023-08-26 02:53:58 +00:00
|
|
|
i64 ret = _cia_start_thread(flags, stack, parent_tid, child_tid, 0, thread_fn, ctx);
|
2023-08-25 23:36:26 +00:00
|
|
|
if(ret < 0) {
|
2023-08-15 08:54:02 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-07-27 13:49:53 +00:00
|
|
|
static _RT_Status _rt_file_std_handles_init() {
|
|
|
|
_rt_file_stdin.fd = 0;
|
|
|
|
_rt_file_stdin.flags = _RT_FILE_READ;
|
|
|
|
_rt_file_stdout.fd = 1;
|
|
|
|
_rt_file_stdout.flags = _RT_FILE_WRITE;
|
|
|
|
_rt_file_stderr.fd = 2;
|
|
|
|
_rt_file_stdout.flags = _RT_FILE_WRITE;
|
|
|
|
return _RT_STATUS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static _RT_Status _rt_file_open(_RT_File *file, char const *name, int _rt_flags) {
|
2023-07-27 13:04:24 +00:00
|
|
|
if((_rt_flags & 0x3) == 0) {
|
|
|
|
return _RT_ERROR_BAD_PARAM;
|
2023-07-23 15:33:12 +00:00
|
|
|
}
|
|
|
|
int mode = 0;
|
|
|
|
int flags = 0;
|
2023-08-01 01:45:45 +00:00
|
|
|
if((_rt_flags & 0x03) == 0x03) mode = O_RDWR;
|
|
|
|
else if(_rt_flags & _RT_FILE_READ) mode = O_RDONLY;
|
|
|
|
else if(_rt_flags & _RT_FILE_WRITE) mode = O_RDWR;
|
|
|
|
if(_rt_flags & _RT_FILE_CREATE) flags |= O_CREAT;
|
|
|
|
if(_rt_flags & _RT_FILE_EXCLUSIVE) flags |= O_EXCL;
|
|
|
|
if(_rt_flags & _RT_FILE_TRUNCATE) flags |= O_TRUNC;
|
2023-08-03 18:36:03 +00:00
|
|
|
i64 fd = sys_open(name, flags, mode);
|
2023-07-27 13:04:24 +00:00
|
|
|
if(-fd == EACCES) return _RT_STATUS_FILE_ACCESS;
|
|
|
|
if(-fd == EEXIST) return _RT_STATUS_FILE_EXISTS;
|
|
|
|
if(-fd == ENOENT) return _RT_STATUS_FILE_NOT_EXISTS;
|
|
|
|
if(-fd == EINVAL) return _RT_ERROR_BAD_PARAM;
|
|
|
|
if(-fd == EISDIR) return _RT_STATUS_FILE_DIRECTORY;
|
2023-07-23 15:33:12 +00:00
|
|
|
// I'm too lazy to fill in the rest so lets leave it at that for now
|
2023-07-27 13:04:24 +00:00
|
|
|
if(fd < 0) return _RT_STATUS_FILE_IO_ERROR;
|
2023-07-23 15:33:12 +00:00
|
|
|
file->fd = (u64)fd;
|
2023-07-27 13:04:24 +00:00
|
|
|
file->flags = _rt_flags;
|
|
|
|
return _RT_STATUS_OK;
|
2023-07-23 15:33:12 +00:00
|
|
|
}
|
|
|
|
|
2023-07-27 13:04:24 +00:00
|
|
|
static _RT_Status _rt_file_read(u64 size, void *buffer, _RT_File *from, u64 *out_bytes_read) {
|
2023-08-03 18:36:03 +00:00
|
|
|
i64 bytes_read = sys_read(from->fd, buffer, size);
|
2023-07-23 15:33:12 +00:00
|
|
|
if(bytes_read == 0) {
|
2023-07-27 13:04:24 +00:00
|
|
|
return _RT_STATUS_FILE_EOF;
|
2023-07-23 15:33:12 +00:00
|
|
|
}
|
|
|
|
if(bytes_read < 0) {
|
2023-07-27 13:04:24 +00:00
|
|
|
return _RT_STATUS_FILE_IO_ERROR;
|
2023-07-23 15:33:12 +00:00
|
|
|
}
|
|
|
|
*out_bytes_read = bytes_read;
|
2023-07-27 13:04:24 +00:00
|
|
|
return _RT_STATUS_OK;
|
2023-07-23 15:33:12 +00:00
|
|
|
}
|
|
|
|
|
2023-07-27 13:04:24 +00:00
|
|
|
static _RT_Status _rt_file_write(_RT_File *to, u64 size, void *buffer, u64 *out_bytes_written) {
|
2023-08-03 18:36:03 +00:00
|
|
|
i64 status = sys_write(to->fd, buffer, size);
|
2023-07-27 13:04:24 +00:00
|
|
|
if(-status == EBADF) return _RT_ERROR_BAD_PARAM;
|
|
|
|
if(-status == EIO) return _RT_STATUS_FILE_IO_ERROR;
|
|
|
|
if(-status > 0) return _RT_STATUS_FILE_IO_ERROR;
|
2023-07-25 05:09:15 +00:00
|
|
|
*out_bytes_written = status;
|
2023-07-27 13:04:24 +00:00
|
|
|
return _RT_STATUS_OK;
|
2023-07-23 15:33:12 +00:00
|
|
|
}
|
|
|
|
|
2023-07-27 13:04:24 +00:00
|
|
|
static _RT_Status _rt_file_close(_RT_File *file) {
|
2023-08-03 18:36:03 +00:00
|
|
|
i64 result = sys_close(file->fd);
|
2023-07-23 15:33:12 +00:00
|
|
|
if(result < 0) {
|
2023-07-27 13:04:24 +00:00
|
|
|
return _RT_STATUS_FILE_IO_ERROR;
|
2023-07-23 15:33:12 +00:00
|
|
|
}
|
2023-07-27 13:04:24 +00:00
|
|
|
return _RT_STATUS_OK;
|
2023-07-23 15:33:12 +00:00
|
|
|
}
|
2023-07-25 05:24:19 +00:00
|
|
|
|
2023-07-30 07:45:14 +00:00
|
|
|
static _RT_Status _rt_mem_alloc(void *optional_desired_addr, u64 size, void **out_addr) {
|
2023-08-03 18:36:03 +00:00
|
|
|
void *addr = sys_mmap((u64)optional_desired_addr, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
2023-07-30 07:45:14 +00:00
|
|
|
if(addr == NULL) {
|
|
|
|
return _RT_ERROR_GENERIC;
|
|
|
|
}
|
|
|
|
*out_addr = addr;
|
|
|
|
return _RT_STATUS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static _RT_Status _rt_mem_free(void *ptr, u64 len) {
|
2023-08-03 18:36:03 +00:00
|
|
|
i64 result = sys_munmap(ptr, len);
|
2023-07-30 07:45:14 +00:00
|
|
|
if(result == -1) {
|
|
|
|
return _RT_ERROR_GENERIC;
|
|
|
|
}
|
|
|
|
return _RT_STATUS_OK;
|
2023-08-27 02:51:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static _RT_Status _rt_sync_wait(u32 *addr, u32 compare_with, u64 sleep) {
|
|
|
|
i64 result = syscall(SYS_futex, addr, FUTEX_WAIT_PRIVATE, compare_with, NULL, 0, 0);
|
|
|
|
if(-result == EAGAIN) {
|
|
|
|
return _RT_STATUS_OK;
|
|
|
|
}
|
|
|
|
else if(-result > 0) {
|
|
|
|
return _RT_ERROR_GENERIC;
|
|
|
|
}
|
|
|
|
return _RT_STATUS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static _RT_Status _rt_sync_wake_one(u32 *addr, u32 *n_woken) {
|
|
|
|
i64 result = syscall(SYS_futex, addr, FUTEX_WAKE_PRIVATE, 1, NULL, 0, 0);
|
|
|
|
if(result < 0) {
|
|
|
|
return _RT_ERROR_GENERIC;
|
|
|
|
}
|
2023-08-27 14:36:46 +00:00
|
|
|
if(n_woken != NULL) {
|
|
|
|
*n_woken = (u32)result;
|
|
|
|
}
|
2023-08-27 02:51:35 +00:00
|
|
|
return _RT_STATUS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static _RT_Status _rt_sync_wake_all(u32 *addr, u32 *n_woken) {
|
|
|
|
i64 result = syscall(SYS_futex, addr, FUTEX_WAKE_PRIVATE, 0x7fffffff, NULL, 0, 0);
|
|
|
|
if(result < 0) {
|
|
|
|
return _RT_ERROR_GENERIC;
|
|
|
|
}
|
2023-08-27 14:36:46 +00:00
|
|
|
if(n_woken != NULL) {
|
|
|
|
*n_woken = (u32)result;
|
|
|
|
}
|
2023-08-27 02:51:35 +00:00
|
|
|
return _RT_STATUS_OK;
|
|
|
|
}
|