summaryrefslogtreecommitdiff
path: root/sys/kern/kern_thread.c
diff options
context:
space:
mode:
authorJeff Roberson <jeff@FreeBSD.org>2019-12-15 21:11:15 +0000
committerJeff Roberson <jeff@FreeBSD.org>2019-12-15 21:11:15 +0000
commit61a74c5ccd65d1a00a96779f16eda8c41ff3a426 (patch)
tree0325e01f4affe5d9ef25e68fae1a7cbd5d2ebde9 /sys/kern/kern_thread.c
parent054802650063bea1cb817ef22a887c3116813ba9 (diff)
downloadsrc-test2-61a74c5ccd65d1a00a96779f16eda8c41ff3a426.tar.gz
src-test2-61a74c5ccd65d1a00a96779f16eda8c41ff3a426.zip
Notes
Diffstat (limited to 'sys/kern/kern_thread.c')
-rw-r--r--sys/kern/kern_thread.c56
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,