diff --git a/kernel-src/arch/x86-64/syscall.asm b/kernel-src/arch/x86-64/syscall.asm index 3b192a8a..292cf9f3 100644 --- a/kernel-src/arch/x86-64/syscall.asm +++ b/kernel-src/arch/x86-64/syscall.asm @@ -34,6 +34,7 @@ extern syscall_fchmod extern syscall_fchmodat extern syscall_umask extern syscall_poll +extern syscall_nanosleep syscalltab: dq syscall_print dq syscall_mmap @@ -70,7 +71,8 @@ dq syscall_fchmod dq syscall_fchmodat dq syscall_umask dq syscall_poll -syscallcount equ 35 +dq syscall_nanosleep +syscallcount equ 36 section .text global arch_syscall_entry ; on entry: diff --git a/kernel-src/arch/x86-64/syscalllog.c b/kernel-src/arch/x86-64/syscalllog.c index 5d2f0a83..6df52584 100644 --- a/kernel-src/arch/x86-64/syscalllog.c +++ b/kernel-src/arch/x86-64/syscalllog.c @@ -42,7 +42,8 @@ static char *name[] = { "fchmod", "fchmodat", "umask", - "poll" + "poll", + "nanosleep" }; static char *args[] = { @@ -80,7 +81,8 @@ static char *args[] = { "fd %d mode %o", // fchmod "dirfd %d path %s mode %o flags %d", // fchmodat "mode %o", // umask - "fds %p nfds %d timeout %d" // poll + "fds %p nfds %d timeout %d", // poll + "time %p remaining %p" // nanosleep }; #endif diff --git a/kernel-src/sys/syscalls/sleep.c b/kernel-src/sys/syscalls/sleep.c new file mode 100644 index 00000000..6fa94c10 --- /dev/null +++ b/kernel-src/sys/syscalls/sleep.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +static void timeout(context_t *, dpcarg_t arg) { + thread_t *thread = arg; + sched_wakeup(thread, 0); +} + +syscallret_t syscall_nanosleep(context_t *, timespec_t *utime, timespec_t *remaining) { + syscallret_t ret = { + .ret = -1 + }; + + if ((void *)utime > USERSPACE_END || (void *)remaining > USERSPACE_END) { + ret.errno = EFAULT; + return ret; + } + + timespec_t time = *utime; + + if (time.ns > 999999999 || time.ns < 0) { + ret.errno = EINVAL; + return ret; + } + + timerentry_t sleepentry; + sched_preparesleep(true); + + sched_targetcpu(_cpu()); + timer_insert(_cpu()->timer, &sleepentry, timeout, _cpu()->thread, time.s * 1000000 + time.ns / 1000, false); + + ret.errno = sched_yield(); + + if (ret.errno) { + // XXX interruptible wait might break things + timer_remove(_cpu()->timer, &sleepentry); + } + + sched_targetcpu(NULL); + + ret.ret = 0; + return ret; +} diff --git a/patches/mlibc/jinx-working-patch.patch b/patches/mlibc/jinx-working-patch.patch index ec41d469..b753503d 100644 --- a/patches/mlibc/jinx-working-patch.patch +++ b/patches/mlibc/jinx-working-patch.patch @@ -133,10 +133,10 @@ index 0000000..e5b087a + diff --git mlibc-workdir/sysdeps/astral/generic/generic.cpp mlibc-workdir/sysdeps/astral/generic/generic.cpp new file mode 100644 -index 0000000..d233630 +index 0000000..22db6d2 --- /dev/null +++ mlibc-workdir/sysdeps/astral/generic/generic.cpp -@@ -0,0 +1,427 @@ +@@ -0,0 +1,438 @@ +#include +#include +#include @@ -216,6 +216,17 @@ index 0000000..d233630 + return 0; + } + ++ int sys_sleep(time_t *secs, long *nanos) { ++ struct timespec ts; ++ ts.tv_sec = *secs; ++ ts.tv_nsec = *nanos; ++ long ret; ++ long err = syscall(SYSCALL_NANOSLEEP, &ret, (uintptr_t)&ts, (uintptr_t)&ts); ++ *secs = ts.tv_sec; ++ *nanos = ts.tv_nsec; ++ return err; ++ } ++ + int sys_tcgetattr(int fd, struct termios *attr){ + int res; + return sys_ioctl(fd, TCGETS, (void *)attr, &res); @@ -583,10 +594,10 @@ index 0000000..990eca0 +#endif diff --git mlibc-workdir/sysdeps/astral/include/astral/syscall.h mlibc-workdir/sysdeps/astral/include/astral/syscall.h new file mode 100644 -index 0000000..d4405b6 +index 0000000..4426771 --- /dev/null +++ mlibc-workdir/sysdeps/astral/include/astral/syscall.h -@@ -0,0 +1,58 @@ +@@ -0,0 +1,59 @@ +#ifndef _SYSCALL_H_INCLUDE +#define _SYSCALL_H_INCLUDE + @@ -625,6 +636,7 @@ index 0000000..d4405b6 +#define SYSCALL_FCHMODAT 32 +#define SYSCALL_UMASK 33 +#define SYSCALL_POLL 34 ++#define SYSCALL_NANOSLEEP 35 + +#include +#include