git: 954cffe95de1 - main - ule: Simplistic time-sharing for interrupt threads.

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Thu, 14 Jul 2022 20:15:37 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=954cffe95de1b9d70ed804daa45b7921f0f5c9da

commit 954cffe95de1b9d70ed804daa45b7921f0f5c9da
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2022-07-14 20:13:57 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2022-07-14 20:13:57 +0000

    ule: Simplistic time-sharing for interrupt threads.
    
    If an interrupt thread runs for a full quantum without yielding the
    CPU, demote its priority and schedule a preemption to give other
    ithreads a turn.
    
    Reviewed by:    kib, markj
    Sponsored by:   Netflix
    Differential Revision:  https://reviews.freebsd.org/D35644
---
 sys/kern/sched_ule.c | 44 +++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 41 insertions(+), 3 deletions(-)

diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index c4eb46944b43..b5ddae868ebb 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -2375,6 +2375,15 @@ sched_wakeup(struct thread *td, int srqflags)
 		sched_interact_update(td);
 		sched_pctcpu_update(ts, 0);
 	}
+
+	/*
+	 * When resuming an idle ithread, restore its base ithread
+	 * priority.
+	 */
+	if (PRI_BASE(td->td_pri_class) == PRI_ITHD &&
+	    td->td_priority != td->td_base_ithread_pri)
+		sched_prio(td, td->td_base_ithread_pri);
+
 	/*
 	 * Reset the slice value since we slept and advanced the round-robin.
 	 */
@@ -2542,9 +2551,25 @@ sched_userret_slowpath(struct thread *td)
 	thread_unlock(td);
 }
 
+SCHED_STAT_DEFINE(ithread_demotions, "Interrupt thread priority demotions");
+SCHED_STAT_DEFINE(ithread_preemptions,
+    "Interrupt thread preemptions due to time-sharing");
+
+/*
+ * Return time slice for a given thread.  For ithreads this is
+ * sched_slice.  For other threads it is tdq_slice(tdq).
+ */
+static inline int
+td_slice(struct thread *td, struct tdq *tdq)
+{
+	if (PRI_BASE(td->td_pri_class) == PRI_ITHD)
+		return (sched_slice);
+	return (tdq_slice(tdq));
+}
+
 /*
  * Handle a stathz tick.  This is really only relevant for timeshare
- * threads.
+ * and interrupt threads.
  */
 void
 sched_clock(struct thread *td, int cnt)
@@ -2602,9 +2627,22 @@ sched_clock(struct thread *td, int cnt)
 	 * time slice (default is 100ms).
 	 */
 	ts->ts_slice += cnt;
-	if (ts->ts_slice >= tdq_slice(tdq)) {
+	if (ts->ts_slice >= td_slice(td, tdq)) {
 		ts->ts_slice = 0;
-		td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
+
+		/*
+		 * If an ithread uses a full quantum, demote its
+		 * priority and preempt it.
+		 */
+		if (PRI_BASE(td->td_pri_class) == PRI_ITHD) {
+			SCHED_STAT_INC(ithread_preemptions);
+			td->td_owepreempt = 1;
+			if (td->td_base_pri + RQ_PPQ < PRI_MAX_ITHD) {
+				SCHED_STAT_INC(ithread_demotions);
+				sched_prio(td, td->td_base_pri + RQ_PPQ);
+			}
+		} else
+			td->td_flags |= TDF_NEEDRESCHED | TDF_SLICEEND;
 	}
 }