diff options
author | kib <kib@FreeBSD.org> | 2015-05-22 08:11:31 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2015-05-22 08:11:31 +0000 |
commit | b453b295750133b89170fcb27025f932be66ad18 (patch) | |
tree | e7f890ee0d2a96f893212c2cea7a973dbf015909 /sys/kern/kern_thread.c | |
parent | 05c61f3a940b6518001801a1e668924d944d97cb (diff) | |
download | FreeBSD-src-b453b295750133b89170fcb27025f932be66ad18.zip FreeBSD-src-b453b295750133b89170fcb27025f932be66ad18.tar.gz |
MFC r282944:
Decrement p_boundary_count in the single-threading thread, during making
other thread runnable. This guarantees that upon return from the
thread_single_end(), p_boundary_count is zero.
Diffstat (limited to 'sys/kern/kern_thread.c')
-rw-r--r-- | sys/kern/kern_thread.c | 51 |
1 files changed, 30 insertions, 21 deletions
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c index ba04471..739ef21 100644 --- a/sys/kern/kern_thread.c +++ b/sys/kern/kern_thread.c @@ -75,6 +75,8 @@ static struct mtx zombie_lock; MTX_SYSINIT(zombie_lock, &zombie_lock, "zombie lock", MTX_SPIN); static void thread_zombie(struct thread *); +static int thread_unsuspend_one(struct thread *td, struct proc *p, + bool boundary); #define TID_BUFFER_SIZE 1024 @@ -446,7 +448,7 @@ thread_exit(void) if (p->p_numthreads == p->p_suspcount) { thread_lock(p->p_singlethread); wakeup_swapper = thread_unsuspend_one( - p->p_singlethread, p); + p->p_singlethread, p, false); thread_unlock(p->p_singlethread); if (wakeup_swapper) kick_proc0(); @@ -602,19 +604,19 @@ weed_inhib(int mode, struct thread *td2, struct proc *p) switch (mode) { case SINGLE_EXIT: if (TD_IS_SUSPENDED(td2)) - wakeup_swapper |= thread_unsuspend_one(td2, p); + wakeup_swapper |= thread_unsuspend_one(td2, p, true); if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) wakeup_swapper |= sleepq_abort(td2, EINTR); break; case SINGLE_BOUNDARY: if (TD_IS_SUSPENDED(td2) && (td2->td_flags & TDF_BOUNDARY) == 0) - wakeup_swapper |= thread_unsuspend_one(td2, p); + wakeup_swapper |= thread_unsuspend_one(td2, p, false); if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) wakeup_swapper |= sleepq_abort(td2, ERESTART); break; case SINGLE_NO_EXIT: if (TD_IS_SUSPENDED(td2) && (td2->td_flags & TDF_BOUNDARY) == 0) - wakeup_swapper |= thread_unsuspend_one(td2, p); + wakeup_swapper |= thread_unsuspend_one(td2, p, false); if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) wakeup_swapper |= sleepq_abort(td2, ERESTART); break; @@ -629,7 +631,7 @@ weed_inhib(int mode, struct thread *td2, struct proc *p) */ if (TD_IS_SUSPENDED(td2) && (td2->td_flags & (TDF_BOUNDARY | TDF_ALLPROCSUSP)) == 0) - wakeup_swapper |= thread_unsuspend_one(td2, p); + wakeup_swapper |= thread_unsuspend_one(td2, p, false); if (TD_ON_SLEEPQ(td2) && (td2->td_flags & TDF_SINTR) != 0) { if ((td2->td_flags & TDF_SBDRY) == 0) { thread_suspend_one(td2); @@ -897,8 +899,8 @@ thread_suspend_check(int return_instead) if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE) { if (p->p_numthreads == p->p_suspcount + 1) { thread_lock(p->p_singlethread); - wakeup_swapper = - thread_unsuspend_one(p->p_singlethread, p); + wakeup_swapper = thread_unsuspend_one( + p->p_singlethread, p, false); thread_unlock(p->p_singlethread); if (wakeup_swapper) kick_proc0(); @@ -917,15 +919,8 @@ thread_suspend_check(int return_instead) } PROC_SUNLOCK(p); mi_switch(SW_INVOL | SWT_SUSPEND, NULL); - if (return_instead == 0) - td->td_flags &= ~TDF_BOUNDARY; thread_unlock(td); PROC_LOCK(p); - if (return_instead == 0) { - PROC_SLOCK(p); - p->p_boundary_count--; - PROC_SUNLOCK(p); - } } return (0); } @@ -974,8 +969,8 @@ thread_suspend_one(struct thread *td) sched_sleep(td, 0); } -int -thread_unsuspend_one(struct thread *td, struct proc *p) +static int +thread_unsuspend_one(struct thread *td, struct proc *p, bool boundary) { THREAD_LOCK_ASSERT(td, MA_OWNED); @@ -985,6 +980,10 @@ thread_unsuspend_one(struct thread *td, struct proc *p) if (td->td_proc == p) { PROC_SLOCK_ASSERT(p, MA_OWNED); p->p_suspcount--; + if (boundary && (td->td_flags & TDF_BOUNDARY) != 0) { + td->td_flags &= ~TDF_BOUNDARY; + p->p_boundary_count--; + } } return (setrunnable(td)); } @@ -1005,12 +1004,13 @@ thread_unsuspend(struct proc *p) FOREACH_THREAD_IN_PROC(p, td) { thread_lock(td); if (TD_IS_SUSPENDED(td)) { - wakeup_swapper |= thread_unsuspend_one(td, p); + wakeup_swapper |= thread_unsuspend_one(td, p, + true); } thread_unlock(td); } - } else if ((P_SHOULDSTOP(p) == P_STOPPED_SINGLE) && - (p->p_numthreads == p->p_suspcount)) { + } else if (P_SHOULDSTOP(p) == P_STOPPED_SINGLE && + p->p_numthreads == p->p_suspcount) { /* * Stopping everything also did the job for the single * threading request. Now we've downgraded to single-threaded, @@ -1019,7 +1019,7 @@ thread_unsuspend(struct proc *p) if (p->p_singlethread->td_proc == p) { thread_lock(p->p_singlethread); wakeup_swapper = thread_unsuspend_one( - p->p_singlethread, p); + p->p_singlethread, p, false); thread_unlock(p->p_singlethread); } } @@ -1043,6 +1043,12 @@ thread_single_end(struct proc *p, int mode) KASSERT((mode == SINGLE_ALLPROC && (p->p_flag & P_TOTAL_STOP) != 0) || (mode != SINGLE_ALLPROC && (p->p_flag & P_TOTAL_STOP) == 0), ("mode %d does not match P_TOTAL_STOP", mode)); + KASSERT(mode == SINGLE_ALLPROC || p->p_singlethread == curthread, + ("thread_single_end from other thread %p %p", + curthread, p->p_singlethread)); + KASSERT(mode != SINGLE_BOUNDARY || + (p->p_flag & P_SINGLE_BOUNDARY) != 0, + ("mis-matched SINGLE_BOUNDARY flags %x", p->p_flag)); p->p_flag &= ~(P_STOPPED_SINGLE | P_SINGLE_EXIT | P_SINGLE_BOUNDARY | P_TOTAL_STOP); PROC_SLOCK(p); @@ -1058,11 +1064,14 @@ thread_single_end(struct proc *p, int mode) FOREACH_THREAD_IN_PROC(p, td) { thread_lock(td); if (TD_IS_SUSPENDED(td)) { - wakeup_swapper |= thread_unsuspend_one(td, p); + wakeup_swapper |= thread_unsuspend_one(td, p, + mode == SINGLE_BOUNDARY); } thread_unlock(td); } } + KASSERT(mode != SINGLE_BOUNDARY || p->p_boundary_count == 0, + ("inconsistent boundary count %d", p->p_boundary_count)); PROC_SUNLOCK(p); if (wakeup_swapper) kick_proc0(); |