mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 12:30:06 +00:00
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 <adhemerval.zanella@linaro.org>
This commit is contained in:
parent
d40ac01cbb
commit
cfb35f5f7f
@ -77,6 +77,7 @@ tests := tst-shm tst-timer tst-timer2 \
|
|||||||
tst-bz28213 \
|
tst-bz28213 \
|
||||||
tst-timer3 tst-timer4 tst-timer5 \
|
tst-timer3 tst-timer4 tst-timer5 \
|
||||||
tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \
|
tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \
|
||||||
|
tst-clock_nanosleep2 \
|
||||||
tst-shm-cancel \
|
tst-shm-cancel \
|
||||||
tst-mqueue10
|
tst-mqueue10
|
||||||
tests-internal := tst-timer-sigmask
|
tests-internal := tst-timer-sigmask
|
||||||
@ -84,6 +85,7 @@ tests-internal := tst-timer-sigmask
|
|||||||
tests-time64 := \
|
tests-time64 := \
|
||||||
tst-aio6-time64 \
|
tst-aio6-time64 \
|
||||||
tst-cpuclock2-time64 \
|
tst-cpuclock2-time64 \
|
||||||
|
tst-clock_nanosleep2-time64 \
|
||||||
tst-mqueue1-time64 \
|
tst-mqueue1-time64 \
|
||||||
tst-mqueue2-time64 \
|
tst-mqueue2-time64 \
|
||||||
tst-mqueue4-time64 \
|
tst-mqueue4-time64 \
|
||||||
|
1
rt/tst-clock_nanosleep2-time64.c
Normal file
1
rt/tst-clock_nanosleep2-time64.c
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "tst-clock_nanosleep2.c"
|
255
rt/tst-clock_nanosleep2.c
Normal file
255
rt/tst-clock_nanosleep2.c
Normal file
@ -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
|
||||||
|
<https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* 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 <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <support/xunistd.h>
|
||||||
|
#include <support/check.h>
|
||||||
|
#include <support/xthread.h>
|
||||||
|
#include <support/timespec.h>
|
||||||
|
|
||||||
|
/* 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 <support/test-driver.c>
|
Loading…
Reference in New Issue
Block a user