mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Shashank Mohan Jain <jain.sm@gmail.com>
To: John Stultz <jstultz@google.com>, Thomas Gleixner <tglx@kernel.org>
Cc: Stephen Boyd <sboyd@kernel.org>,
	Miroslav Lichvar <mlichvar@redhat.com>,
	Eric Dumazet <edumazet@google.com>,
	Joel Granados <joel.granados@kernel.org>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 3/3] time/kunit: Add tests for usecs_to_jiffies() and jiffies_to_clock_t()
Date: Mon, 28 Sep 2026 15:06:01 +0530	[thread overview]
Message-ID: <20260928093601.79224-4-jain.sm@gmail.com> (raw)
In-Reply-To: <20260928093601.79224-1-jain.sm@gmail.com>

Check that jiffies_to_clock_t() and jiffies_64_to_clock_t() invert
clock_t_to_jiffies() for every clock_t value that is a whole number of
jiffies, and that usecs_to_jiffies() rounds up and never saturates for
any unsigned int input, both through the out-of-line and the
constant-folded path.

The tests do not depend on HZ. With HZ=100 (UML) the usecs_to_jiffies()
test fails without the preceding fix for the values close to UINT_MAX,
and with HZ=300 both tests fail without the preceding fixes. Each loop
stops at its first failure, so a failing run reports a handful of
values instead of thousands.

Assisted-by: LLM
Signed-off-by: Shashank Mohan Jain <jain.sm@gmail.com>
---
Run with kunit.py, filter "time_test_cases.*jiffies*", with and without
patches 1-2, on UML x86_64 (HZ=100) and on qemu x86_64 and i386 (TCG)
with CONFIG_HZ_300=y. Also on UML x86_64 with HZ/USER_HZ temporarily
edited: with patches 1-2 both tests pass at 24/100, 1024/100, 1200/100,
32/1024, 1024/1024 and 1200/1024; without them both fail at 1200/100
and 1024/1024.
Without the fixes, the HZ=300 x86_64 run now reports 15 failed
expectations (4 KB of output) instead of about 2,900. Prepared with
Claude Code (Anthropic), model Claude Opus 5.5 (claude-opus-5-5).

 kernel/time/time_test.c | 79 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 79 insertions(+)

diff --git a/kernel/time/time_test.c b/kernel/time/time_test.c
index 1b99180da288..77e1ec1d5d8b 100644
--- a/kernel/time/time_test.c
+++ b/kernel/time/time_test.c
@@ -1,6 +1,9 @@
 // SPDX-License-Identifier: LGPL-2.1+
 
 #include <kunit/test.h>
