This is the next piece of the clock interrupt reorganization patch
series.
This patch removes the roundrobin() call from hardclock() and makes
roundrobin() an independent clock interrupt.
- Revise roundrobin() to make it a valid clock interrupt callback.
It remains periodic. It still runs at one tenth of the hardclock
frequency.
- Account for multiple expirations in roundrobin(). If two or more
intervals have elapsed we set SPCF_SHOULDYIELD immediately.
This preserves existing behavior: hardclock() is called multiple
times during clockintr_hardclock() if clock interrupts are blocked
for long enough.
- Each schedstate_percpu has its own roundrobin() handle, spc_roundrobin.
spc_roundrobin is established during sched_init_cpu(), staggered during
the first clockintr_cpu_init() call, and advanced during clockintr_cpu_init().
Expirations during suspend/resume are discarded.
- spc_rrticks and rrticks_init are now useless. Delete them.
ok?
Also, yes, I see the growing pile of scheduler-controlled clock
interrupt handles. My current plan is to move the setup code at the
end of clockintr_cpu_init() to a different routine, maybe something
like "sched_start_cpu()". On the primary CPU you'd call it immediately
after cpu_initclocks(). On secondary CPUs you'd call it at the end of
cpu_hatch() just before cpu_switchto().
In any case, we will need to find a home for that code someplace. It
can't stay in clockintr_cpu_init() forever.
Index: kern/sched_bsd.c
===================================================================
RCS file: /cvs/src/sys/kern/sched_bsd.c,v
retrieving revision 1.79
diff -u -p -r1.79 sched_bsd.c
--- kern/sched_bsd.c 5 Aug 2023 20:07:55 -0000 1.79
+++ kern/sched_bsd.c 5 Aug 2023 22:15:25 -0000
@@ -56,7 +56,6 @@
int lbolt; /* once a second sleep address */
-int rrticks_init; /* # of hardclock ticks per roundrobin() */
#ifdef MULTIPROCESSOR
struct __mp_lock sched_lock;
@@ -69,21 +68,23 @@ uint32_t decay_aftersleep(uint32_t, uin
* Force switch among equal priority processes every 100ms.
*/
void
-roundrobin(struct cpu_info *ci)
+roundrobin(struct clockintr *cl, void *cf)
{
+ struct cpu_info *ci = curcpu();
struct schedstate_percpu *spc = &ci->ci_schedstate;
+ uint64_t count;
- spc->spc_rrticks = rrticks_init;
+ count = clockintr_advance(cl, hardclock_period * 10);
if (ci->ci_curproc != NULL) {
- if (spc->spc_schedflags & SPCF_SEENRR) {
+ if (spc->spc_schedflags & SPCF_SEENRR || count >= 2) {
/*
* The process has already been through a roundrobin
* without switching and may be hogging the CPU.
* Indicate that the process should yield.
*/
atomic_setbits_int(&spc->spc_schedflags,
- SPCF_SHOULDYIELD);
+ SPCF_SEENRR | SPCF_SHOULDYIELD);
} else {
atomic_setbits_int(&spc->spc_schedflags,
SPCF_SEENRR);
@@ -695,8 +696,6 @@ scheduler_start(void)
* its job.
*/
timeout_set(&schedcpu_to, schedcpu, &schedcpu_to);
-
- rrticks_init = hz / 10;
schedcpu(&schedcpu_to);
#ifndef SMALL_KERNEL
Index: kern/kern_sched.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_sched.c,v
retrieving revision 1.84
diff -u -p -r1.84 kern_sched.c
--- kern/kern_sched.c 5 Aug 2023 20:07:55 -0000 1.84
+++ kern/kern_sched.c 5 Aug 2023 22:15:25 -0000
@@ -102,6 +102,12 @@ sched_init_cpu(struct cpu_info *ci)
if (spc->spc_profclock == NULL)
panic("%s: clockintr_establish profclock", __func__);
}
+ if (spc->spc_roundrobin == NULL) {
+ spc->spc_roundrobin = clockintr_establish(&ci->ci_queue,
+ roundrobin);
+ if (spc->spc_roundrobin == NULL)
+ panic("%s: clockintr_establish roundrobin", __func__);
+ }
kthread_create_deferred(sched_kthreads_create, ci);
Index: kern/kern_clockintr.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_clockintr.c,v
retrieving revision 1.30
diff -u -p -r1.30 kern_clockintr.c
--- kern/kern_clockintr.c 5 Aug 2023 20:07:55 -0000 1.30
+++ kern/kern_clockintr.c 5 Aug 2023 22:15:25 -0000
@@ -204,6 +204,11 @@ clockintr_cpu_init(const struct intrcloc
clockintr_stagger(spc->spc_profclock, profclock_period,
multiplier, MAXCPUS);
}
+ if (spc->spc_roundrobin->cl_expiration == 0) {
+ clockintr_stagger(spc->spc_roundrobin, hardclock_period,
+ multiplier, MAXCPUS);
+ }
+ clockintr_advance(spc->spc_roundrobin, hardclock_period * 10);
if (reset_cq_intrclock)
SET(cq->cq_flags, CQ_INTRCLOCK);
Index: kern/kern_clock.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_clock.c,v
retrieving revision 1.111
diff -u -p -r1.111 kern_clock.c
--- kern/kern_clock.c 5 Aug 2023 20:07:55 -0000 1.111
+++ kern/kern_clock.c 5 Aug 2023 22:15:25 -0000
@@ -113,9 +113,6 @@ hardclock(struct clockframe *frame)
{
struct cpu_info *ci = curcpu();
- if (--ci->ci_schedstate.spc_rrticks <= 0)
- roundrobin(ci);
-
#if NDT > 0
DT_ENTER(profile, NULL);
if (CPU_IS_PRIMARY(ci))
Index: sys/sched.h
===================================================================
RCS file: /cvs/src/sys/sys/sched.h,v
retrieving revision 1.60
diff -u -p -r1.60 sched.h
--- sys/sched.h 5 Aug 2023 20:07:56 -0000 1.60
+++ sys/sched.h 5 Aug 2023 22:15:25 -0000
@@ -105,10 +105,10 @@ struct schedstate_percpu {
u_int spc_schedticks; /* ticks for schedclock() */
u_int64_t spc_cp_time[CPUSTATES]; /* CPU state statistics */
u_char spc_curpriority; /* usrpri of curproc */
- int spc_rrticks; /* ticks until roundrobin() */
struct clockintr *spc_itimer; /* [o] itimer_update handle */
struct clockintr *spc_profclock; /* [o] profclock handle */
+ struct clockintr *spc_roundrobin; /* [o] roundrobin handle */
u_int spc_nrun; /* procs on the run queues */
@@ -150,11 +150,11 @@ extern int rrticks_init; /* ticks per r
struct proc;
void schedclock(struct proc *);
-struct cpu_info;
-void roundrobin(struct cpu_info *);
+void roundrobin(struct clockintr *, void *);
void scheduler_start(void);
void userret(struct proc *p);
+struct cpu_info;
void sched_init_cpu(struct cpu_info *);
void sched_idle(void *);
void sched_exit(struct proc *);