From 2398dd9b805fb97b5fcf469930dc8801f677d45f Mon Sep 17 00:00:00 2001 From: Matheus Date: Sun, 9 Jul 2023 18:11:53 -0300 Subject: [PATCH] poll: timeout --- kernel-src/include/kernel/poll.h | 2 +- kernel-src/io/poll.c | 29 ++++++++++++++++++++++++++++- kernel-src/sys/syscalls/poll.c | 8 ++------ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/kernel-src/include/kernel/poll.h b/kernel-src/include/kernel/poll.h index 6abbf7fb..bc32ef26 100644 --- a/kernel-src/include/kernel/poll.h +++ b/kernel-src/include/kernel/poll.h @@ -36,7 +36,7 @@ typedef struct polldata { int poll_initdesc(polldesc_t *, size_t size); void poll_add(pollheader_t *, polldata_t *, int events); void poll_leave(polldesc_t *); -int poll_dowait(polldesc_t *); +int poll_dowait(polldesc_t *, size_t ustimeout); void poll_event(pollheader_t *, int events); void poll_destroydesc(polldesc_t *); diff --git a/kernel-src/io/poll.c b/kernel-src/io/poll.c index a1cb5bf6..b276f6b8 100644 --- a/kernel-src/io/poll.c +++ b/kernel-src/io/poll.c @@ -64,7 +64,20 @@ void poll_leave(polldesc_t *desc) { } } -int poll_dowait(polldesc_t *desc) { +static void timeout(context_t *, dpcarg_t arg) { + polldesc_t *desc = arg; + + MUTEX_TRY(&desc->eventlock); + + if (spinlock_try(&desc->lock)) + sched_wakeup(desc->thread, 1); + + MUTEX_RELEASE(&desc->eventlock); +} + +int poll_dowait(polldesc_t *desc, size_t ustimeout) { + timerentry_t sleepentry = {0}; + MUTEX_ACQUIRE(&desc->eventlock, false); if (desc->event) { MUTEX_RELEASE(&desc->eventlock); @@ -72,12 +85,26 @@ int poll_dowait(polldesc_t *desc) { } sched_preparesleep(true); + + if (ustimeout != 0) { + sched_targetcpu(_cpu()); + timer_insert(_cpu()->timer, &sleepentry, timeout, desc, ustimeout, false); + } + spinlock_release(&desc->lock); MUTEX_RELEASE(&desc->eventlock); int ret = sched_yield(); // on return, the desc lock is REQUIRED to be left locked by the poll_event function. // XXX interruptible wait breaks this __assert(spinlock_try(&desc->lock) == false); + + if (ustimeout != 0 && ret != 1) { + timer_remove(_cpu()->timer, &sleepentry); + sched_targetcpu(NULL); + } + + ret = ret == 1 ? 0 : ret; + return ret; } diff --git a/kernel-src/sys/syscalls/poll.c b/kernel-src/sys/syscalls/poll.c index 0df366f6..0b8ae59b 100644 --- a/kernel-src/sys/syscalls/poll.c +++ b/kernel-src/sys/syscalls/poll.c @@ -16,9 +16,6 @@ syscallret_t syscall_poll(context_t *, pollfd_t *fds, size_t nfds, int timeoutms .ret = -1 }; - // timeouts are not supported yet - __assert(timeoutms <= 0); - if ((void *)fds > USERSPACE_END) { ret.errno = EFAULT; return ret; @@ -60,9 +57,8 @@ syscallret_t syscall_poll(context_t *, pollfd_t *fds, size_t nfds, int timeoutms } if (eventcount == 0 && timeoutms != 0) { - // TODO timeout - ret.errno = poll_dowait(&desc); - if (ret.errno == 0) { + ret.errno = poll_dowait(&desc, (timeoutms == -1 ? 0 : timeoutms) * 1000); + if (ret.errno == 0 && desc.event) { int fd = ((uintptr_t)desc.event - (uintptr_t)desc.data) / sizeof(pollfd_t); fdsbuff[fd].revents = desc.data[fd].revents; eventcount = 1;