[LTP] [PATCH v2 11/31] testcases: sysfs: Add sys_clockevents01

Cyril Hrubis chrubis@suse.cz
Wed Aug 19 18:16:14 CEST 2026


A test for /sys/devices/system/clockevents/* files.

Signed-off-by: Cyril Hrubis <chrubis@suse.cz>
---
 runtest/sysfs                                 |   1 +
 .../devices/system/clockevents/.gitignore     |   1 +
 .../sysfs/devices/system/clockevents/Makefile |   7 +
 .../system/clockevents/sys_clockevents01.c    | 140 ++++++++++++++++++
 4 files changed, 149 insertions(+)
 create mode 100644 testcases/kernel/sysfs/devices/system/clockevents/.gitignore
 create mode 100644 testcases/kernel/sysfs/devices/system/clockevents/Makefile
 create mode 100644 testcases/kernel/sysfs/devices/system/clockevents/sys_clockevents01.c

diff --git a/runtest/sysfs b/runtest/sysfs
index 928b85928..3015c03f5 100644
--- a/runtest/sysfs
+++ b/runtest/sysfs
@@ -7,3 +7,4 @@ sys_cpu_topology02 sys_cpu_topology02
 sys_cpu_vulnerabilities01 sys_cpu_vulnerabilities01
 sys_cpu_smt01 sys_cpu_smt01
 sys_cpu_cache01 sys_cpu_cache01
+sys_clockevents01 sys_clockevents01
diff --git a/testcases/kernel/sysfs/devices/system/clockevents/.gitignore b/testcases/kernel/sysfs/devices/system/clockevents/.gitignore
new file mode 100644
index 000000000..9379d10dd
--- /dev/null
+++ b/testcases/kernel/sysfs/devices/system/clockevents/.gitignore
@@ -0,0 +1 @@
+/sys_clockevents01
diff --git a/testcases/kernel/sysfs/devices/system/clockevents/Makefile b/testcases/kernel/sysfs/devices/system/clockevents/Makefile
new file mode 100644
index 000000000..781865569
--- /dev/null
+++ b/testcases/kernel/sysfs/devices/system/clockevents/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (c) 2026 Cyril Hrubis <chrubis@suse.cz>
+
+top_srcdir		?= ../../../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/sysfs/devices/system/clockevents/sys_clockevents01.c b/testcases/kernel/sysfs/devices/system/clockevents/sys_clockevents01.c
new file mode 100644
index 000000000..c2cd432f5
--- /dev/null
+++ b/testcases/kernel/sysfs/devices/system/clockevents/sys_clockevents01.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2026 Cyril Hrubis <chrubis@suse.cz>
+ */
+
+/*\
+ * Sanity checks for the per-CPU clock event devices exported under
+ * /sys/devices/system/clockevents/clockeventN/.
+ *
+ * The kernel's tick_init_sysfs() creates one clockeventN directory for every
+ * *possible* CPU (for_each_possible_cpu()), not just the online ones, and N
+ * is the CPU id the directory belongs to (broadcast is a separate, extra
+ * entry used for CPUs whose local timer stops in idle). These directories
+ * are never removed on CPU hotplug, so a clockeventN directory exists
+ * regardless of whether cpuN is currently online.
+ *
+ * However current_device only names a device while the CPU is online:
+ * tick_shutdown(), called while taking a CPU offline, clears the per-CPU
+ * evtdev pointer, which makes current_device_show() emit an empty string.
+ * So current_device is expected to be non-empty only for online CPUs, it is
+ * legitimately empty for offline (or not-present) ones.
+ *
+ * On platforms without a per-CPU timer, secondary CPUs may instead rely
+ * entirely on a broadcast IPI from a single shared timer without ever
+ * getting their own clockeventN entry, so the number of clockeventN
+ * directories is only asserted not to exceed the number of possible CPUs
+ * rather than to match it exactly. The test verifies that:
+ *
+ * - there is at least one clockeventN directory
+ * - the number of clockeventN directories does not exceed the number of
+ *   possible CPUs
+ * - each clockeventN/current_device names a non-empty clock event device
+ *   while cpuN is online, and is not checked while cpuN is offline or not
+ *   present
+ *
+ * The test skips with TCONF when no clockevents directory is present.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include "tst_test.h"
+#include "tst_sysfs_assert.h"
+
+#define CLOCKEVENTS "/sys/devices/system/clockevents"
+#define SYS_CPU "/sys/devices/system/cpu"
+
+static int cpu_is_online(int cpu_id)
+{
+	char online[8];
+
+	/* CPU not present at all, e.g. possible but never plugged in. */
+	if (!tst_sysfs_exists(SYS_CPU "/cpu%d", cpu_id))
+		return 0;
+
+	/*
+	 * Some CPUs, e.g. the boot CPU on some arches, cannot be offlined
+	 * and therefore have no "online" file. Such a CPU is always online.
+	 */
+	if (!TST_SYSFS_READ_STR(online, sizeof(online),
+				SYS_CPU "/cpu%d/online", cpu_id))
+		return 1;
+
+	return atoi(online) == 1;
+}
+
+static void check_clockevent(const char *name)
+{
+	char device[64] = "";
+	int cpu_id, online;
+
+	if (sscanf(name, "clockevent%d", &cpu_id) != 1) {
+		tst_res(TWARN, "Cannot parse CPU id out of '%s'", name);
+		return;
+	}
+
+	online = cpu_is_online(cpu_id);
+
+	TST_SYSFS_READ_STR(device, sizeof(device),
+			   CLOCKEVENTS "/%s/current_device", name);
+
+	if (device[0] != '\0') {
+		tst_res(TPASS, "%s/current_device = '%s'", name, device);
+		return;
+	}
+
+	if (online) {
+		tst_res(TFAIL,
+			"%s/current_device is empty while cpu%d is online",
+			name, cpu_id);
+	} else {
+		tst_res(TPASS,
+			"%s/current_device is empty while cpu%d is offline",
+			name, cpu_id);
+	}
+}
+
+static void do_test(void)
+{
+	DIR *d;
+	struct dirent *ent;
+	int nclockevents = 0;
+	int possible_count, max_id;
+
+	d = SAFE_OPENDIR(CLOCKEVENTS);
+
+	while ((ent = SAFE_READDIR(d))) {
+		if (strncmp(ent->d_name, "clockevent", 10))
+			continue;
+
+		nclockevents++;
+		check_clockevent(ent->d_name);
+	}
+
+	SAFE_CLOSEDIR(d);
+
+	if (!nclockevents) {
+		tst_res(TCONF, "No clockevent directory found");
+		return;
+	}
+
+	if (TST_SYSFS_ASSERT_PARSE_LIST(&possible_count, &max_id,
+					SYS_CPU "/possible"))
+		return;
+
+	if (nclockevents <= possible_count) {
+		tst_res(TPASS,
+			"number of clockevent devices (%d) does not exceed possible CPUs (%d)",
+			nclockevents, possible_count);
+	} else {
+		tst_res(TFAIL,
+			"number of clockevent devices (%d) exceeds possible CPUs (%d)",
+			nclockevents, possible_count);
+	}
+}
+
+static struct tst_test test = {
+	.test_all = do_test,
+};
-- 
2.54.0



More information about the ltp mailing list