Clearing the flag when preempting will let the preempted thread run
too much time. This can finish in a scheduler deadlock with ping-pong between two threads. One sample of this is: - device lapic (to have a preemption point on critical_exit()) - options DEVICE_POLLING with HZ>1499 (to have lapic freq = hardclock freq) - running a cpu intensive task (that does not enter the kernel) - only one CPU on SMP or no SMP. As requested by jhb@ 4BSD have received the same type of fix instead of propagating the flag to the new thread. Reviewed by: jhb, jeff MFC after: 1 month
This commit is contained in:
parent
a90dd577e7
commit
586cb6ec77
@ -940,12 +940,8 @@ sched_switch(struct thread *td, struct thread *newtd, int flags)
|
||||
if ((td->td_flags & TDF_NOLOAD) == 0)
|
||||
sched_load_rem();
|
||||
|
||||
if (newtd) {
|
||||
MPASS(newtd->td_lock == &sched_lock);
|
||||
newtd->td_flags |= (td->td_flags & TDF_NEEDRESCHED);
|
||||
}
|
||||
|
||||
td->td_lastcpu = td->td_oncpu;
|
||||
if (!(flags & SW_PREEMPT))
|
||||
td->td_flags &= ~TDF_NEEDRESCHED;
|
||||
td->td_owepreempt = 0;
|
||||
td->td_oncpu = NOCPU;
|
||||
|
@ -1783,6 +1783,7 @@ sched_switch(struct thread *td, struct thread *newtd, int flags)
|
||||
ts->ts_rltick = ticks;
|
||||
td->td_lastcpu = td->td_oncpu;
|
||||
td->td_oncpu = NOCPU;
|
||||
if (!(flags & SW_PREEMPT))
|
||||
td->td_flags &= ~TDF_NEEDRESCHED;
|
||||
td->td_owepreempt = 0;
|
||||
tdq->tdq_switchcnt++;
|
||||
|
Loading…
Reference in New Issue
Block a user