diff --git a/include/metalsvm/syscall.h b/include/metalsvm/syscall.h index 79fea3bd..c04d0c78 100644 --- a/include/metalsvm/syscall.h +++ b/include/metalsvm/syscall.h @@ -38,6 +38,7 @@ extern "C" { #define __NR_kill 9 #define __NR_fstat 10 #define __NR_sbrk 11 +#define __NR_fork 12 #ifdef __cplusplus } diff --git a/kernel/syscall.c b/kernel/syscall.c index 4997f0d6..aadca322 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -21,6 +21,7 @@ #include #include #include +#include static int sys_write(int fildes, const char *buf, size_t len) { @@ -38,7 +39,7 @@ static int sys_write(int fildes, const char *buf, size_t len) int syscall_handler(uint32_t sys_nr, ...) { - int ret = -1; + int ret = -EINVAL; va_list vl; va_start(vl, sys_nr); @@ -66,10 +67,11 @@ int syscall_handler(uint32_t sys_nr, ...) case __NR_getpid: ret = per_core(current_task)->id; break; + case __NR_fork: case __NR_fstat: default: kputs("invalid system call\n"); - ret = -1; + ret = -EINVAL; break; }; diff --git a/newlib/src/libgloss/metalsvm/_exit.c b/newlib/src/libgloss/metalsvm/_exit.c index 3c8fc789..78499875 100644 --- a/newlib/src/libgloss/metalsvm/_exit.c +++ b/newlib/src/libgloss/metalsvm/_exit.c @@ -21,13 +21,19 @@ #include "syscall.h" #include <_ansi.h> #include <_syslist.h> +#undef errno +extern int errno; _VOID _DEFUN (_exit, (rc), int rc) { + int ret; + /* task exit */ - SYSCALL1(__NR_exit, rc); + ret = SYSCALL1(__NR_exit, rc); + if (ret < 0) + errno = -ret; /* Convince GCC that this function never returns. */ for (;;) diff --git a/newlib/src/libgloss/metalsvm/close.c b/newlib/src/libgloss/metalsvm/close.c index 74db7805..5bcf18e6 100644 --- a/newlib/src/libgloss/metalsvm/close.c +++ b/newlib/src/libgloss/metalsvm/close.c @@ -33,6 +33,10 @@ _DEFUN (close, (fildes), int ret; ret = SYSCALL1(__NR_close, fildes); + if (ret < 0) { + errno = -ret; + ret = -1; + } return ret; } diff --git a/newlib/src/libgloss/metalsvm/fork.c b/newlib/src/libgloss/metalsvm/fork.c index b2308a9b..91864ee9 100644 --- a/newlib/src/libgloss/metalsvm/fork.c +++ b/newlib/src/libgloss/metalsvm/fork.c @@ -24,11 +24,20 @@ #undef errno extern int errno; #include "warning.h" +#include "syscall.h" int _DEFUN (_fork, (), _NOARGS) { - errno = EAGAIN; - return -1; + int ret; + + /* create a child process */ + ret = SYSCALL0(__NR_fork); + if (ret < 0) { + errno = -ret; + ret = -1; + } + + return ret; } diff --git a/newlib/src/libgloss/metalsvm/getpid.c b/newlib/src/libgloss/metalsvm/getpid.c index bc75047b..9c386e00 100644 --- a/newlib/src/libgloss/metalsvm/getpid.c +++ b/newlib/src/libgloss/metalsvm/getpid.c @@ -33,6 +33,10 @@ _DEFUN (_getpid, (), int ret; ret = SYSCALL0(__NR_getpid); + if (ret < 0) { + errno = -ret; + ret = -1; + } return ret; } diff --git a/newlib/src/libgloss/metalsvm/open.c b/newlib/src/libgloss/metalsvm/open.c index 993a0ced..c7f40c14 100644 --- a/newlib/src/libgloss/metalsvm/open.c +++ b/newlib/src/libgloss/metalsvm/open.c @@ -35,6 +35,10 @@ _DEFUN (_open, (file, flags, mode), int ret; ret = SYSCALL2(__NR_open, flags, mode); + if (ret < 0) { + errno = -ret; + ret = -1; + } return ret; } diff --git a/newlib/src/libgloss/metalsvm/syscall.h b/newlib/src/libgloss/metalsvm/syscall.h index df174939..e5d18093 100644 --- a/newlib/src/libgloss/metalsvm/syscall.h +++ b/newlib/src/libgloss/metalsvm/syscall.h @@ -35,6 +35,7 @@ extern "C" { #define __NR_kill 9 #define __NR_fstat 10 #define __NR_sbrk 11 +#define __NR_fork 12 #define _STR(token) #token #define _SYSCALLSTR(x) "int $" _STR(x) " " diff --git a/newlib/src/libgloss/metalsvm/write.c b/newlib/src/libgloss/metalsvm/write.c index 441f9a80..8c0fd3c0 100644 --- a/newlib/src/libgloss/metalsvm/write.c +++ b/newlib/src/libgloss/metalsvm/write.c @@ -35,6 +35,10 @@ _DEFUN (write, (file, ptr, len), int ret; ret = SYSCALL3(__NR_write, file, ptr, len); + if (ret < 0) { + errno = -ret; + ret = -1; + } return ret; }