summaryrefslogtreecommitdiffstats
path: root/sys/kern/sched_ule.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2012-08-09 19:26:13 +0000
committermav <mav@FreeBSD.org>2012-08-09 19:26:13 +0000
commit1f0ad947a6c993e63b43f3e0425966cb88699f30 (patch)
tree0309debb19e0fbda2144215613bcee44d7097bc7 /sys/kern/sched_ule.c
parent278be30294f435b7b5e07d641af9c4c6b7dc3b95 (diff)
downloadFreeBSD-src-1f0ad947a6c993e63b43f3e0425966cb88699f30.zip
FreeBSD-src-1f0ad947a6c993e63b43f3e0425966cb88699f30.tar.gz
Rework r220198 change (by fabient). I believe it solves the problem from
the wrong direction. Before it, if preemption and end of time slice happen same time, thread was put to the head of the queue as for only preemption. It could cause single thread to run for indefinitely long time. r220198 handles it by not clearing TDF_NEEDRESCHED in case of preemption. But that causes delayed context switch every time preemption happens, even when not needed. Solve problem by introducing scheduler-specifoc thread flag TDF_SLICEEND, set when thread's time slice is over and it should be put to the tail of queue. Using SW_PREEMPT flag for that purpose as it was before just not enough informative to work correctly. On my tests this by 2-3 times reduces run time deviation (improves fairness) in cases when several threads share one CPU. Reviewed by: fabient MFC after: 2 months Sponsored by: iXsystems, Inc.
Diffstat (limited to 'sys/kern/sched_ule.c')
-rw-r--r--sys/kern/sched_ule.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index 726362d..719592a 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -189,6 +189,9 @@ static struct td_sched td_sched0;
#define SCHED_INTERACT_HALF (SCHED_INTERACT_MAX / 2)
#define SCHED_INTERACT_THRESH (30)
+/* Flags kept in td_flags. */
+#define TDF_SLICEEND TDF_SCHED2 /* Thread time slice is over. */
+
/*
* tickincr: Converts a stathz tick into a hz domain scaled by
* the shift factor. Without the shift the error rate
@@ -1841,7 +1844,7 @@ sched_switch(struct thread *td, struct thread *newtd, int flags)
struct td_sched *ts;
struct mtx *mtx;
int srqflag;
- int cpuid;
+ int cpuid, preempted;
THREAD_LOCK_ASSERT(td, MA_OWNED);
KASSERT(newtd == NULL, ("sched_switch: Unsupported newtd argument"));
@@ -1854,8 +1857,8 @@ 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;
+ preempted = !(td->td_flags & TDF_SLICEEND);
+ td->td_flags &= ~(TDF_NEEDRESCHED | TDF_SLICEEND);
td->td_owepreempt = 0;
tdq->tdq_switchcnt++;
/*
@@ -1867,7 +1870,7 @@ sched_switch(struct thread *td, struct thread *newtd, int flags)
TD_SET_CAN_RUN(td);
} else if (TD_IS_RUNNING(td)) {
MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
- srqflag = (flags & SW_PREEMPT) ?
+ srqflag = preempted ?
SRQ_OURSELF|SRQ_YIELDING|SRQ_PREEMPTED :
SRQ_OURSELF|SRQ_YIELDING;
#ifdef SMP
@@ -2237,7 +2240,7 @@ sched_clock(struct thread *td)
* We're out of time, force a requeue at userret().
*/
ts->ts_slice = sched_slice;
- td->td_flags |= TDF_NEEDRESCHED;
+ td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
}
/*
OpenPOWER on IntegriCloud