summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2019-06-18 15:53:12 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2019-06-18 15:53:12 +0000
commit09b8fbccd5d52cd226b320396da67281e0531a13 (patch)
tree6c7a831a7895b06291c25859f602a5aa2b3b2ae7 /sys/kern
parent2a57b93af794fc6e59a3e56b775a950fd863d6ca (diff)
Ensure that timeout p_sleep_to is not left running when finishing sleep.
This is necessary when invoking sleep_finish_timeout() without the kernel lock. If not cancelled properly, an already running endtsleep() might cause a spurious wakeup on the thread if the thread re-enters a sleep queue very quickly before the handler completes. The flag P_TIMEOUT should stay cleared across the timeout cancellation. Add an assertion for that. OK mpi@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_synch.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 2ec52e662a5..378c25cadaf 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_synch.c,v 1.148 2019/04/23 13:35:12 visa Exp $ */
+/* $OpenBSD: kern_synch.c,v 1.149 2019/06/18 15:53:11 visa Exp $ */
/* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
/*
@@ -329,8 +329,11 @@ sleep_finish_timeout(struct sleep_state *sls)
if (p->p_flag & P_TIMEOUT) {
atomic_clearbits_int(&p->p_flag, P_TIMEOUT);
return (EWOULDBLOCK);
- } else
- timeout_del(&p->p_sleep_to);
+ } else {
+ /* This must not sleep. */
+ timeout_del_barrier(&p->p_sleep_to);
+ KASSERT((p->p_flag & P_TIMEOUT) == 0);
+ }
return (0);
}