mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 15:08:21 +00:00
poll: properly do timeouts
This commit is contained in:
+25
-2
@@ -5,6 +5,8 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <kernel/sched.h>
|
#include <kernel/sched.h>
|
||||||
#include <arch/interrupt.h>
|
#include <arch/interrupt.h>
|
||||||
|
#include <arch/timekeeper.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#define MAXNFDS 4096
|
#define MAXNFDS 4096
|
||||||
|
|
||||||
@@ -12,6 +14,7 @@ syscallret syscall_poll(pollfd *fds, size_t nfds, int timeoutms){
|
|||||||
syscallret retv;
|
syscallret retv;
|
||||||
retv.ret = -1;
|
retv.ret = -1;
|
||||||
|
|
||||||
|
|
||||||
if(fds > USER_SPACE_END){
|
if(fds > USER_SPACE_END){
|
||||||
retv.errno = EFAULT;
|
retv.errno = EFAULT;
|
||||||
return retv;
|
return retv;
|
||||||
@@ -42,6 +45,14 @@ syscallret syscall_poll(pollfd *fds, size_t nfds, int timeoutms){
|
|||||||
bool eventhappened = false;
|
bool eventhappened = false;
|
||||||
|
|
||||||
fdtable_t* fdtable = &arch_getcls()->thread->proc->fdtable;
|
fdtable_t* fdtable = &arch_getcls()->thread->proc->fdtable;
|
||||||
|
|
||||||
|
struct timespec target = arch_timekeeper_gettime();
|
||||||
|
target.tv_sec += timeoutms / 1000;
|
||||||
|
target.tv_nsec += timeoutms * 1000000;
|
||||||
|
if(target.tv_nsec >= 1000000000){
|
||||||
|
target.tv_sec++;
|
||||||
|
target.tv_nsec %= 1000000000;
|
||||||
|
}
|
||||||
|
|
||||||
while(!eventhappened){
|
while(!eventhappened){
|
||||||
for(uintmax_t i = 0; i < nfds; ++i){
|
for(uintmax_t i = 0; i < nfds; ++i){
|
||||||
@@ -69,6 +80,7 @@ syscallret syscall_poll(pollfd *fds, size_t nfds, int timeoutms){
|
|||||||
|
|
||||||
if(ilist[i].revents)
|
if(ilist[i].revents)
|
||||||
eventhappened = true;
|
eventhappened = true;
|
||||||
|
|
||||||
|
|
||||||
// cleanup
|
// cleanup
|
||||||
|
|
||||||
@@ -79,6 +91,15 @@ syscallret syscall_poll(pollfd *fds, size_t nfds, int timeoutms){
|
|||||||
// TODO check for signal or timeout
|
// TODO check for signal or timeout
|
||||||
|
|
||||||
if(timeoutms == 0) break;
|
if(timeoutms == 0) break;
|
||||||
|
if(timeoutms > 0){
|
||||||
|
struct timespec now = arch_timekeeper_gettime();
|
||||||
|
if(now.tv_sec > target.tv_sec)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(now.tv_sec == target.tv_sec && now.tv_nsec >= target.tv_sec)
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
arch_interrupt_disable();
|
arch_interrupt_disable();
|
||||||
sched_yield();
|
sched_yield();
|
||||||
arch_interrupt_enable();
|
arch_interrupt_enable();
|
||||||
@@ -91,12 +112,14 @@ syscallret syscall_poll(pollfd *fds, size_t nfds, int timeoutms){
|
|||||||
|
|
||||||
for(uintmax_t i = 0; i < nfds; ++i){
|
for(uintmax_t i = 0; i < nfds; ++i){
|
||||||
|
|
||||||
if(ilist[i].fd < 0 || ilist[i].revents == 0)
|
if(ilist[i].fd < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
fds[i].revents = ilist[i].revents;
|
fds[i].revents = ilist[i].revents;
|
||||||
|
|
||||||
++eventcount;
|
if(ilist[i].revents)
|
||||||
|
++eventcount;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user