-/* $OpenBSD: kern_clockintr.c,v 1.13 2023/04/20 14:51:28 cheloha Exp $ */
+/* $OpenBSD: kern_clockintr.c,v 1.14 2023/04/21 02:41:06 cheloha Exp $ */
/*
* Copyright (c) 2003 Dale Rahn <drahn@openbsd.org>
* Copyright (c) 2020 Mark Kettenis <kettenis@openbsd.org>
void clockintr_statclock(struct clockintr *, void *);
void clockintr_statvar_init(int, uint32_t *, uint32_t *, uint32_t *);
uint64_t clockqueue_next(const struct clockintr_queue *);
+void clockqueue_reset_intrclock(struct clockintr_queue *);
uint64_t nsec_advance(uint64_t *, uint64_t, uint64_t);
/*
if (ISSET(cl->cl_flags, CLST_PENDING))
clockintr_cancel_locked(cl);
clockintr_schedule_locked(cl, expiration);
+ if (ISSET(cq->cq_flags, CQ_INTRCLOCK)) {
+ if (cl == TAILQ_FIRST(&cq->cq_pend)) {
+ if (cq == &curcpu()->ci_queue)
+ clockqueue_reset_intrclock(cq);
+ }
+ }
if (cl == cq->cq_running)
SET(cl->cl_flags, CLST_IGNORE_SHADOW);
mtx_leave(&cq->cq_mtx);
clockintr_cancel(struct clockintr *cl)
{
struct clockintr_queue *cq = cl->cl_queue;
+ int was_next;
if (cl == &cq->cq_shadow) {
CLR(cl->cl_flags, CLST_SHADOW_PENDING);
}
mtx_enter(&cq->cq_mtx);
- if (ISSET(cl->cl_flags, CLST_PENDING))
+ if (ISSET(cl->cl_flags, CLST_PENDING)) {
+ was_next = cl == TAILQ_FIRST(&cq->cq_pend);
clockintr_cancel_locked(cl);
+ if (ISSET(cq->cq_flags, CQ_INTRCLOCK)) {
+ if (was_next && !TAILQ_EMPTY(&cq->cq_pend)) {
+ if (cq == &curcpu()->ci_queue)
+ clockqueue_reset_intrclock(cq);
+ }
+ }
+ }
if (cl == cq->cq_running)
SET(cl->cl_flags, CLST_IGNORE_SHADOW);
mtx_leave(&cq->cq_mtx);
if (ISSET(cl->cl_flags, CLST_PENDING))
clockintr_cancel_locked(cl);
clockintr_schedule_locked(cl, expiration);
+ if (ISSET(cq->cq_flags, CQ_INTRCLOCK)) {
+ if (cl == TAILQ_FIRST(&cq->cq_pend)) {
+ if (cq == &curcpu()->ci_queue)
+ clockqueue_reset_intrclock(cq);
+ }
+ }
if (cl == cq->cq_running)
SET(cl->cl_flags, CLST_IGNORE_SHADOW);
mtx_leave(&cq->cq_mtx);
return TAILQ_FIRST(&cq->cq_pend)->cl_expiration;
}
+void
+clockqueue_reset_intrclock(struct clockintr_queue *cq)
+{
+ uint64_t exp, now;
+
+ MUTEX_ASSERT_LOCKED(&cq->cq_mtx);
+ KASSERT(ISSET(cq->cq_flags, CQ_INTRCLOCK));
+
+ exp = clockqueue_next(cq);
+ now = nsecuptime();
+ if (now < exp)
+ intrclock_rearm(&cq->cq_intrclock, exp - now);
+ else
+ intrclock_trigger(&cq->cq_intrclock);
+}
+
/*
* Advance *next in increments of period until it exceeds now.
* Returns the number of increments *next was advanced.