From nobody Fri Mar 20 07:16:14 2026 X-Original-To: dev-commits-src-all@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 4fcYl26v3Qz6VVk0 for ; Fri, 20 Mar 2026 07:16:14 +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 4fcYl23yVhz4LGw for ; Fri, 20 Mar 2026 07:16:14 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1773990974; 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=a6wD30pHUPaNHZpJIVSGKVYtxz796c8UW4DwVL5ICj8=; b=iG8W9eLkz1gUo54s8D4d5XzBlQzB+V6CG8+B/24tAmY+HH/JpJddvRqVl8OSSm7MCZL+rt KS0Zf+l3GWvDlkGITSTlFZZ6pyi6AjW7Uit6izyrQ1elcmKsoCreQAL5wEO7PyQQdnhm6w /9BncsTs1TrAtUcLbhAvgp0B0/iuGYbKnVJuFgfVrwaHkgdf+At3kdk0mLgy8NtUkG0JKz BV/U/YQtCpimo1ciA+6VxfHI1D5AUv1CpNs3dq9R7jRcuA5wDMu/EI1rPjXLD25GPKMSUl M9ekbypZa5zW3XbYf9H8F9HI0XVvEoqy72m+XbWjy5G0CXpoUN93Jz8xz9SiDw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1773990974; a=rsa-sha256; cv=none; b=TN3JoqSXlJ7yhPAqq9Qn/nZa8infEl1rfbW0v/H9d9tnzUQFIDSY/7LrUhKdntQM9+IfpB khQDRe+FMlHMjoHoEdjCpTmTyP9usFsI9c2oeeA3F/xgZPnIMbJ11IEm+U0+AeU/H3BmAb V8z/bvF4VAui3jrQdijJDGXVRk4JRHHHZG5iKuBCg0KWuDQlBdWDLa+U5T4WcktGmcA0Z3 iNTpMEQUX0KiZ1jmTidx6J6e1AAZYq+61d5nw2gILAvVgljff2d/9RGDBIGpCvseK7kHEL zZ2K0gskUEul87wfHGziK6o3cMYAG3sm/4iHs9qRFPcoTwBRaSygZuEv5RiTKg== 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=1773990974; 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=a6wD30pHUPaNHZpJIVSGKVYtxz796c8UW4DwVL5ICj8=; b=Ta5aBB7KkkCVqNXK4MCy0eUwuQ7a5ZzNu1PjesD/Zc3e6vYSG0dS8Je72Z8baBHqlgWb5J W+tW2dJ9PWqUrbxUuKjtMdv9IrUQ3nVvEZDWIsP3sL/q4bHdsceH9DonXU7+OG4W+JwpDX lpWuzvOgSwG7CoLz9mvkMBQ5KXf3ACaiUn90i9IiE1twzRow/r9RePp8Hb+h2b7ISJqufp jR/SglVekpwAmXpKnrmcfDcCNYXElDxKG7tK67CRzllCWCrbzXEGFUXNeNr1uJHVkA+wPR VnFnwzYOf1UyXkh/pcsKRBkQ8ZIuPLcTo8VY8ortJRK7U19DczIyYdVzhf+Kew== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fcYl23Gnbz1F6 for ; Fri, 20 Mar 2026 07:16:14 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3b7c5 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 20 Mar 2026 07:16:14 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Jake Freeland Subject: git: 85c0f1a87da1 - main - timerfd: Fix interval callout scheduling List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@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/main X-Git-Reftype: branch X-Git-Commit: 85c0f1a87da1fd1eb3e646e86f70e630c48da91a Auto-Submitted: auto-generated Date: Fri, 20 Mar 2026 07:16:14 +0000 Message-Id: <69bcf43e.3b7c5.37897cca@gitrepo.freebsd.org> The branch main has been updated by jfree: URL: https://cgit.FreeBSD.org/src/commit/?id=85c0f1a87da1fd1eb3e646e86f70e630c48da91a commit 85c0f1a87da1fd1eb3e646e86f70e630c48da91a Author: Jake Freeland AuthorDate: 2026-03-20 06:33:03 +0000 Commit: Jake Freeland CommitDate: 2026-03-20 07:15:08 +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 --- 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);