From nobody Fri Apr 3 15:27:26 2026 X-Original-To: dev-commits-src-branches@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4fnMzL57shz6YgZb for ; Fri, 03 Apr 2026 15:27:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fnMzL178tz3hP2 for ; Fri, 03 Apr 2026 15:27:26 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775230046; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nn520/yk/QeIpZN6j1UnDShQ9GGninfPcx3QIOsmMZc=; b=cpo3k2DRgVKciTZT6nJY6wr6K5glBE6wVg5zfAQqz/djAY35NlfJDv9/WfUVCmEUSpd8Ju vzAARmVAbNaujLo9KVJQg8ClhQgR5yUfBeq1EgzxMTNVro4NxVmHDLdfjE9ws8smygBMsk z/TpwOV+DsAG5A6UfUE3OMSGakETTXZNFVNYHGbJv4SPvaYSjdyASqoEk6ie9hJO73AFXC slMixnDlXo8300/7DCPB3k7wrx80K8u/7aGRAznV/3oIiuTf3fBsGL9xBcZ6nEivRMSXqw 0uzMaPFt2HMGdeyy6ZcsBRTVDwwUzwa0g/mEXNdt8h8khHmIVpIW/rHFaxdg7A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1775230046; a=rsa-sha256; cv=none; b=rqQWBWW3s8dXLrfcVc+qsSPuQIKge8fZh2vhLL4XmEQ3n+SyTRe1yU7olSe+BVCuTaZsVl AmB8b2kFQNsufNXYsY2AjPNbQ0kMgEf3S1vrpivR6+AdhD0zxCno0L239sSKMzs3xZxM4c MmrI50JytrBkAUHB4FwblGzLC5oOrACjfI5r0THfMRAgwUX3m1cSnrnUlW5iDkbHMDbL9A oTHB5Rui7iEnlvspN7jSOcId36s7T/VJxxixkxTVFOyTMATorEYYdaK8sS3jqdtuFzA1pp 7c8EpKIouQrZ4T1i9DgC8kj7lFA1We8gIDKpugOno9CGjnEkQ+bRTpcWP2QNyw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775230046; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nn520/yk/QeIpZN6j1UnDShQ9GGninfPcx3QIOsmMZc=; b=Wi3Q7EEaJQ04IK6IoLLinFvHaUfltRlylwxDnpgvk6bVQ7f8doMFGRieS/5S/6X/sRLtZI ijVIjeaYMB6Ofx5jGKhlulSKS1LXPVydr9ySMnUGXf3NOquPFli6iuVzBstZ6GoSUh7p3G 0YcYW4nN2FX/Wf/voHXN3JptqNDUc+ix1k3epk9wvEYAwliAA+KsyWEd3mSA7A7Q5WFpE4 mLuhb6DuMIqBwOWKqJO0h8ihORuoOALcmcgEhSbdaICTqK3nGVOV/GCzjCyidIPhD+3lph dtDFngJ6hdWYXALRpeNiEyY2XzHApmW8mC62QLs54ZgGAZ2wrm5jp53LCaCf4w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fnMzL0kjjzv46 for ; Fri, 03 Apr 2026 15:27:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 405a2 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 03 Apr 2026 15:27:26 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Jake Freeland Subject: git: 3c00f603a280 - stable/14 - timerfd: Fix interval callout scheduling List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jfree X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: 3c00f603a2801fd780666f9e94a26f264a887c90 Auto-Submitted: auto-generated Date: Fri, 03 Apr 2026 15:27:26 +0000 Message-Id: <69cfdc5e.405a2.6f1d4e7@gitrepo.freebsd.org> The branch stable/14 has been updated by jfree: URL: https://cgit.FreeBSD.org/src/commit/?id=3c00f603a2801fd780666f9e94a26f264a887c90 commit 3c00f603a2801fd780666f9e94a26f264a887c90 Author: Jake Freeland AuthorDate: 2026-03-20 06:33:03 +0000 Commit: Jake Freeland CommitDate: 2026-04-03 15:26:56 +0000 timerfd: Fix interval callout scheduling When a timerfd interval callout misses its scheduled activation time, a differential is calculated based on the actual activation time and the scheduled activation time. This differential is divided by the timerfd's interval time and the quotient is added to the timerfd's counter. Before this change, the next callout was scheduled to activate at: scheduled activation time + timerfd interval. This change fixes the scheduling of the next callout to activate at: actual activation time + timerfd interval - remainder. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D55790 MFC after: 2 weeks (cherry picked from commit 85c0f1a87da1fd1eb3e646e86f70e630c48da91a) --- sys/kern/sys_timerfd.c | 24 +++++++++++++----------- tests/sys/kern/timerfd.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/sys/kern/sys_timerfd.c b/sys/kern/sys_timerfd.c index 565ab3ad6ee6..236dfe8bb96a 100644 --- a/sys/kern/sys_timerfd.c +++ b/sys/kern/sys_timerfd.c @@ -393,23 +393,25 @@ static void timerfd_expire(void *arg) { struct timerfd *tfd = (struct timerfd *)arg; - struct timespec uptime; + sbintime_t exp, interval, now, next, diff; ++tfd->tfd_count; tfd->tfd_expired = true; if (timespecisset(&tfd->tfd_time.it_interval)) { + exp = tstosbt(tfd->tfd_time.it_value); + interval = tstosbt(tfd->tfd_time.it_interval); + now = sbinuptime(); + next = now + interval; + /* Count missed events. */ - nanouptime(&uptime); - if (timespeccmp(&uptime, &tfd->tfd_time.it_value, >)) { - timespecsub(&uptime, &tfd->tfd_time.it_value, &uptime); - tfd->tfd_count += tstosbt(uptime) / - tstosbt(tfd->tfd_time.it_interval); + if (now > exp) { + diff = now - exp; + tfd->tfd_count += diff / interval; + next -= diff % interval; } - timespecadd(&tfd->tfd_time.it_value, - &tfd->tfd_time.it_interval, &tfd->tfd_time.it_value); - callout_schedule_sbt(&tfd->tfd_callout, - tstosbt(tfd->tfd_time.it_value), - 0, C_ABSOLUTE); + + callout_schedule_sbt(&tfd->tfd_callout, next, 0, C_ABSOLUTE); + tfd->tfd_time.it_value = sbttots(next); } else { /* Single shot timer. */ callout_deactivate(&tfd->tfd_callout); diff --git a/tests/sys/kern/timerfd.c b/tests/sys/kern/timerfd.c index 37cb4924faf1..b24d093b346e 100644 --- a/tests/sys/kern/timerfd.c +++ b/tests/sys/kern/timerfd.c @@ -949,6 +949,34 @@ ATF_TC_BODY(timerfd__reset_to_very_long, tc) ATF_REQUIRE(errno == EAGAIN); } +ATF_TC_WITHOUT_HEAD(timerfd__missed_events); +ATF_TC_BODY(timerfd__missed_events, tc) +{ + struct itimerspec its = { }; + uint64_t timeouts; + int timerfd; + + timerfd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC); + ATF_REQUIRE(timerfd >= 0); + + ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &its.it_value) == 0); + its.it_value.tv_sec -= 1000; + its.it_interval.tv_sec = 1; + + ATF_REQUIRE(timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &its, + NULL) == 0); + + ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) == + sizeof(timeouts)); + ATF_REQUIRE_MSG(timeouts == 1001, "%ld", (long)timeouts); + + ATF_REQUIRE(read(timerfd, &timeouts, sizeof(timeouts)) == + sizeof(timeouts)); + ATF_REQUIRE_MSG(timeouts == 1, "%ld", (long)timeouts); + + ATF_REQUIRE(close(timerfd) == 0); +} + /* * Tests requiring root (clock_settime on CLOCK_REALTIME). * Tests gracefully skip if not running as root. @@ -1306,6 +1334,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, timerfd__short_evfilt_timer_timeout); ATF_TP_ADD_TC(tp, timerfd__unmodified_errno); ATF_TP_ADD_TC(tp, timerfd__reset_to_very_long); + ATF_TP_ADD_TC(tp, timerfd__missed_events); ATF_TP_ADD_TC(tp, timerfd_root__zero_read_on_abs_realtime); ATF_TP_ADD_TC(tp, timerfd_root__read_on_abs_realtime_no_interval);