summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2017-09-22 21:09:24 +0200
committerRichard Braun <rbraun@sceen.net>2017-09-22 21:14:21 +0200
commitcf79bad4b192d4a22833032b189e6e14df5cbbb2 (patch)
tree646342f9ea4b201dbcadb9506cfca6a5ce50ccc5
parent5d9043e95ca86d4b1d69bc17727bbff3caa4e33b (diff)
kern/{sleepq,turnstile}: handle spurious wakeups
-rw-r--r--kern/sleepq.c24
-rw-r--r--kern/turnstile.c5
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