mpi@ suggests folding the pseudorandom advance code from
clockintr_statclock() into the clockintr API itself.  This replaces
three API calls -- clockintr_expiration(), clockintr_nsecuptime(), and
clockintr_schedule() -- we just one call to a new function,
clockintr_advance_random().

I'm fine with it.  A pseudorandom period is an odd thing and
supporting it is difficult.  Having a single bespoke API to support it
might be the lesser of two evils.

With this in place, the statclock() patch on tech@ can be simplified.

ok?

Index: kern_clockintr.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_clockintr.c,v
retrieving revision 1.33
diff -u -p -r1.33 kern_clockintr.c
--- kern_clockintr.c    26 Aug 2023 22:21:00 -0000      1.33
+++ kern_clockintr.c    5 Sep 2023 14:11:38 -0000
@@ -42,8 +42,8 @@ uint32_t statclock_avg;                       /* [I] average
 uint32_t statclock_min;                        /* [I] minimum statclock period 
(ns) */
 uint32_t statclock_mask;               /* [I] set of allowed offsets */
 
+uint64_t clockintr_advance_random(struct clockintr *, uint64_t, uint32_t);
 void clockintr_cancel_locked(struct clockintr *);
-uint64_t clockintr_expiration(const struct clockintr *);
 void clockintr_hardclock(struct clockintr *, void *);
 uint64_t clockintr_nsecuptime(const struct clockintr *);
 void clockintr_schedule(struct clockintr *, uint64_t);
@@ -345,6 +345,30 @@ clockintr_advance(struct clockintr *cl, 
        return count;
 }
 
+/*
+ * Custom version of clockintr_advance() to support a pseudorandom
+ * statclock() period.  Hopefully we can throw this out at some point
+ * in the future.
+ */
+uint64_t
+clockintr_advance_random(struct clockintr *cl, uint64_t lo, uint32_t mask)
+{
+       uint64_t count = 0;
+       struct clockintr_queue *cq = cl->cl_queue;
+       uint32_t off;
+
+       KASSERT(cl == &cq->cq_shadow);
+
+       while (cl->cl_expiration <= cq->cq_uptime) {
+               while ((off = (random() & mask)) == 0)
+                       continue;
+               cl->cl_expiration += lo + off;
+               count++;
+       }
+       SET(cl->cl_flags, CLST_SHADOW_PENDING);
+       return count;
+}
+
 void
 clockintr_cancel(struct clockintr *cl)
 {
@@ -402,21 +426,6 @@ clockintr_establish(struct clockintr_que
        return cl;
 }
 
-uint64_t
-clockintr_expiration(const struct clockintr *cl)
-{
-       uint64_t expiration;
-       struct clockintr_queue *cq = cl->cl_queue;
-
-       if (cl == &cq->cq_shadow)
-               return cl->cl_expiration;
-
-       mtx_enter(&cq->cq_mtx);
-       expiration = cl->cl_expiration;
-       mtx_leave(&cq->cq_mtx);
-       return expiration;
-}
-
 void
 clockintr_schedule(struct clockintr *cl, uint64_t expiration)
 {
@@ -478,13 +487,6 @@ clockintr_stagger(struct clockintr *cl, 
        mtx_leave(&cq->cq_mtx);
 }
 
-uint64_t
-clockintr_nsecuptime(const struct clockintr *cl)
-{
-       KASSERT(cl == &cl->cl_queue->cq_shadow);
-       return cl->cl_queue->cq_uptime;
-}
-
 void
 clockintr_hardclock(struct clockintr *cl, void *frame)
 {
@@ -498,20 +500,11 @@ clockintr_hardclock(struct clockintr *cl
 void
 clockintr_statclock(struct clockintr *cl, void *frame)
 {
-       uint64_t count, expiration, i, uptime;
-       uint32_t off;
+       uint64_t count, i;
 
        if (ISSET(clockintr_flags, CL_RNDSTAT)) {
-               count = 0;
-               expiration = clockintr_expiration(cl);
-               uptime = clockintr_nsecuptime(cl);
-               while (expiration <= uptime) {
-                       while ((off = (random() & statclock_mask)) == 0)
-                               continue;
-                       expiration += statclock_min + off;
-                       count++;
-               }
-               clockintr_schedule(cl, expiration);
+               count = clockintr_advance_random(cl, statclock_min,
+                   statclock_mask);
        } else {
                count = clockintr_advance(cl, statclock_avg);
        }

Reply via email to