diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2022-05-03 19:48:50 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2022-06-13 19:30:02 +0000 |
commit | d7a9e6e74067f70eeec74dcd64a9bcc851503a6e (patch) | |
tree | 83a154f0010878cea428bf982f38542c19808b98 | |
parent | 02a2aacbe2c81be455811fa9d4200101f70a86d2 (diff) | |
download | src-d7a9e6e74067f70eeec74dcd64a9bcc851503a6e.tar.gz src-d7a9e6e74067f70eeec74dcd64a9bcc851503a6e.zip |
thread_single: wait for P_STOPPED_SINGLE to pass
to avoid ALLPROC mode to try to race with any other single-threading
mode.
In collaboration with: pho
Reviewed by: markj
Sponsored by: The FreeBSD Foundation
MFC after: 2 weeks
Differential revision: https://reviews.freebsd.org/D35310
-rw-r--r-- | sys/kern/kern_thread.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 57d235c002f0..4dd8dbdfb5a7 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -1207,10 +1207,18 @@ thread_single(struct proc *p, int mode) mtx_assert(&Giant, MA_NOTOWNED); PROC_LOCK_ASSERT(p, MA_OWNED); - if ((p->p_flag & P_HADTHREADS) == 0 && mode != SINGLE_ALLPROC) + /* + * Is someone already single threading? + * Or may be singlethreading is not needed at all. + */ + if (mode == SINGLE_ALLPROC) { + while ((p->p_flag & P_STOPPED_SINGLE) != 0) { + if ((p->p_flag2 & P2_WEXIT) != 0) + return (1); + msleep(&p->p_flag, &p->p_mtx, PCATCH, "thrsgl", 0); + } + } else if ((p->p_flag & P_HADTHREADS) == 0) return (0); - - /* Is someone already single threading? */ if (p->p_singlethread != NULL && p->p_singlethread != td) return (1); @@ -1669,6 +1677,7 @@ thread_single_end(struct proc *p, int mode) PROC_SUNLOCK(p); if (wakeup_swapper) kick_proc0(); + wakeup(&p->p_flag); } /* |