[Midnightbsd-cvs] src [8164] trunk/sys/kern: Rework r220198 change (by fabient).

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Fri Sep 16 22:29:25 EDT 2016


Revision: 8164
          http://svnweb.midnightbsd.org/src/?rev=8164
Author:   laffer1
Date:     2016-09-16 22:29:24 -0400 (Fri, 16 Sep 2016)
Log Message:
-----------
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.

Obtained from FreeBSD

Revision Links:
--------------
    http://svnweb.midnightbsd.org/src/?rev=220198
    http://svnweb.midnightbsd.org/src/?rev=220198

Modified Paths:
--------------
    trunk/sys/kern/sched_4bsd.c
    trunk/sys/kern/sched_ule.c

Modified: trunk/sys/kern/sched_4bsd.c
===================================================================
--- trunk/sys/kern/sched_4bsd.c	2016-09-17 02:26:43 UTC (rev 8163)
+++ trunk/sys/kern/sched_4bsd.c	2016-09-17 02:29:24 UTC (rev 8164)
@@ -105,6 +105,7 @@
 /* flags kept in td_flags */
 #define TDF_DIDRUN	TDF_SCHED0	/* thread actually ran. */
 #define TDF_BOUND	TDF_SCHED1	/* Bound to one CPU. */
+#define	TDF_SLICEEND	TDF_SCHED2	/* Thread time slice is over. */
 
 /* flags kept in ts_flags */
 #define	TSF_AFFINITY	0x0001		/* Has a non-"full" CPU set. */
@@ -726,7 +727,7 @@
 	 */
 	if (!TD_IS_IDLETHREAD(td) && (--ts->ts_slice <= 0)) {
 		ts->ts_slice = sched_slice;
-		td->td_flags |= TDF_NEEDRESCHED;
+		td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
 	}
 
 	stat = DPCPU_PTR(idlestat);
@@ -942,6 +943,7 @@
 	struct mtx *tmtx;
 	struct td_sched *ts;
 	struct proc *p;
+	int preempted;
 
 	tmtx = NULL;
 	ts = td->td_sched;
@@ -963,8 +965,8 @@
 		sched_load_rem();
 
 	td->td_lastcpu = td->td_oncpu;
-	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;
 	td->td_oncpu = NOCPU;
 
@@ -982,7 +984,7 @@
 	} else {
 		if (TD_IS_RUNNING(td)) {
 			/* Put us back on the run queue. */
-			sched_add(td, (flags & SW_PREEMPT) ?
+			sched_add(td, preempted ?
 			    SRQ_OURSELF|SRQ_YIELDING|SRQ_PREEMPTED :
 			    SRQ_OURSELF|SRQ_YIELDING);
 		}

Modified: trunk/sys/kern/sched_ule.c
===================================================================
--- trunk/sys/kern/sched_ule.c	2016-09-17 02:26:43 UTC (rev 8163)
+++ trunk/sys/kern/sched_ule.c	2016-09-17 02:29:24 UTC (rev 8164)
@@ -189,6 +189,9 @@
 #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 @@
 	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 @@
 	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 @@
 		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 @@
 	 * 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;
 }
 
 /*



More information about the Midnightbsd-cvs mailing list