tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

hardclock(9) could go.



Hello,

I'm investigating how to make our kernel less reliant on hardclock(9)
being called at hz(9).

Please find attached a patch to reduce hardclock(9)'s responsibilities
wrt the rest of the system timekeeping.

The idea is that hardclock(9) will drive callout_hardclock() for now,
until we modify the latter to not expect a fixed "tick" rate (ie; hz) -
at which point we have the option of several callers - for eg: a
carefully crafted one-shot interrupt at a programmable timespan.

With this patch, I'd like to understand what it does to the system as-is
- so ideally as many configs as possible (different arch/ and MP/UP) as
well as virtualisation situations (eg: Xen).

I look forward to your comments and test results, if any.

Many Thanks,
-- 
Math/(~cherry)

diff -r 95278b51da8b sys/kern/kern_clock.c
--- a/sys/kern/kern_clock.c	Tue Mar 19 10:53:00 2024 +0000
+++ b/sys/kern/kern_clock.c	Wed Mar 20 05:24:07 2024 +0000
@@ -107,6 +107,9 @@
 
 static int sysctl_kern_clockrate(SYSCTLFN_PROTO);
 
+static callout_t clocktick_coh_var,  *clocktick_coh =
+  &clocktick_coh_var; /* Callout handle for clock tick */
+
 /*
  * Clock handling routines.
  *
@@ -222,6 +225,42 @@
 	return atomic_load_relaxed(&hardclock_ticks);
 }
 
+static void
+clocktick(void *coptr)
+{
+	struct lwp *l;
+	struct cpu_info *ci;
+
+	ci = curcpu();
+	l = ci->ci_onproc;
+
+	/*
+	 * If no separate schedclock is provided, call it here
+	 * at about 16 Hz.
+	 */
+	if (schedhz == 0) {
+		if ((int)(--ci->ci_schedstate.spc_schedticks) <= 0) {
+			schedclock(l);
+			ci->ci_schedstate.spc_schedticks = hardscheddiv;
+		}
+	}
+	if ((--ci->ci_schedstate.spc_ticks) <= 0)
+		sched_tick(ci);
+
+	if (CPU_IS_PRIMARY(ci)) {
+		atomic_store_relaxed(&hardclock_ticks,
+		    atomic_load_relaxed(&hardclock_ticks) + 1);
+		tc_ticktock();
+	}
+
+	/*
+	 * Make sure the CPUs and timecounter are making progress.
+	 */
+	heartbeat();
+
+	callout_schedule(clocktick_coh, 1); /* Schedule next one */
+}
+     
 /*
  * Initialize clock frequencies and start both clocks running.
  */
@@ -254,6 +293,10 @@
 	 */
 	intr_timecounter.tc_frequency = hz;
 	tc_init(&intr_timecounter);
+	callout_init(clocktick_coh, CALLOUT_MPSAFE);
+	callout_setfunc(clocktick_coh, clocktick, curcpu());
+	callout_schedule(clocktick_coh, 1); /* Schedule first one */
+	callout_hardclock(); /* And kick it down the road */
 
 	/*
 	 * Compute profhz and stathz, fix profhz if needed.
@@ -318,33 +361,9 @@
 	if (stathz == 0)
 		statclock(frame);
 	/*
-	 * If no separate schedclock is provided, call it here
-	 * at about 16 Hz.
-	 */
-	if (schedhz == 0) {
-		if ((int)(--ci->ci_schedstate.spc_schedticks) <= 0) {
-			schedclock(l);
-			ci->ci_schedstate.spc_schedticks = hardscheddiv;
-		}
-	}
-	if ((--ci->ci_schedstate.spc_ticks) <= 0)
-		sched_tick(ci);
-
-	if (CPU_IS_PRIMARY(ci)) {
-		atomic_store_relaxed(&hardclock_ticks,
-		    atomic_load_relaxed(&hardclock_ticks) + 1);
-		tc_ticktock();
-	}
-
-	/*
-	 * Make sure the CPUs and timecounter are making progress.
-	 */
-	heartbeat();
-
-	/*
 	 * Update real-time timeout queue.
 	 */
-	callout_hardclock();
+	callout_hardclock();  
 }
 
 /*


Home | Main Index | Thread Index | Old Index