diff options
author | Richard Braun <rbraun@sceen.net> | 2017-09-22 21:09:24 +0200 |
---|---|---|
committer | Richard Braun <rbraun@sceen.net> | 2017-09-22 21:14:21 +0200 |
commit | cf79bad4b192d4a22833032b189e6e14df5cbbb2 (patch) | |
tree | 646342f9ea4b201dbcadb9506cfca6a5ce50ccc5 | |
parent | 5d9043e95ca86d4b1d69bc17727bbff3caa4e33b (diff) |
kern/{sleepq,turnstile}: handle spurious wakeups
-rw-r--r-- | kern/sleepq.c | 24 | ||||
-rw-r--r-- | kern/turnstile.c | 5 |
2 files changed, 19 insertions, 10 deletions
diff --git a/kern/sleepq.c b/kern/sleepq.c index 3a9273be..294ad7ca 100644 --- a/kern/sleepq.c +++ b/kern/sleepq.c @@ -450,17 +450,23 @@ sleepq_wait_common(struct sleepq *sleepq, const char *wchan, sleepq_waiter_init(&waiter, thread); sleepq_add_waiter(sleepq, &waiter); - if (!timed) { - thread_sleep(&sleepq->bucket->lock, sleepq->sync_obj, wchan); - error = 0; - } else { - error = thread_timedsleep(&sleepq->bucket->lock, sleepq->sync_obj, - wchan, ticks); - - if (error && sleepq_waiter_pending_wakeup(&waiter)) { + do { + if (!timed) { + thread_sleep(&sleepq->bucket->lock, sleepq->sync_obj, wchan); error = 0; + } else { + error = thread_timedsleep(&sleepq->bucket->lock, sleepq->sync_obj, + wchan, ticks); + + if (error) { + if (sleepq_waiter_pending_wakeup(&waiter)) { + error = 0; + } else { + break; + } + } } - } + } while (!sleepq_waiter_pending_wakeup(&waiter)); sleepq_remove_waiter(sleepq, &waiter); diff --git a/kern/turnstile.c b/kern/turnstile.c index 3145399f..157c43f2 100644 --- a/kern/turnstile.c +++ b/kern/turnstile.c @@ -743,7 +743,10 @@ turnstile_wait_common(struct turnstile *turnstile, const char *wchan, } } - assert(turnstile_waiter_awaken(&waiter)); + /* Handle spurious wakeups */ + if (!turnstile_waiter_awaken(&waiter)) { + continue; + } /* * The real priority of a thread may change between waking up |