[PATCH 3/3] time/kunit: Add tests for usecs_to_jiffies() and jiffies_to_clock_t()

From: Shashank Mohan Jain

Date: Mon Sep 28 2026 - 05:42:41 EST


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@xxxxxxxxx>
---
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