diff options
Diffstat (limited to 'time')
-rw-r--r-- | time/Makefile | 8 | ||||
-rw-r--r-- | time/Versions | 13 | ||||
-rw-r--r-- | time/clock_getcpuclockid.c | 47 | ||||
-rw-r--r-- | time/clock_getres.c | 39 | ||||
-rw-r--r-- | time/clock_gettime.c | 40 | ||||
-rw-r--r-- | time/clock_nanosleep.c | 46 | ||||
-rw-r--r-- | time/clock_settime.c | 40 | ||||
-rw-r--r-- | time/tst-clock.c | 121 | ||||
-rw-r--r-- | time/tst-clock2.c | 43 | ||||
-rw-r--r-- | time/tst-clock_nanosleep.c | 57 | ||||
-rw-r--r-- | time/tst-cpuclock1.c | 320 |
11 files changed, 772 insertions, 2 deletions
diff --git a/time/Makefile b/time/Makefile index a428f55245..85a62c0376 100644 --- a/time/Makefile +++ b/time/Makefile @@ -36,14 +36,18 @@ routines := offtime asctime clock ctime ctime_r difftime \ stime dysize timegm ftime \ getdate strptime strptime_l \ strftime wcsftime strftime_l wcsftime_l \ - timespec_get + timespec_get \ + clock_getcpuclockid clock_getres \ + clock_gettime clock_settime clock_nanosleep + aux := era alt_digit lc-time-cleanup tests := test_time clocktest tst-posixtz tst-strptime tst_wcsftime \ tst-getdate tst-mktime tst-mktime2 tst-ftime_l tst-strftime \ tst-mktime3 tst-strptime2 bug-asctime bug-asctime_r bug-mktime1 \ tst-strptime3 bug-getdate1 tst-strptime-whitespace tst-ftime \ - tst-tzname tst-y2039 bug-mktime4 tst-strftime2 tst-strftime3 + tst-tzname tst-y2039 bug-mktime4 tst-strftime2 tst-strftime3 \ + tst-clock tst-clock2 tst-clock_nanosleep tst-cpuclock1 include ../Rules diff --git a/time/Versions b/time/Versions index fd838181e4..8788e192ce 100644 --- a/time/Versions +++ b/time/Versions @@ -49,6 +49,10 @@ libc { GLIBC_2.2 { # w* wcsftime; + + # c*; actually in librt in version 2.2, moved to libc in 2.17 + clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; + clock_nanosleep; } GLIBC_2.3 { # these internal names are used by libstdc++ @@ -65,4 +69,13 @@ libc { GLIBC_2.16 { timespec_get; } + GLIBC_2.17 { + # c* + clock_getres; clock_gettime; clock_settime; clock_getcpuclockid; + clock_nanosleep; + } + GLIBC_PRIVATE { + # same as clock_gettime; used in other libraries + __clock_gettime; + } } diff --git a/time/clock_getcpuclockid.c b/time/clock_getcpuclockid.c new file mode 100644 index 0000000000..8d205abfa9 --- /dev/null +++ b/time/clock_getcpuclockid.c @@ -0,0 +1,47 @@ +/* Get a clockid_t for the process CPU clock of a given process. Generic. + Copyright (C) 2000-2019 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <time.h> +#include <unistd.h> +#include <shlib-compat.h> + +int +__clock_getcpuclockid (pid_t pid, clockid_t *clock_id) +{ + /* We don't allow any process ID but our own. */ + if (pid != 0 && pid != getpid ()) + return EPERM; + +#ifdef CLOCK_PROCESS_CPUTIME_ID + /* Store the number. */ + *clock_id = CLOCK_PROCESS_CPUTIME_ID; + + return 0; +#else + /* We don't have a timer for that. */ + return ENOENT; +#endif +} +versioned_symbol (libc, __clock_getcpuclockid, clock_getcpuclockid, GLIBC_2_17); +/* clock_getcpuclockid moved to libc in version 2.17; + old binaries may expect the symbol version it had in librt. */ +#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) +strong_alias (__clock_getcpuclockid, __clock_getcpuclockid_2); +compat_symbol (libc, __clock_getcpuclockid_2, clock_getcpuclockid, GLIBC_2_2); +#endif diff --git a/time/clock_getres.c b/time/clock_getres.c new file mode 100644 index 0000000000..412f80fbec --- /dev/null +++ b/time/clock_getres.c @@ -0,0 +1,39 @@ +/* Get the resolution of a clock. Stub version. + Copyright (C) 1999-2019 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <time.h> +#include <shlib-compat.h> + +/* Get resolution of clock. */ +int +__clock_getres (clockid_t clock_id, struct timespec *res) +{ + __set_errno (ENOSYS); + return -1; +} + +versioned_symbol (libc, __clock_getres, clock_getres, GLIBC_2_17); +/* clock_getres moved to libc in version 2.17; + old binaries may expect the symbol version it had in librt. */ +#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) +strong_alias (__clock_getres, __clock_getres_2); +compat_symbol (libc, __clock_getres_2, clock_getres, GLIBC_2_2); +#endif + +stub_warning (clock_getres) diff --git a/time/clock_gettime.c b/time/clock_gettime.c new file mode 100644 index 0000000000..92c6081dcb --- /dev/null +++ b/time/clock_gettime.c @@ -0,0 +1,40 @@ +/* Get the current value of a clock. Stub version. + Copyright (C) 1999-2019 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <time.h> +#include <shlib-compat.h> + +/* Get current value of CLOCK and store it in TP. */ +int +__clock_gettime (clockid_t clock_id, struct timespec *tp) +{ + __set_errno (ENOSYS); + return -1; +} +libc_hidden_def (__clock_gettime) + +versioned_symbol (libc, __clock_gettime, clock_gettime, GLIBC_2_17); +/* clock_gettime moved to libc in version 2.17; + old binaries may expect the symbol version it had in librt. */ +#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) +strong_alias (__clock_gettime, __clock_gettime_2); +compat_symbol (libc, __clock_gettime_2, clock_gettime, GLIBC_2_2); +#endif + +stub_warning (clock_gettime) diff --git a/time/clock_nanosleep.c b/time/clock_nanosleep.c new file mode 100644 index 0000000000..c53c820880 --- /dev/null +++ b/time/clock_nanosleep.c @@ -0,0 +1,46 @@ +/* High-resolution sleep with the specified clock. Stub version. + Copyright (C) 2000-2019 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <time.h> +#include <shlib-compat.h> + +int +__clock_nanosleep (clockid_t clock_id, int flags, const struct timespec *req, + struct timespec *rem) +{ + if (__builtin_expect (req->tv_nsec, 0) < 0 + || __builtin_expect (req->tv_nsec, 0) >= 1000000000) + return EINVAL; + + if (flags != TIMER_ABSTIME && flags != 0) + return EINVAL; + + /* Not implemented. */ + return ENOSYS; +} + +versioned_symbol (libc, __clock_nanosleep, clock_nanosleep, GLIBC_2_17); +/* clock_nanosleep moved to libc in version 2.17; + old binaries may expect the symbol version it had in librt. */ +#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) +strong_alias (__clock_nanosleep, __clock_nanosleep_2); +compat_symbol (libc, __clock_nanosleep_2, clock_nanosleep, GLIBC_2_2); +#endif + +stub_warning (clock_nanosleep) diff --git a/time/clock_settime.c b/time/clock_settime.c new file mode 100644 index 0000000000..dd86a1c189 --- /dev/null +++ b/time/clock_settime.c @@ -0,0 +1,40 @@ +/* Set a clock to a given value. Stub version. + Copyright (C) 1999-2019 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <time.h> +#include <shlib-compat.h> + +/* Set CLOCK to value TP. */ +int +__clock_settime (clockid_t clock_id, const struct timespec *tp) +{ + __set_errno (ENOSYS); + return -1; +} +libc_hidden_def (__clock_settime) + +versioned_symbol (libc, __clock_settime, clock_settime, GLIBC_2_17); +/* clock_settime moved to libc in version 2.17; + old binaries may expect the symbol version it had in librt. */ +#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_17) +strong_alias (__clock_settime, __clock_settime_2); +compat_symbol (libc, __clock_settime_2, clock_settime, GLIBC_2_2); +#endif + +stub_warning (clock_settime) diff --git a/time/tst-clock.c b/time/tst-clock.c new file mode 100644 index 0000000000..2e19bb1a43 --- /dev/null +++ b/time/tst-clock.c @@ -0,0 +1,121 @@ +/* Test program for POSIX clock_* functions. + Copyright (C) 2000-2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. + + 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 + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <stdint.h> + + +/* We want to see output immediately. */ +#define STDOUT_UNBUFFERED + +static int +clock_test (clockid_t cl) +{ + struct timespec old_ts; + struct timespec ts; + struct timespec waitit; + int result = 0; + int i; + + memset (&ts, '\0', sizeof ts); + + waitit.tv_sec = 0; + waitit.tv_nsec = 500000000; + + /* Get and print resolution of the clock. */ + if (clock_getres (cl, &ts) == 0) + { + if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000) + { + printf ("clock %d: nanosecond value of resolution wrong\n", cl); + result = 1; + } + else + printf ("clock %d: resolution = %jd.%09jd secs\n", + cl, (intmax_t) ts.tv_sec, (intmax_t) ts.tv_nsec); + } + else + { + printf ("clock %d: cannot get resolution\n", cl); + result = 1; + } + + memset (&ts, '\0', sizeof ts); + memset (&old_ts, '\0', sizeof old_ts); + + /* Next get the current time value a few times. */ + for (i = 0; i < 10; ++i) + { + if (clock_gettime (cl, &ts) == 0) + { + if (ts.tv_nsec < 0 || ts.tv_nsec >= 1000000000) + { + printf ("clock %d: nanosecond value of time wrong (try %d)\n", + cl, i); + result = 1; + } + else + { + printf ("clock %d: time = %jd.%09jd secs\n", + cl, (intmax_t) ts.tv_sec, (intmax_t) ts.tv_nsec); + + if (memcmp (&ts, &old_ts, sizeof ts) == 0) + { + printf ("clock %d: time hasn't changed (try %d)\n", cl, i); + result = 1; + + old_ts = ts; + } + } + } + else + { + printf ("clock %d: cannot get time (try %d)\n", cl, i); + result = 1; + } + + /* Wait a bit before the next iteration. */ + nanosleep (&waitit, NULL); + } + + return result; +} + +static int +do_test (void) +{ + clockid_t cl; + int result; + + result = clock_test (CLOCK_REALTIME); + + if (clock_getcpuclockid (0, &cl) == 0) + /* XXX It's not yet a bug when this fails. */ + clock_test (cl); + else + printf("CPU clock unavailble, skipping test\n"); + + return result; +} +#define TEST_FUNCTION do_test () + + +#include "../test-skeleton.c" diff --git a/time/tst-clock2.c b/time/tst-clock2.c new file mode 100644 index 0000000000..4c8fb9f247 --- /dev/null +++ b/time/tst-clock2.c @@ -0,0 +1,43 @@ +/* Test setting the monotonic clock. */ + +#include <time.h> +#include <unistd.h> + +#if defined CLOCK_MONOTONIC && defined _POSIX_MONOTONIC_CLOCK + +# include <errno.h> +# include <stdio.h> + +static int +do_test (void) +{ + if (sysconf (_SC_MONOTONIC_CLOCK) <= 0) + return 0; + + struct timespec ts; + if (clock_gettime (CLOCK_MONOTONIC, &ts) != 0) + { + puts ("clock_gettime(CLOCK_MONOTONIC) failed"); + return 1; + } + + /* Setting the monotonic clock must fail. */ + if (clock_settime (CLOCK_MONOTONIC, &ts) != -1) + { + puts ("clock_settime(CLOCK_MONOTONIC) did not fail"); + return 1; + } + if (errno != EINVAL) + { + printf ("clock_settime(CLOCK_MONOTONIC) set errno to %d, expected %d\n", + errno, EINVAL); + return 1; + } + return 0; +} +# define TEST_FUNCTION do_test () + +#else +# define TEST_FUNCTION 0 +#endif +#include "../test-skeleton.c" diff --git a/time/tst-clock_nanosleep.c b/time/tst-clock_nanosleep.c new file mode 100644 index 0000000000..f5df327e2f --- /dev/null +++ b/time/tst-clock_nanosleep.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2003-2019 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 + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <sys/time.h> +#include <time.h> + + +/* Test that clock_nanosleep() does sleep. */ +static int +do_test (void) +{ + /* Current time. */ + struct timeval tv1; + (void) gettimeofday (&tv1, NULL); + + struct timespec ts; + ts.tv_sec = 1; + ts.tv_nsec = 0; + TEMP_FAILURE_RETRY (clock_nanosleep (CLOCK_REALTIME, 0, &ts, &ts)); + + /* At least one second must have passed. */ + struct timeval tv2; + (void) gettimeofday (&tv2, NULL); + + tv2.tv_sec -= tv1.tv_sec; + tv2.tv_usec -= tv1.tv_usec; + if (tv2.tv_usec < 0) + --tv2.tv_sec; + + if (tv2.tv_sec < 1) + { + puts ("clock_nanosleep didn't sleep long enough"); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/time/tst-cpuclock1.c b/time/tst-cpuclock1.c new file mode 100644 index 0000000000..e3f23aa307 --- /dev/null +++ b/time/tst-cpuclock1.c @@ -0,0 +1,320 @@ +/* Test program for process CPU clocks. + Copyright (C) 2004-2019 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 + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <signal.h> +#include <stdint.h> +#include <sys/wait.h> + +/* This function is intended to rack up both user and system time. */ +static void +chew_cpu (void) +{ + 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 = open ("/dev/null", O_WRONLY); + for (int i = 0; i < 100; ++i) + for (size_t j = 0; j < sizeof buf; ++j) + buf[j] = 0xbb; + write (nullfd, (char *) buf, sizeof buf); + close (nullfd); + if (getppid () == 1) + _exit (2); + } +} + +static int +do_test (void) +{ + int result = 0; + clockid_t cl; + int e; + pid_t dead_child, child; + + /* Fork a child and let it die, to give us a PID known not be valid + (assuming PIDs don't wrap around during the test). */ + { + dead_child = fork (); + if (dead_child == 0) + _exit (0); + if (dead_child < 0) + { + perror ("fork"); + return 1; + } + int x; + if (wait (&x) != dead_child) + { + perror ("wait"); + return 2; + } + } + + /* POSIX says we should get ESRCH for this. */ + e = clock_getcpuclockid (dead_child, &cl); + if (e != ENOSYS && e != ESRCH && e != EPERM) + { + printf ("clock_getcpuclockid on dead PID %d => %s\n", + dead_child, strerror (e)); + result = 1; + } + + /* Now give us a live child eating up CPU time. */ + child = fork (); + if (child == 0) + { + chew_cpu (); + _exit (1); + } + if (child < 0) + { + perror ("fork"); + return 1; + } + + e = clock_getcpuclockid (child, &cl); + if (e == EPERM) + { + puts ("clock_getcpuclockid does not support other processes"); + goto done; + } + if (e != 0) + { + printf ("clock_getcpuclockid on live PID %d => %s\n", + child, strerror (e)); + result = 1; + goto done; + } + + const clockid_t child_clock = cl; + struct timespec res; + if (clock_getres (child_clock, &res) < 0) + { + printf ("clock_getres on live PID %d clock %lx => %s\n", + child, (unsigned long int) child_clock, strerror (errno)); + result = 1; + goto done; + } + printf ("live PID %d clock %lx resolution %ju.%.9ju\n", + child, (unsigned long int) child_clock, + (uintmax_t) res.tv_sec, (uintmax_t) res.tv_nsec); + + struct timespec before, after; + if (clock_gettime (child_clock, &before) < 0) + { + printf ("clock_gettime on live PID %d clock %lx => %s\n", + child, (unsigned long int) child_clock, strerror (errno)); + result = 1; + goto done; + } + /* Should be close to 0.0. */ + printf ("live PID %d before sleep => %ju.%.9ju\n", + child, (uintmax_t) before.tv_sec, (uintmax_t) before.tv_nsec); + + struct timespec sleeptime = { .tv_nsec = 500000000 }; + if (nanosleep (&sleeptime, NULL) != 0) + { + perror ("nanosleep"); + result = 1; + goto done; + } + + if (clock_gettime (child_clock, &after) < 0) + { + printf ("clock_gettime on live PID %d clock %lx => %s\n", + child, (unsigned long int) child_clock, strerror (errno)); + result = 1; + goto done; + } + /* Should be close to 0.5. */ + printf ("live PID %d after sleep => %ju.%.9ju\n", + child, (uintmax_t) after.tv_sec, (uintmax_t) after.tv_nsec); + + struct timespec diff = { .tv_sec = after.tv_sec - before.tv_sec, + .tv_nsec = after.tv_nsec - before.tv_nsec }; + if (diff.tv_nsec < 0) + { + --diff.tv_sec; + diff.tv_nsec += 1000000000; + } + if (diff.tv_sec != 0 + || diff.tv_nsec > 600000000 + || diff.tv_nsec < 100000000) + { + printf ("before - after %ju.%.9ju outside reasonable range\n", + (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec); + result = 1; + } + + sleeptime.tv_nsec = 100000000; + e = clock_nanosleep (child_clock, 0, &sleeptime, NULL); + if (e == EINVAL || e == ENOTSUP || e == ENOSYS) + { + printf ("clock_nanosleep not supported for other process clock: %s\n", + strerror (e)); + } + else if (e != 0) + { + printf ("clock_nanosleep on other process clock: %s\n", strerror (e)); + result = 1; + } + else + { + struct timespec afterns; + if (clock_gettime (child_clock, &afterns) < 0) + { + printf ("clock_gettime on live PID %d clock %lx => %s\n", + child, (unsigned long int) child_clock, strerror (errno)); + result = 1; + } + else + { + struct timespec d = { .tv_sec = afterns.tv_sec - after.tv_sec, + .tv_nsec = afterns.tv_nsec - after.tv_nsec }; + if (d.tv_nsec < 0) + { + --d.tv_sec; + d.tv_nsec += 1000000000; + } + if (d.tv_sec > 0 + || d.tv_nsec < sleeptime.tv_nsec + || d.tv_nsec > sleeptime.tv_nsec * 2) + { + printf ("nanosleep time %ju.%.9ju outside reasonable range\n", + (uintmax_t) d.tv_sec, (uintmax_t) d.tv_nsec); + result = 1; + } + } + } + + if (kill (child, SIGKILL) != 0) + { + perror ("kill"); + result = 2; + goto done; + } + + /* Wait long enough to let the child finish dying. */ + + sleeptime.tv_nsec = 200000000; + if (nanosleep (&sleeptime, NULL) != 0) + { + perror ("nanosleep"); + result = 1; + goto done; + } + + struct timespec dead; + if (clock_gettime (child_clock, &dead) < 0) + { + printf ("clock_gettime on dead PID %d clock %lx => %s\n", + child, (unsigned long int) child_clock, strerror (errno)); + result = 1; + goto done; + } + /* Should be close to 0.6. */ + printf ("dead PID %d => %ju.%.9ju\n", + child, (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec); + + diff.tv_sec = dead.tv_sec - after.tv_sec; + diff.tv_nsec = dead.tv_nsec - after.tv_nsec; + if (diff.tv_nsec < 0) + { + --diff.tv_sec; + diff.tv_nsec += 1000000000; + } + if (diff.tv_sec != 0 || diff.tv_nsec > 200000000) + { + printf ("dead - after %ju.%.9ju outside reasonable range\n", + (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec); + result = 1; + } + + /* Now reap the child and verify that its clock is no longer valid. */ + { + int x; + if (waitpid (child, &x, 0) != child) + { + perror ("waitpid"); + result = 1; + } + } + + if (clock_gettime (child_clock, &dead) == 0) + { + printf ("clock_gettime on reaped PID %d clock %lx => %ju%.9ju\n", + child, (unsigned long int) child_clock, + (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec); + result = 1; + } + else + { + if (errno != EINVAL) + result = 1; + printf ("clock_gettime on reaped PID %d clock %lx => %s\n", + child, (unsigned long int) child_clock, strerror (errno)); + } + + if (clock_getres (child_clock, &dead) == 0) + { + printf ("clock_getres on reaped PID %d clock %lx => %ju%.9ju\n", + child, (unsigned long int) child_clock, + (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec); + result = 1; + } + else + { + if (errno != EINVAL) + result = 1; + printf ("clock_getres on reaped PID %d clock %lx => %s\n", + child, (unsigned long int) child_clock, strerror (errno)); + } + + return result; + + done: + { + if (kill (child, SIGKILL) != 0 && errno != ESRCH) + { + perror ("kill"); + return 2; + } + int x; + if (waitpid (child, &x, 0) != child && errno != ECHILD) + { + perror ("waitpid"); + return 2; + } + } + + return result; +} + + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" |