summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2015-05-22 08:11:31 +0000
committerkib <kib@FreeBSD.org>2015-05-22 08:11:31 +0000
commitb453b295750133b89170fcb27025f932be66ad18 (patch)
treee7f890ee0d2a96f893212c2cea7a973dbf015909 /sys
parent05c61f3a940b6518001801a1e668924d944d97cb (diff)
downloadFreeBSD-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')
-rw-r--r--sys/kern/kern_thread.c51
-rw-r--r--sys/sys/proc.h1
2 files changed, 30 insertions, 22 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();
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 8587238..ff87b5dc 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -966,7 +966,6 @@ void thread_suspend_switch(struct thread *, struct proc *p);
void thread_suspend_one(struct thread *td);
void thread_unlink(struct thread *td);
void thread_unsuspend(struct proc *p);
-int thread_unsuspend_one(struct thread *td, struct proc *p);
void thread_wait(struct proc *p);
struct thread *thread_find(struct proc *p, lwpid_t tid);
OpenPOWER on IntegriCloud