diff options
author | Jeff Roberson <jeff@FreeBSD.org> | 2019-12-15 21:11:15 +0000 |
---|---|---|
committer | Jeff Roberson <jeff@FreeBSD.org> | 2019-12-15 21:11:15 +0000 |
commit | 61a74c5ccd65d1a00a96779f16eda8c41ff3a426 (patch) | |
tree | 0325e01f4affe5d9ef25e68fae1a7cbd5d2ebde9 /sys/kern/kern_thread.c | |
parent | 054802650063bea1cb817ef22a887c3116813ba9 (diff) | |
download | src-test2-61a74c5ccd65d1a00a96779f16eda8c41ff3a426.tar.gz src-test2-61a74c5ccd65d1a00a96779f16eda8c41ff3a426.zip |
Notes
Diffstat (limited to 'sys/kern/kern_thread.c')
-rw-r--r-- | sys/kern/kern_thread.c | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index 9d389eb8917f..a3f02a9d4111 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -565,7 +565,6 @@ thread_exit(void) thread_lock(p->p_singlethread); wakeup_swapper = thread_unsuspend_one( p->p_singlethread, p, false); - thread_unlock(p->p_singlethread); if (wakeup_swapper) kick_proc0(); } @@ -606,7 +605,7 @@ thread_exit(void) /* Save our resource usage in our process. */ td->td_ru.ru_nvcsw++; - ruxagg(p, td); + ruxagg_locked(p, td); rucollect(&p->p_ru, &td->td_ru); PROC_STATUNLOCK(p); @@ -730,19 +729,36 @@ weed_inhib(int mode, struct thread *td2, struct proc *p) THREAD_LOCK_ASSERT(td2, MA_OWNED); wakeup_swapper = 0; + + /* + * Since the thread lock is dropped by the scheduler we have + * to retry to check for races. + */ +restart: switch (mode) { case SINGLE_EXIT: - if (TD_IS_SUSPENDED(td2)) + if (TD_IS_SUSPENDED(td2)) { wakeup_swapper |= thread_unsuspend_one(td2, p, true); - if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) + thread_lock(td2); + goto restart; + } + if (TD_CAN_ABORT(td2)) { wakeup_swapper |= sleepq_abort(td2, EINTR); + return (wakeup_swapper); + } break; case SINGLE_BOUNDARY: case SINGLE_NO_EXIT: - if (TD_IS_SUSPENDED(td2) && (td2->td_flags & TDF_BOUNDARY) == 0) + if (TD_IS_SUSPENDED(td2) && + (td2->td_flags & TDF_BOUNDARY) == 0) { wakeup_swapper |= thread_unsuspend_one(td2, p, false); - if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) + thread_lock(td2); + goto restart; + } + if (TD_CAN_ABORT(td2)) { wakeup_swapper |= sleepq_abort(td2, ERESTART); + return (wakeup_swapper); + } break; case SINGLE_ALLPROC: /* @@ -754,18 +770,25 @@ weed_inhib(int mode, struct thread *td2, struct proc *p) * is used to avoid immediate un-suspend. */ if (TD_IS_SUSPENDED(td2) && (td2->td_flags & (TDF_BOUNDARY | - TDF_ALLPROCSUSP)) == 0) + TDF_ALLPROCSUSP)) == 0) { wakeup_swapper |= thread_unsuspend_one(td2, p, false); - if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) { + thread_lock(td2); + goto restart; + } + if (TD_CAN_ABORT(td2)) { if ((td2->td_flags & TDF_SBDRY) == 0) { thread_suspend_one(td2); td2->td_flags |= TDF_ALLPROCSUSP; } else { wakeup_swapper |= sleepq_abort(td2, ERESTART); + return (wakeup_swapper); } } break; + default: + break; } + thread_unlock(td2); return (wakeup_swapper); } @@ -842,9 +865,10 @@ thread_single(struct proc *p, int mode) #ifdef SMP } else if (TD_IS_RUNNING(td2) && td != td2) { forward_signal(td2); + thread_unlock(td2); #endif - } - thread_unlock(td2); + } else + thread_unlock(td2); } if (wakeup_swapper) kick_proc0(); @@ -1028,7 +1052,6 @@ thread_suspend_check(int return_instead) thread_lock(p->p_singlethread); wakeup_swapper = thread_unsuspend_one( p->p_singlethread, p, false); - thread_unlock(p->p_singlethread); if (wakeup_swapper) kick_proc0(); } @@ -1112,7 +1135,7 @@ thread_unsuspend_one(struct thread *td, struct proc *p, bool boundary) p->p_boundary_count--; } } - return (setrunnable(td)); + return (setrunnable(td, 0)); } /* @@ -1133,8 +1156,8 @@ thread_unsuspend(struct proc *p) if (TD_IS_SUSPENDED(td)) { wakeup_swapper |= thread_unsuspend_one(td, p, true); - } - thread_unlock(td); + } else + thread_unlock(td); } } else if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE && p->p_numthreads == p->p_suspcount) { @@ -1147,7 +1170,6 @@ thread_unsuspend(struct proc *p) thread_lock(p->p_singlethread); wakeup_swapper = thread_unsuspend_one( p->p_singlethread, p, false); - thread_unlock(p->p_singlethread); } } if (wakeup_swapper) @@ -1193,8 +1215,8 @@ thread_single_end(struct proc *p, int mode) if (TD_IS_SUSPENDED(td)) { wakeup_swapper |= thread_unsuspend_one(td, p, mode == SINGLE_BOUNDARY); - } - thread_unlock(td); + } else + thread_unlock(td); } } KASSERT(mode != SINGLE_BOUNDARY || p->p_boundary_count == 0, |