Block the thread lock in sched_throw() and use cpu_switch() to unblock

it.  The introduction of lockless switch in r355784 created a race to
re-use the exiting thread that was only possible to hit on a hypervisor.

Reported/Tested by:	rlibby
Discussed with:	rlibby, jhb
This commit is contained in:
Jeff Roberson 2020-01-23 03:36:50 +00:00
parent e87ad0ab37
commit 1eb13fce84
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=357014

View File

@ -2894,7 +2894,7 @@ sched_throw(struct thread *td)
struct thread *newtd;
struct tdq *tdq;
if (td == NULL) {
if (__predict_false(td == NULL)) {
#ifdef SMP
PCPU_SET(sched, DPCPU_PTR(tdq));
#endif
@ -2912,13 +2912,18 @@ sched_throw(struct thread *td)
tdq_load_rem(tdq, td);
td->td_lastcpu = td->td_oncpu;
td->td_oncpu = NOCPU;
thread_lock_block(td);
}
newtd = choosethread();
spinlock_enter();
TDQ_UNLOCK(tdq);
KASSERT(curthread->td_md.md_spinlock_count == 1,
("invalid count %d", curthread->td_md.md_spinlock_count));
cpu_throw(td, newtd); /* doesn't return */
/* doesn't return */
if (__predict_false(td == NULL))
cpu_throw(td, newtd); /* doesn't return */
else
cpu_switch(td, newtd, TDQ_LOCKPTR(tdq));
}
/*