From fe7fa81da1465acf8e76cfbf6b018e8093333615 Mon Sep 17 00:00:00 2001 From: Arjun Shankar Date: Tue, 1 Jul 2025 18:36:01 +0200 Subject: [PATCH] Add new tests for clock_nanosleep (RHEL-62188) Resolves: RHEL-62188 --- glibc-RHEL-62188-1.patch | 301 +++++++++++++++++++++++++++++++++++++++ glibc-RHEL-62188-2.patch | 18 +++ glibc.spec | 7 +- 3 files changed, 325 insertions(+), 1 deletion(-) create mode 100644 glibc-RHEL-62188-1.patch create mode 100644 glibc-RHEL-62188-2.patch diff --git a/glibc-RHEL-62188-1.patch b/glibc-RHEL-62188-1.patch new file mode 100644 index 0000000..c8bf9ee --- /dev/null +++ b/glibc-RHEL-62188-1.patch @@ -0,0 +1,301 @@ +commit cfb35f5f7f32cec8fa4e16b99e35b7d70fa13f1f +Author: DJ Delorie +Date: Tue Sep 17 22:52:37 2024 -0400 + + rt: more clock_nanosleep tests + + Test that clock_nanosleep rejects out of range time values. + + Test that clock_nanosleep actually sleeps for at least the + requested time relative to the requested clock. + + Reviewed-by: Adhemerval Zanella + +diff --git a/rt/Makefile b/rt/Makefile +index 910e7759956d7ae9..64d2a173e6ea2851 100644 +--- a/rt/Makefile ++++ b/rt/Makefile +@@ -77,6 +77,7 @@ tests := tst-shm tst-timer tst-timer2 \ + tst-bz28213 \ + tst-timer3 tst-timer4 tst-timer5 \ + tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \ ++ tst-clock_nanosleep2 \ + tst-shm-cancel \ + tst-mqueue10 + tests-internal := tst-timer-sigmask +@@ -84,6 +85,7 @@ tests-internal := tst-timer-sigmask + tests-time64 := \ + tst-aio6-time64 \ + tst-cpuclock2-time64 \ ++ tst-clock_nanosleep2-time64 \ + tst-mqueue1-time64 \ + tst-mqueue2-time64 \ + tst-mqueue4-time64 \ +diff --git a/rt/tst-clock_nanosleep2-time64.c b/rt/tst-clock_nanosleep2-time64.c +new file mode 100644 +index 0000000000000000..8deb4201f38b094a +--- /dev/null ++++ b/rt/tst-clock_nanosleep2-time64.c +@@ -0,0 +1 @@ ++#include "tst-clock_nanosleep2.c" +diff --git a/rt/tst-clock_nanosleep2.c b/rt/tst-clock_nanosleep2.c +new file mode 100644 +index 0000000000000000..10c822fd54668531 +--- /dev/null ++++ b/rt/tst-clock_nanosleep2.c +@@ -0,0 +1,255 @@ ++/* Test program for process CPU clocks - invalid inputs, minimum time ++ Copyright (C) 2024 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++/* This test has two primary goals - first, to validate that invalid ++ inputs to clock_nanosleep are caught, and second, to validate that ++ clock_nanosleep sleeps for at least the amount of time requested. ++ It is assumed that the system may sleep for an arbitrary additional ++ amount of time beyond the requested time. */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++/* This is 1 ms per test, we have 10 tests, so this file runs in on ++ the order of 0.01 seconds. */ ++#define TEST_NSEC 1000000 ++ ++/* Nanoseconds per second. */ ++#define NSECMAX 1000000000L ++ ++static pthread_barrier_t barrier; ++ ++/* This function is intended to rack up both user and system time. */ ++static void * ++chew_cpu (void *arg) ++{ ++ pthread_barrier_wait (&barrier); ++ ++ while (1) ++ { ++ static volatile char buf[4096]; ++ for (int i = 0; i < 100; ++i) ++ for (size_t j = 0; j < sizeof buf; ++j) ++ buf[j] = 0xaa; ++ int nullfd = xopen ("/dev/null", O_WRONLY, 0); ++ for (int i = 0; i < 100; ++i) ++ for (size_t j = 0; j < sizeof buf; ++j) ++ buf[j] = 0xbb; ++ xwrite (nullfd, (char *) buf, sizeof buf); ++ close (nullfd); ++ } ++ ++ return NULL; ++} ++ ++static void ++ptime_1 (const char *n, struct timespec t) ++{ ++ /* This is only for debugging failed test cases. */ ++ printf ("%12s: %lld.%09lld\n", n, (long long int) t.tv_sec, ++ (long long int) t.tv_nsec); ++} ++#define ptime(t) ptime_1 (#t, t) ++ ++static void ++test_interval_1 (const char *n_clock, clockid_t t_clock) ++{ ++ struct timespec me_before, me_after, quantum, me_sleep, me_slept; ++ long long int slept, min_slept; ++ ++ /* Arbitrary to ensure our time period is sufficiently bigger than ++ the time step. */ ++ TEST_VERIFY (clock_getres (t_clock, &quantum) == 0); ++ printf("Clock quantum: %lld ns, test time: %lld ns\n", ++ (long long int) quantum.tv_nsec, (long long int) TEST_NSEC); ++ TEST_VERIFY (quantum.tv_nsec <= TEST_NSEC / 10); ++ ++ min_slept = TEST_NSEC; ++ ++ me_sleep = make_timespec (0, min_slept); ++ ++ printf ("test clock %s for %lld.%09lld sec relative\n", ++ n_clock, (long long int) me_sleep.tv_sec, ++ (long long int) me_sleep.tv_nsec); ++ ++ TEST_COMPARE (clock_gettime (t_clock, &me_before), 0); ++ TEST_COMPARE (clock_nanosleep (t_clock, 0, &me_sleep, NULL), 0); ++ TEST_COMPARE (clock_gettime (t_clock, &me_after), 0); ++ ++ me_slept = timespec_sub (me_after, me_before); ++ slept = support_timespec_ns (me_slept); ++ ++ ptime (me_before); ++ ptime (me_after); ++ ptime (me_sleep); ++ ptime (me_slept); ++ printf ("test slept %lld nsec >= asked for %lld ?\n", slept, min_slept); ++ ++ /* This is the important part - verify that the time slept is at ++ least as much as the time requested. */ ++ TEST_VERIFY (slept >= min_slept); ++} ++ ++static void ++test_abs_1 (const char *n_clock, clockid_t t_clock) ++{ ++ struct timespec me_before, me_after, quantum, me_sleep; ++ ++ /* Arbitrary to ensure our time period is sufficiently bigger than ++ the time step. */ ++ TEST_VERIFY (clock_getres (t_clock, &quantum) == 0); ++ printf("Clock quantum: %lld ns, test time: %lld ns\n", ++ (long long int) quantum.tv_nsec, (long long int) TEST_NSEC); ++ TEST_VERIFY (quantum.tv_nsec <= TEST_NSEC / 10); ++ ++ me_sleep = make_timespec (0, TEST_NSEC); ++ ++ printf ("test clock %s for %lld.%09lld sec absolute\n", ++ n_clock, (long long int) me_sleep.tv_sec, ++ (long long int) me_sleep.tv_nsec); ++ ++ TEST_COMPARE (clock_gettime (t_clock, &me_before), 0); ++ me_sleep = timespec_add (me_sleep, me_before); ++ TEST_COMPARE (clock_nanosleep (t_clock, TIMER_ABSTIME, &me_sleep, NULL), 0); ++ TEST_COMPARE (clock_gettime (t_clock, &me_after), 0); ++ ++ ptime (me_before); ++ ptime (me_sleep); ++ ptime (me_after); ++ ++ printf("test slept until %lld.%09lld after requested %lld.%09lld ?\n", ++ (long long int) me_after.tv_sec, (long long int) me_after.tv_nsec, ++ (long long int) me_sleep.tv_sec, (long long int) me_sleep.tv_nsec); ++ ++ /* This is the important part - verify that the time slept is at ++ least as much as the time requested. */ ++ TEST_TIMESPEC_EQUAL_OR_AFTER (me_after, me_sleep); ++} ++ ++static void ++test_invalids_1 (const char *the_clock_name, int the_clock, ++ const char *flags_name, int flags) ++{ ++ struct timespec me_before; ++ ++ /* Note: do not use make_timespec() in case that function tries to ++ normalize the fields. */ ++ ++ printf ("%s: %s: test tv 0, 0\n", the_clock_name, flags_name); ++ me_before.tv_sec = 0; ++ me_before.tv_nsec = 0; ++ TEST_COMPARE (clock_nanosleep (the_clock, 0, &me_before, NULL), 0); ++ ++ printf ("%s: %s: test tv -1, 0\n", the_clock_name, flags_name); ++ me_before.tv_sec = -1; ++ me_before.tv_nsec = 0; ++ TEST_COMPARE (clock_nanosleep (the_clock, 0, &me_before, NULL), EINVAL); ++ ++ printf ("%s: %s: test tv 0, -1\n", the_clock_name, flags_name); ++ me_before.tv_sec = 0; ++ me_before.tv_nsec = -1; ++ TEST_COMPARE (clock_nanosleep (the_clock, 0, &me_before, NULL), EINVAL); ++ ++ printf ("%s: %s: test tv -1, -1\n", the_clock_name, flags_name); ++ me_before.tv_sec = -1; ++ me_before.tv_nsec = -1; ++ TEST_COMPARE (clock_nanosleep (the_clock, 0, &me_before, NULL), EINVAL); ++ ++ printf ("%s: %s: test tv 0, MAX\n", the_clock_name, flags_name); ++ me_before.tv_sec = 0; ++ me_before.tv_nsec = NSECMAX; ++ TEST_COMPARE (clock_nanosleep (the_clock, 0, &me_before, NULL), EINVAL); ++} ++ ++static int ++do_test (void) ++{ ++ pthread_t th; ++ ++ pthread_barrier_init (&barrier, NULL, 2); ++ ++ /* Test for proper error detection. */ ++ ++#define test_invalids(c, f) test_invalids_1 (#c, c, #f, f) ++ test_invalids (CLOCK_REALTIME, 0); ++#ifdef CLOCK_TAI ++ test_invalids (CLOCK_TAI, 0); ++#endif ++ test_invalids (CLOCK_MONOTONIC, 0); ++#ifdef CLOCK_BOOTTIME ++ test_invalids (CLOCK_BOOTTIME, 0); ++#endif ++ test_invalids (CLOCK_PROCESS_CPUTIME_ID, 0); ++ test_invalids (CLOCK_REALTIME, TIMER_ABSTIME); ++#ifdef CLOCK_TAI ++ test_invalids (CLOCK_TAI, TIMER_ABSTIME); ++#endif ++ test_invalids (CLOCK_MONOTONIC, TIMER_ABSTIME); ++#ifdef CLOCK_BOOTTIME ++ test_invalids (CLOCK_BOOTTIME, TIMER_ABSTIME); ++#endif ++ test_invalids (CLOCK_PROCESS_CPUTIME_ID, TIMER_ABSTIME); ++ ++ /* Test for various clocks "working". */ ++ ++#define test_interval(c) test_interval_1 (#c, c) ++ test_interval (CLOCK_REALTIME); ++#ifdef CLOCK_TAI ++ test_interval (CLOCK_TAI); ++#endif ++ test_interval (CLOCK_MONOTONIC); ++#ifdef CLOCK_BOOTTIME ++ test_interval (CLOCK_BOOTTIME); ++#endif ++ ++ th = xpthread_create (NULL, chew_cpu, NULL); ++ xpthread_barrier_wait (&barrier); ++ test_interval (CLOCK_PROCESS_CPUTIME_ID); ++ xpthread_cancel (th); ++ ++#define test_abs(c) test_abs_1 (#c, c) ++ test_abs (CLOCK_REALTIME); ++#ifdef CLOCK_TAI ++ test_abs (CLOCK_TAI); ++#endif ++ test_abs (CLOCK_MONOTONIC); ++#ifdef CLOCK_BOOTTIME ++ test_abs (CLOCK_BOOTTIME); ++#endif ++ ++ th = xpthread_create (NULL, chew_cpu, NULL); ++ xpthread_barrier_wait (&barrier); ++ test_abs (CLOCK_PROCESS_CPUTIME_ID); ++ xpthread_cancel (th); ++ ++ return 0; ++} ++ ++#include diff --git a/glibc-RHEL-62188-2.patch b/glibc-RHEL-62188-2.patch new file mode 100644 index 0000000..813c7ff --- /dev/null +++ b/glibc-RHEL-62188-2.patch @@ -0,0 +1,18 @@ +commit 1895a35e7092713b224166d36b9bc26e8eb3371f +Author: DJ Delorie +Date: Tue Oct 8 14:30:21 2024 -0400 + + rt: more clock_nanosleep tests addendum + + Forgot to change the first-line description. + +diff --git a/rt/tst-clock_nanosleep2.c b/rt/tst-clock_nanosleep2.c +index 10c822fd54668531..e9b2a2716d6e9016 100644 +--- a/rt/tst-clock_nanosleep2.c ++++ b/rt/tst-clock_nanosleep2.c +@@ -1,4 +1,4 @@ +-/* Test program for process CPU clocks - invalid inputs, minimum time ++/* Test for clock_nanosleep parameter checks and sleep duration. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + diff --git a/glibc.spec b/glibc.spec index 5316d42..996c92c 100644 --- a/glibc.spec +++ b/glibc.spec @@ -157,7 +157,7 @@ end \ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 209%{?dist} +Release: 210%{?dist} # In general, GPLv2+ is used by programs, LGPLv2+ is used for # libraries. @@ -1254,6 +1254,8 @@ Patch945: glibc-RHEL-48820-6.patch Patch946: glibc-RHEL-48820-7.patch Patch947: glibc-RHEL-53909-1.patch Patch948: glibc-RHEL-53909-2.patch +Patch949: glibc-RHEL-62188-1.patch +Patch950: glibc-RHEL-62188-2.patch ############################################################################## # Continued list of core "glibc" package information: @@ -3251,6 +3253,9 @@ update_gconv_modules_cache () %endif %changelog +* Tue Jul 01 2025 Arjun Shankar - 2.34-210 +- Add new tests for clock_nanosleep (RHEL-62188) + * Tue Jul 01 2025 Arjun Shankar - 2.34-209 - Add new test for if_nameindex and if_indextoname (RHEL-53909)