+#include <linux/gcd.h>
+#include <linux/jiffies.h>
+#include <linux/math64.h>
 #include <linux/time.h>
 
 /*
@@ -87,8 +90,84 @@ static void time64_to_tm_test_date_range(struct kunit *test)
 	}
 }
 
+/*
+ * jiffies_to_clock_t() must be the inverse of clock_t_to_jiffies() for every
+ * clock_t value that is a whole number of jiffies, whatever HZ is.
+ */
+static void jiffies_to_clock_t_test(struct kunit *test)
+{
+	unsigned long step = USER_HZ / gcd(HZ, USER_HZ);
+	unsigned long x;
+
+	/* Bridge STP defaults, exposed in USER_HZ through sysfs and netlink */
+	KUNIT_EXPECT_EQ(test, 15 * USER_HZ, jiffies_to_clock_t(15 * HZ));
+	KUNIT_EXPECT_EQ(test, 2 * USER_HZ, jiffies_to_clock_t(2 * HZ));
+	KUNIT_EXPECT_EQ(test, 300 * USER_HZ, jiffies_to_clock_t(300 * HZ));
+	/* Large enough to catch a rounded NSEC_PER_SEC / USER_HZ (alpha) */
+	KUNIT_EXPECT_EQ(test, 10000 * USER_HZ, jiffies_to_clock_t(10000 * HZ));
+
+	for (x = 0; x <= 100 * USER_HZ; x += step) {
+		unsigned long j = clock_t_to_jiffies(x);
+		clock_t c = jiffies_to_clock_t(j);
+		u64 c64 = jiffies_64_to_clock_t(j);
+
+		KUNIT_ASSERT_EQ_MSG(test, x * HZ, (u64)j * USER_HZ,
+				    "clock_t %lu -> %lu jiffies", x, j);
+		if (c != (long)x || c64 != x) {
+			KUNIT_FAIL(test, "clock_t %lu -> %lu jiffies -> %ld / %llu",
+				   x, j, (long)c, c64);
+			break;
+		}
+	}
+}
+
+/*
+ * Every unsigned int number of microseconds fits in MAX_JIFFY_OFFSET jiffies
+ * for any supported HZ, so usecs_to_jiffies() must never saturate. It must
+ * round up; when HZ does not divide USEC_PER_SEC, the reciprocal
+ * multiplication may round up by one more jiffy for large values.
+ */
+static bool check_usecs_to_jiffies(struct kunit *test, unsigned int u,
+				   unsigned long got)
+{
+	unsigned long want = DIV_ROUND_UP_ULL((u64)u * HZ, USEC_PER_SEC);
+
+	if (got >= want && got <= want + !!(USEC_PER_SEC % HZ))
+		return true;
+	KUNIT_FAIL(test, "usecs_to_jiffies(%u) = %lu, want %lu%s", u, got,
+		   want, USEC_PER_SEC % HZ ? " or one more" : "");
+	return false;
+}
+
+static void usecs_to_jiffies_test(struct kunit *test)
+{
+	static const unsigned int vals[] = {
+		0, 1, 999, 1000, 1001, 1000000, 1431649098, 1431649099,
+		2000000000, 3000000000U, UINT_MAX - 20000, UINT_MAX - 1,
+		UINT_MAX,
+	};
+	u64 x;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(vals); i++)
+		check_usecs_to_jiffies(test, vals[i], usecs_to_jiffies(vals[i]));
+
+	for (x = 0; x <= UINT_MAX; x += 999983)
+		if (!check_usecs_to_jiffies(test, x, usecs_to_jiffies(x)))
+			break;
+	for (x = UINT_MAX - 30000; x <= UINT_MAX; x++)
+		if (!check_usecs_to_jiffies(test, x, usecs_to_jiffies(x)))
+			break;
+
+	/* Constant-folded variant */
+	check_usecs_to_jiffies(test, 3000000000U, usecs_to_jiffies(3000000000U));
+	check_usecs_to_jiffies(test, UINT_MAX, usecs_to_jiffies(UINT_MAX));
+}
+
 static struct kunit_case time_test_cases[] = {
 	KUNIT_CASE_SLOW(time64_to_tm_test_date_range),
+	KUNIT_CASE(jiffies_to_clock_t_test),
+	KUNIT_CASE(usecs_to_jiffies_test),
 	{}
 };
 
-- 
2.43.0


      parent reply	other threads:[~2026-09-28  9:36 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-28  9:35 [PATCH 0/3] time/jiffies: Fix usecs_to_jiffies() saturation and jiffies_to_clock_t() rounding Shashank Mohan Jain
2026-09-28  9:35 ` [PATCH 1/3] time/jiffies: Don't saturate usecs_to_jiffies() on a truncated limit Shashank Mohan Jain
2026-09-28 11:38   ` Joel Granados
2026-09-28 12:09     ` shashank Jain
2026-09-28  9:36 ` [PATCH 2/3] time/jiffies: Use the exact HZ ratio in jiffies_to_clock_t() Shashank Mohan Jain
2026-09-28  9:36 ` Shashank Mohan Jain [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260928093601.79224-4-jain.sm@gmail.com \
    --to=jain.sm@gmail.com \
    --cc=edumazet@google.com \
    --cc=joel.granados@kernel.org \
    --cc=jstultz@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mlichvar@redhat.com \
    --cc=sboyd@kernel.org \
    --cc=tglx@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®