diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2019-06-18 15:53:12 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2019-06-18 15:53:12 +0000 |
commit | 09b8fbccd5d52cd226b320396da67281e0531a13 (patch) | |
tree | 6c7a831a7895b06291c25859f602a5aa2b3b2ae7 /sys/kern | |
parent | 2a57b93af794fc6e59a3e56b775a950fd863d6ca (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.c | 9 |
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); } |