Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 May 2021 16:51:03 GMT
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 7cb40543e964 - main - filt_timerexpire: do not iterate over the interval
Message-ID:  <202105031651.143Gp31q065156@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=7cb40543e96451092d5bc6bb3d96ebee364327e0

commit 7cb40543e96451092d5bc6bb3d96ebee364327e0
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-04-28 16:28:49 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-05-03 16:49:54 +0000

    filt_timerexpire: do not iterate over the interval
    
    User-supplied data might make this loop too time-consuming. Divide
    directly, and handle both the possibility that we were woken up earlier,
    and arithmetic overflows/underflows from the calculation.
    
    Reported and tested by: pho (previous version)
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D30069
---
 sys/kern/kern_event.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 33a6cdcda486..1067e7f128b7 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -718,6 +718,7 @@ filt_timerexpire_l(struct knote *kn, bool proc_locked)
 {
 	struct kq_timer_cb_data *kc;
 	struct proc *p;
+	uint64_t delta;
 	sbintime_t now;
 
 	kc = kn->kn_ptr.p_v;
@@ -728,9 +729,17 @@ filt_timerexpire_l(struct knote *kn, bool proc_locked)
 		return;
 	}
 
-	for (now = sbinuptime(); kc->next <= now; kc->next += kc->to)
-		kn->kn_data++;
-	KNOTE_ACTIVATE(kn, 0);	/* XXX - handle locking */
+	now = sbinuptime();
+	if (now >= kc->next) {
+		delta = (now - kc->next) / kc->to;
+		if (delta == 0)
+			delta = 1;
+		kn->kn_data += delta;
+		kc->next += (delta + 1) * kc->to;
+		if (now >= kc->next)	/* overflow */
+			kc->next = now + kc->to;
+		KNOTE_ACTIVATE(kn, 0);	/* XXX - handle locking */
+	}
 
 	/*
 	 * Initial check for stopped kc->p is racy.  It is fine to



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202105031651.143Gp31q065156>