selftests/proc: Assert clock_gettime(CLOCK_BOOTTIME) VS /proc/uptime monotonicity
authorFrederic Weisbecker <frederic@kernel.org>
Wed, 22 Feb 2023 14:46:49 +0000 (15:46 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 18 Apr 2023 14:35:13 +0000 (16:35 +0200)
The first field of /proc/uptime relies on the CLOCK_BOOTTIME clock which
can also be fetched from clock_gettime() API.

Improve the test coverage while verifying the monotonicity of
CLOCK_BOOTTIME accross both interfaces.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/r/20230222144649.624380-9-frederic@kernel.org
tools/testing/selftests/proc/proc-uptime-001.c
tools/testing/selftests/proc/proc-uptime-002.c
tools/testing/selftests/proc/proc-uptime.h

index 35bddd9dd60b7b3620c76206dd759a9a2adf2050..f335eec5067e91f7017fca10f311470b51c53fb0 100644 (file)
@@ -13,9 +13,9 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-// Test that boottime value in /proc/uptime increments monotonically.
-// We don't test idle time monotonicity due to broken iowait task
-// counting, cf: comment above get_cpu_idle_time_us()
+// Test that boottime value in /proc/uptime and CLOCK_BOOTTIME increment
+// monotonically. We don't test idle time monotonicity due to broken iowait
+// task counting, cf: comment above get_cpu_idle_time_us()
 #undef NDEBUG
 #include <assert.h>
 #include <stdint.h>
@@ -27,7 +27,7 @@
 
 int main(void)
 {
-       uint64_t start, u0, u1;
+       uint64_t start, u0, u1, c0, c1;
        int fd;
 
        fd = open("/proc/uptime", O_RDONLY);
@@ -35,10 +35,23 @@ int main(void)
 
        u0 = proc_uptime(fd);
        start = u0;
+       c0 = clock_boottime();
+
        do {
                u1 = proc_uptime(fd);
+               c1 = clock_boottime();
+
+               /* Is /proc/uptime monotonic ? */
                assert(u1 >= u0);
+
+               /* Is CLOCK_BOOTTIME monotonic ? */
+               assert(c1 >= c0);
+
+               /* Is CLOCK_BOOTTIME VS /proc/uptime monotonic ? */
+               assert(c0 >= u0);
+
                u0 = u1;
+               c0 = c1;
        } while (u1 - start < 100);
 
        return 0;
index 7ad79d5eaa8440a7fe864ae794081cf1dde0399c..ae453daa96c1911038ccaa6082db6cc7bd7adf63 100644 (file)
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-// Test that boottime value in /proc/uptime increments monotonically
-// while shifting across CPUs. We don't test idle time monotonicity
-// due to broken iowait task counting, cf: comment above get_cpu_idle_time_us()
+// Test that boottime value in /proc/uptime and CLOCK_BOOTTIME increment
+// monotonically while shifting across CPUs. We don't test idle time
+// monotonicity due to broken iowait task counting, cf: comment above
+// get_cpu_idle_time_us()
 #undef NDEBUG
 #include <assert.h>
 #include <errno.h>
@@ -43,10 +44,10 @@ static inline int sys_sched_setaffinity(pid_t pid, unsigned int len, unsigned lo
 
 int main(void)
 {
+       uint64_t u0, u1, c0, c1;
        unsigned int len;
        unsigned long *m;
        unsigned int cpu;
-       uint64_t u0, u1;
        int fd;
 
        /* find out "nr_cpu_ids" */
@@ -62,6 +63,8 @@ int main(void)
        assert(fd >= 0);
 
        u0 = proc_uptime(fd);
+       c0 = clock_boottime();
+
        for (cpu = 0; cpu < len * 8; cpu++) {
                memset(m, 0, len);
                m[cpu / (8 * sizeof(unsigned long))] |= 1UL << (cpu % (8 * sizeof(unsigned long)));
@@ -70,8 +73,19 @@ int main(void)
                sys_sched_setaffinity(0, len, m);
 
                u1 = proc_uptime(fd);
+               c1 = clock_boottime();
+
+               /* Is /proc/uptime monotonic ? */
                assert(u1 >= u0);
+
+               /* Is CLOCK_BOOTTIME monotonic ? */
+               assert(c1 >= c0);
+
+               /* Is CLOCK_BOOTTIME VS /proc/uptime monotonic ? */
+               assert(c0 >= u0);
+
                u0 = u1;
+               c0 = c1;
        }
 
        return 0;
index ca55abeb0cccca752260b508e3132ab47709ba83..730cce4a3d73ec36ee4aec506c2778844bbc0b18 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <time.h>
 
 #include "proc.h"
 
+static uint64_t clock_boottime(void)
+{
+       struct timespec ts;
+       int err;
+
+       err = clock_gettime(CLOCK_BOOTTIME, &ts);
+       assert(err >= 0);
+
+       return (ts.tv_sec * 100) + (ts.tv_nsec / 10000000);
+}
+
 static uint64_t proc_uptime(int fd)
 {
        uint64_t val1, val2;