clockintr_cpu_init: mask CQ_INTRCLOCK while advancing schedule
authorcheloha <cheloha@openbsd.org>
Thu, 20 Apr 2023 00:24:11 +0000 (00:24 +0000)
committercheloha <cheloha@openbsd.org>
Thu, 20 Apr 2023 00:24:11 +0000 (00:24 +0000)
Allowing the intrclock to fire in the midst of clockintr_cpu_init()
would complicate the function a lot.  However, in a future patch we
will need to enable intrclock operations in clockintr_advance(),
clockintr_cancel(), and clockintr_schedule().

We can avoid this conflict by masking CQ_INTRCLOCK while we're
updating the internal clockintrs in clockintr_cpu_init().  When we no
longer need clockintr_cpu_init(), this workaround will disappear.

sys/kern/kern_clockintr.c

index c163df7..94ac0a7 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_clockintr.c,v 1.11 2023/04/19 14:30:35 cheloha Exp $ */
+/* $OpenBSD: kern_clockintr.c,v 1.12 2023/04/20 00:24:11 cheloha Exp $ */
 /*
  * Copyright (c) 2003 Dale Rahn <drahn@openbsd.org>
  * Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
@@ -110,6 +110,7 @@ clockintr_cpu_init(const struct intrclock *ic)
        uint64_t multiplier = 0, offset;
        struct cpu_info *ci = curcpu();
        struct clockintr_queue *cq = &ci->ci_queue;
+       int reset_cq_intrclock = 0;
 
        KASSERT(ISSET(clockintr_flags, CL_INIT));
 
@@ -141,6 +142,16 @@ clockintr_cpu_init(const struct intrclock *ic)
                }
        }
 
+       /*
+        * Mask CQ_INTRCLOCK while we're advancing the internal clock
+        * interrupts.  We don't want the intrclock to fire until this
+        * thread reaches clockintr_trigger().
+        */
+       if (ISSET(cq->cq_flags, CQ_INTRCLOCK)) {
+               CLR(cq->cq_flags, CQ_INTRCLOCK);
+               reset_cq_intrclock = 1;
+       }
+
        /*
         * Until we understand scheduler lock contention better, stagger
         * the hardclock and statclock so they don't all happen at once.
@@ -176,6 +187,9 @@ clockintr_cpu_init(const struct intrclock *ic)
                clockintr_advance(cq->cq_schedclock, schedclock_period);
        }
 
+       if (reset_cq_intrclock)
+               SET(cq->cq_flags, CQ_INTRCLOCK);
+
        SET(cq->cq_flags, CQ_INIT);
 }