diff options
Diffstat (limited to 'libs/libc/sys.c')
-rw-r--r-- | libs/libc/sys.c | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/libs/libc/sys.c b/libs/libc/sys.c new file mode 100644 index 0000000..491c37c --- /dev/null +++ b/libs/libc/sys.c @@ -0,0 +1,203 @@ +// MIT License, Copyright (c) 2020 Marvin Borner +// Syscall implementation + +#include <arg.h> +#include <assert.h> +#include <errno.h> +#include <sys.h> + +#if defined(userspace) + +/** + * Definitions + */ + +#define ERRIFY(ret) \ + if (ret < 0) { \ + errno = -ret; \ + return -1; \ + } \ + errno = 0; \ + return ret + +res sys0(enum sys num); +res sys0(enum sys num) +{ + int a; + __asm__ volatile("int $0x80" : "=a"(a) : "0"(num)); + ERRIFY(a); +} + +res sys1(enum sys num, int d1); +res sys1(enum sys num, int d1) +{ + int a; + __asm__ volatile("int $0x80" : "=a"(a) : "0"(num), "b"((int)d1)); + ERRIFY(a); +} + +res sys2(enum sys num, int d1, int d2); +res sys2(enum sys num, int d1, int d2) +{ + int a; + __asm__ volatile("int $0x80" : "=a"(a) : "0"(num), "b"((int)d1), "c"((int)d2)); + ERRIFY(a); +} + +res sys3(enum sys num, int d1, int d2, int d3); +res sys3(enum sys num, int d1, int d2, int d3) +{ + int a; + __asm__ volatile("int $0x80" + : "=a"(a) + : "0"(num), "b"((int)d1), "c"((int)d2), "d"((int)d3)); + ERRIFY(a); +} + +res sys4(enum sys num, int d1, int d2, int d3, int d4); +res sys4(enum sys num, int d1, int d2, int d3, int d4) +{ + int a; + __asm__ volatile("int $0x80" + : "=a"(a) + : "0"(num), "b"((int)d1), "c"((int)d2), "d"((int)d3), "S"((int)d4)); + ERRIFY(a); +} + +res sys5(enum sys num, int d1, int d2, int d3, int d4, int d5); +res sys5(enum sys num, int d1, int d2, int d3, int d4, int d5) +{ + int a; + __asm__ volatile("int $0x80" + : "=a"(a) + : "0"(num), "b"((int)d1), "c"((int)d2), "d"((int)d3), "S"((int)d4), + "D"((int)d5)); + ERRIFY(a); +} + +/** + * Syscalls + */ + +res sys_alloc(u32 size, u32 *addr) +{ + u32 id = 0; + return sys4(SYS_ALLOC, (int)size, (int)addr, (int)&id, 0); +} + +res sys_free(void *ptr) +{ + return sys1(SYS_FREE, (int)ptr); +} + +res shalloc(u32 size, u32 *addr, u32 *id) +{ + return sys4(SYS_ALLOC, (int)size, (int)addr, (int)id, 1); +} + +res shaccess(u32 id, u32 *addr, u32 *size) +{ + return sys3(SYS_SHACCESS, (int)id, (int)addr, (int)size); +} + +void loop(void) +{ + sys0(SYS_LOOP); +} + +res read(const char *path, void *buf, u32 offset, u32 count) +{ + return sys4(SYS_READ, (int)path, (int)buf, (int)offset, (int)count); +} + +res write(const char *path, const void *buf, u32 offset, u32 count) +{ + return sys4(SYS_WRITE, (int)path, (int)buf, (int)offset, (int)count); +} + +res ioctl(const char *path, ...) +{ + va_list ap; + int args[4] = { 0 }; + + va_start(ap, path); + for (int i = 0; i < 4; i++) + args[i] = va_arg(ap, int); + va_end(ap); + + return sys5(SYS_IOCTL, (int)path, args[0], args[1], args[2], args[3]); +} + +res stat(const char *path, struct stat *buf) +{ + return sys2(SYS_STAT, (int)path, (int)buf); +} + +res poll(const char **files) +{ + return sys1(SYS_POLL, (int)files); +} + +res exec(const char *path, ...) +{ + va_list ap; + int args[4] = { 0 }; + + va_start(ap, path); + for (int i = 0; i < 4; i++) + args[i] = va_arg(ap, int); + va_end(ap); + + return sys5(SYS_EXEC, (int)path, args[0], args[1], args[2], args[3]); +} + +res yield(void) +{ + return sys0(SYS_YIELD); +} + +static void atexit_trigger(void); +void exit(s32 status) +{ + atexit_trigger(); + sys1(SYS_EXIT, (int)status); + while (1) + yield(); +} + +res boot(u32 cmd) +{ + return sys2(SYS_BOOT, SYS_BOOT_MAGIC, cmd); +} + +u32 time(void) +{ + return (u32)sys0(SYS_TIME); +} + +/** + * At exit + */ + +#define ATEXIT_MAX 32 + +static u32 slot = 0; +static void (*funcs[ATEXIT_MAX])(void) = { 0 }; + +static void atexit_trigger(void) +{ + while (slot-- > 0) { + if (funcs[slot]) { + funcs[slot](); + funcs[slot] = NULL; + } + } +} + +void atexit(void (*func)(void)) +{ + if (slot < ATEXIT_MAX) + funcs[slot++] = func; +} + +#endif |