poll: fix interruptible sleep

This commit is contained in:
Matheus
2024-04-14 12:06:08 -03:00
parent c3f508b994
commit f19f784694
3 changed files with 10 additions and 6 deletions
+1
View File
@@ -10,6 +10,7 @@ typedef struct {
thread_t *thread; thread_t *thread;
spinlock_t lock; spinlock_t lock;
spinlock_t eventlock; spinlock_t eventlock;
spinlock_t wakeuplock;
struct polldata *data; struct polldata *data;
struct polldata *event; struct polldata *event;
size_t size; size_t size;
+8 -3
View File
@@ -40,6 +40,7 @@ int poll_initdesc(polldesc_t *desc, size_t size) {
desc->size = size; desc->size = size;
SPINLOCK_INIT(desc->lock); SPINLOCK_INIT(desc->lock);
SPINLOCK_INIT(desc->eventlock); SPINLOCK_INIT(desc->eventlock);
SPINLOCK_INIT(desc->wakeuplock);
for (uintmax_t i = 0; i < size; ++i) for (uintmax_t i = 0; i < size; ++i)
desc->data[i].desc = desc; desc->data[i].desc = desc;
__assert(spinlock_try(&desc->lock)); __assert(spinlock_try(&desc->lock));
@@ -106,8 +107,11 @@ int poll_dowait(polldesc_t *desc, size_t ustimeout) {
spinlock_release(&desc->eventlock); spinlock_release(&desc->eventlock);
int ret = sched_yield(); int ret = sched_yield();
// on return, the desc lock is REQUIRED to be left locked by the poll_event function. // on return, the desc lock is REQUIRED to be left locked by the poll_event function.
// XXX interruptible wait breaks this // in the case of sleep being interrupted, wait until poll_event has done everything (if anything)
__assert(spinlock_try(&desc->lock) == false); __assert(ret || spinlock_try(&desc->lock) == false);
if (ret)
spinlock_acquire(&desc->wakeuplock);
if (ustimeout != 0 && ret != 1) { if (ustimeout != 0 && ret != 1) {
timer_remove(_cpu()->timer, &sleepentry); timer_remove(_cpu()->timer, &sleepentry);
@@ -134,7 +138,7 @@ void poll_event(pollheader_t *header, int events) {
spinlock_acquire(&desc->eventlock); spinlock_acquire(&desc->eventlock);
int revents = iterator->events & events; int revents = iterator->events & events;
if (spinlock_try(&desc->lock) == false) { if (spinlock_try(&desc->lock) == false || spinlock_try(&desc->wakeuplock) == false) {
removefromlist(&pending, iterator); removefromlist(&pending, iterator);
insertinheader(header, iterator); insertinheader(header, iterator);
} }
@@ -154,6 +158,7 @@ void poll_event(pollheader_t *header, int events) {
polldata_t *next = iterator->next; polldata_t *next = iterator->next;
sched_wakeup(iterator->desc->thread, 0); sched_wakeup(iterator->desc->thread, 0);
insertinheader(header, iterator); insertinheader(header, iterator);
spinlock_release(&iterator->desc->wakeuplock);
iterator = next; iterator = next;
} }
+1 -3
View File
@@ -34,10 +34,8 @@ syscallret_t syscall_nanosleep(context_t *, timespec_t *utime, timespec_t *remai
ret.errno = sched_yield(); ret.errno = sched_yield();
if (ret.errno) { if (ret.errno)
// XXX interruptible wait might break things
timer_remove(_cpu()->timer, &sleepentry); timer_remove(_cpu()->timer, &sleepentry);
}
sched_targetcpu(NULL); sched_targetcpu(NULL);