mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-11-01 23:18:21 +00:00
poll: fix interruptible sleep
This commit is contained in:
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user