diff --git a/support/Makefile b/support/Makefile
index a0304e6def..1e45d99b27 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -31,6 +31,7 @@ libsupport-routines = \
check_dns_packet \
check_hostent \
check_netent \
+ support_cpuclock \
delayed_exit \
ignore_stderr \
next_to_fault \
diff --git a/support/support_cpuclock.c b/support/support_cpuclock.c
new file mode 100644
index 0000000000..cd5212bc32
--- /dev/null
+++ b/support/support_cpuclock.c
@@ -0,0 +1,58 @@
+/* Support functions for cpuclock tests.
+ Copyright (C) 2020 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
+ . */
+
+#include "support_cpuclock.h"
+#include
+#include
+
+#define TIMESPEC_HZ 1000000000.0
+
+/* Returns t normalized timespec with .tv_nsec < TIMESPEC_HZ
+ and the overflows added to .tv_sec. */
+struct timespec
+support_timespec_normalize (struct timespec t)
+{
+ int diff;
+ diff = (t.tv_nsec / TIMESPEC_HZ);
+ t.tv_sec += diff;
+ t.tv_nsec += -(diff * TIMESPEC_HZ);
+ return t;
+}
+
+/* Returns TRUE if diff to base ratio is within the specified bounds, and
+FALSE otherwise.
+For example the call
+
+support_timespec_check_ratio(base, diff, 1.2, .5);
+
+will check if
+
+.5 <= diff/base <= 1.2
+
+In other words it will check if diff time is within 50% to 120% of
+the base time. */
+int
+support_timespec_check_ratio (struct timespec base, struct timespec diff,
+ double upper_bound, double lower_bound)
+{
+ assert (upper_bound >= lower_bound);
+ double base_norm = base.tv_sec + base.tv_nsec / TIMESPEC_HZ;
+ double diff_norm = diff.tv_sec + diff.tv_nsec / TIMESPEC_HZ;
+ double ratio = diff_norm / base_norm;
+ return (ratio <= upper_bound && ratio >= lower_bound);
+}
diff --git a/support/support_cpuclock.h b/support/support_cpuclock.h
new file mode 100644
index 0000000000..a14bc91e3f
--- /dev/null
+++ b/support/support_cpuclock.h
@@ -0,0 +1,28 @@
+/* Support functions for cpuclock tests.
+ Copyright (C) 2020 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
+ . */
+
+#ifndef SUPPORT_CPUCLOCK_H
+#define SUPPORT_CPUCLOCK_H
+
+#include
+
+struct timespec support_timespec_normalize (struct timespec t);
+int support_timespec_check_ratio (struct timespec base, struct timespec diff,
+ double upper_bound, double lower_bound);
+
+#endif /* SUPPORT_CPUCLOCK_H */
diff --git a/time/tst-cpuclock1.c b/time/tst-cpuclock1.c
index 0120906f23..72450f71ee 100644
--- a/time/tst-cpuclock1.c
+++ b/time/tst-cpuclock1.c
@@ -26,6 +26,8 @@
#include
#include
#include
+#include
+#include
/* This function is intended to rack up both user and system time. */
static void
@@ -155,19 +157,13 @@ do_test (void)
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)
+ support_timespec_normalize(after);
+ support_timespec_normalize(before);
+ struct timespec diff = timespec_sub(after, before);
+ if (!support_timespec_check_ratio(sleeptime, diff, 1.3, .0025))
{
printf ("before - after %ju.%.9ju outside reasonable range\n",
- (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
+ (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
result = 1;
}
@@ -194,19 +190,12 @@ do_test (void)
}
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)
+ support_timespec_normalize(afterns);
+ diff = timespec_sub(afterns, after);
+ if (!support_timespec_check_ratio(sleeptime, diff, 1.6, .71))
{
printf ("nanosleep time %ju.%.9ju outside reasonable range\n",
- (uintmax_t) d.tv_sec, (uintmax_t) d.tv_nsec);
+ (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
result = 1;
}
}
@@ -241,17 +230,13 @@ do_test (void)
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)
+ support_timespec_normalize(dead);
+ diff = timespec_sub(dead, after);
+ sleeptime.tv_nsec = 100000000;
+ if (!support_timespec_check_ratio(sleeptime, diff, 1.6, .7))
{
printf ("dead - after %ju.%.9ju outside reasonable range\n",
- (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
+ (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
result = 1;
}