[PATCH v9] Fix time/tst-cpuclock1 intermitent failures
Lucas A. M. Magalhaes
lamm@linux.ibm.com
Mon May 25 11:46:50 GMT 2020
PING
Quoting Lucas A. M. Magalhaes (2020-05-11 14:41:40)
> PING.
>
> Quoting Lucas A. M. Magalhaes via Libc-alpha (2020-04-21 14:44:56)
> > This test fails intermittently in systems with heavy load as
> > CLOCK_PROCESS_CPUTIME_ID is subject to scheduler pressure. Thus the
> > test boundaries were relaxed to keep it from failing on such systems.
> >
> > A refactor of the spent time checking was made with some support
> > functions. With the advantage to representing time jitter in percent
> > of the target.
> >
> > The values used by the test boundaries are all empirical.
> >
> > ---
> >
> > Hi Carlos,
> > I also got skeptical about my dataset so I genegerated another one.
> > That .4 boundry was indeed too low. Also, the support/tst-timespec was
> > not actually running any tests because of a lazy bug, sorry about that.
> > Thanks for taking the time for reviewing this.
> >
> > changes on V9:
> > Add new testcases
> > Fix support/tst-timespec do_run
> > Add comments
> > Change boundaries
> >
> > changes on V8:
> > Add support_timespec_ns
> > Add more tests
> >
> > This list of changes where getting to long.
> > ---
> > support/Makefile | 1 +
> > support/timespec.c | 64 +++++++++
> > support/timespec.h | 8 ++
> > support/tst-timespec.c | 320 +++++++++++++++++++++++++++++++++++++++++
> > time/tst-cpuclock1.c | 52 +++----
> > 5 files changed, 415 insertions(+), 30 deletions(-)
> > create mode 100644 support/tst-timespec.c
> >
> > diff --git a/support/Makefile b/support/Makefile
> > index 6e38b87ebe..cacaac96a5 100644
> > --- a/support/Makefile
> > +++ b/support/Makefile
> > @@ -233,6 +233,7 @@ tests = \
> > tst-test_compare \
> > tst-test_compare_blob \
> > tst-test_compare_string \
> > + tst-timespec \
> > tst-xreadlink \
> > tst-xsigstack \
> >
> > diff --git a/support/timespec.c b/support/timespec.c
> > index ea6b947546..103beafdc4 100644
> > --- a/support/timespec.c
> > +++ b/support/timespec.c
> > @@ -19,6 +19,8 @@
> > #include <support/timespec.h>
> > #include <stdio.h>
> > #include <stdint.h>
> > +#include <assert.h>
> > +#include <intprops.h>
> >
> > void
> > test_timespec_before_impl (const char *file, int line,
> > @@ -57,3 +59,65 @@ test_timespec_equal_or_after_impl (const char *file, int line,
> > (intmax_t) diff.tv_sec, (intmax_t) diff.tv_nsec);
> > }
> > }
> > +
> > +/* Convert TIME to nanoseconds stored in shrinked in a long.
> > + Returns long maximum or minimum if the conversion overflows
> > + or underflows, respectively. */
> > +long
> > +support_timespec_ns (struct timespec time)
> > +{
> > + long time_ns;
> > + if (INT_MULTIPLY_WRAPV(time.tv_sec, TIMESPEC_HZ, &time_ns))
> > + {
> > + return (time.tv_sec < 0) ? TYPE_MINIMUM(long): TYPE_MAXIMUM(long);
> > + }
> > + if (INT_ADD_WRAPV(time_ns, time.tv_nsec, &time_ns))
> > + {
> > + return (time.tv_nsec < 0) ? TYPE_MINIMUM(long): TYPE_MAXIMUM(long);
> > + }
> > + return time_ns;
> > +}
> > +
> > +/* Returns t normalized timespec with .tv_nsec < TIMESPEC_HZ
> > + and the whole seconds added to .tv_sec. If an overflow or
> > + underflow occurs the values are clamped to its maximum or
> > + minimum respectively. */
> > +struct timespec
> > +support_timespec_normalize (struct timespec time)
> > +{
> > + struct timespec norm;
> > + if (INT_ADD_WRAPV (time.tv_sec, (time.tv_nsec / TIMESPEC_HZ), &norm.tv_sec))
> > + {
> > + norm.tv_sec = (time.tv_nsec < 0) ? TYPE_MINIMUM (time_t): TYPE_MAXIMUM (time_t);
> > + norm.tv_nsec = (time.tv_nsec < 0) ? -1 * (TIMESPEC_HZ - 1) : TIMESPEC_HZ - 1;
> > + return norm;
> > + }
> > + norm.tv_nsec = time.tv_nsec % TIMESPEC_HZ;
> > + return norm;
> > +}
> > +
> > +/* Returns TRUE if the observed time is within the given percentage
> > + bounds of the expected time, and FALSE otherwise.
> > + For example the call
> > +
> > + support_timespec_check_in_range(expected, observed, .5, 1.2);
> > +
> > + will check if
> > +
> > + .5 <= observed/expected <= 1.2
> > +
> > + In other words it will check if observed time is within 50% to
> > + 120% of the expected time. */
> > +int
> > +support_timespec_check_in_range (struct timespec expected, struct timespec observed,
> > + double lower_bound, double upper_bound)
> > +{
> > + assert (upper_bound >= lower_bound);
> > + long expected_norm, observed_norm;
> > + expected_norm = support_timespec_ns (expected);
> > + /* Don't divide by zero */
> > + assert(expected_norm != 0);
> > + observed_norm = support_timespec_ns (observed);
> > + double ratio = (double)observed_norm / expected_norm;
> > + return (lower_bound <= ratio && ratio <= upper_bound);
> > +}
> > diff --git a/support/timespec.h b/support/timespec.h
> > index c5852dfe75..fd5466745d 100644
> > --- a/support/timespec.h
> > +++ b/support/timespec.h
> > @@ -48,6 +48,14 @@ void test_timespec_equal_or_after_impl (const char *file, int line,
> > const struct timespec left,
> > const struct timespec right);
> >
> > +long support_timespec_ns (struct timespec time);
> > +
> > +struct timespec support_timespec_normalize (struct timespec time);
> > +
> > +int support_timespec_check_in_range (struct timespec expected, struct timespec observed,
> > + double lower_bound, double upper_bound);
> > +
> > +
> > /* Check that the timespec on the left represents a time before the
> > time on the right. */
> > #define TEST_TIMESPEC_BEFORE(left, right) \
> > diff --git a/support/tst-timespec.c b/support/tst-timespec.c
> > new file mode 100644
> > index 0000000000..b421b219fd
> > --- /dev/null
> > +++ b/support/tst-timespec.c
> > @@ -0,0 +1,320 @@
> > +/* Test for support_timespec_check_in_range function.
> > + 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
> > + <https://www.gnu.org/licenses/>. */
> > +
> > +#include <support/timespec.h>
> > +#include <support/check.h>
> > +#include <limits.h>
> > +
> > +#define TIMESPEC_HZ 1000000000
> > +
> > +struct timespec_ns_test_case
> > +{
> > + struct timespec time;
> > + long time_ns;
> > +};
> > +
> > +struct timespec_norm_test_case
> > +{
> > + struct timespec time;
> > + struct timespec norm;
> > +};
> > +
> > +struct timespec_test_case
> > +{
> > + struct timespec expected;
> > + struct timespec observed;
> > + double upper_bound;
> > + double lower_bound;
> > + int result;
> > +};
> > +
> > +/* Test cases for timespec_ns */
> > +struct timespec_ns_test_case ns_cases[] = {
> > + {.time = {.tv_sec = 0, .tv_nsec = 0},
> > + .time_ns = 0,
> > + },
> > + {.time = {.tv_sec = 0, .tv_nsec = 1},
> > + .time_ns = 1,
> > + },
> > + {.time = {.tv_sec = 1, .tv_nsec = 0},
> > + .time_ns = TIMESPEC_HZ,
> > + },
> > + {.time = {.tv_sec = 1, .tv_nsec = 1},
> > + .time_ns = TIMESPEC_HZ + 1,
> > + },
> > + {.time = {.tv_sec = 0, .tv_nsec = -1},
> > + .time_ns = -1,
> > + },
> > + {.time = {.tv_sec = -1, .tv_nsec = 0},
> > + .time_ns = -TIMESPEC_HZ,
> > + },
> > + {.time = {.tv_sec = -1, .tv_nsec = -1},
> > + .time_ns = -TIMESPEC_HZ - 1,
> > + },
> > + {.time = {.tv_sec = 1, .tv_nsec = -1},
> > + .time_ns = TIMESPEC_HZ - 1,
> > + },
> > + {.time = {.tv_sec = -1, .tv_nsec = 1},
> > + .time_ns = -TIMESPEC_HZ + 1,
> > + },
> > + // Overflow bondary by 2
> > + {.time = {.tv_sec = LONG_MAX / TIMESPEC_HZ, .tv_nsec = LONG_MAX%TIMESPEC_HZ - 1},
> > + .time_ns = LONG_MAX - 1,
> > + },
> > + // Overflow bondary
> > + {.time = {.tv_sec = LONG_MAX / TIMESPEC_HZ, .tv_nsec = LONG_MAX%TIMESPEC_HZ},
> > + .time_ns = LONG_MAX,
> > + },
> > + // Underflow bondary by 1
> > + {.time = {.tv_sec = LONG_MIN / TIMESPEC_HZ, .tv_nsec = LONG_MIN%TIMESPEC_HZ + 1},
> > + .time_ns = LONG_MIN + 1,
> > + },
> > + // Underflow bondary
> > + {.time = {.tv_sec = LONG_MIN / TIMESPEC_HZ, .tv_nsec = LONG_MIN%TIMESPEC_HZ},
> > + .time_ns = LONG_MIN,
> > + },
> > + // Multiplication overflow
> > + {.time = {.tv_sec = LONG_MAX / TIMESPEC_HZ + 1, .tv_nsec = 1},
> > + .time_ns = LONG_MAX,
> > + },
> > + // Multiplication underflow
> > + {.time = {.tv_sec = LONG_MIN / TIMESPEC_HZ - 1, .tv_nsec = -1},
> > + .time_ns = LONG_MIN,
> > + },
> > + // Sum overflows
> > + {.time = {.tv_sec = LONG_MAX / TIMESPEC_HZ, .tv_nsec = LONG_MAX%TIMESPEC_HZ + 1},
> > + .time_ns = LONG_MAX,
> > + },
> > + // Sum underflow
> > + {.time = {.tv_sec = LONG_MIN / TIMESPEC_HZ, .tv_nsec = LONG_MIN%TIMESPEC_HZ - 1},
> > + .time_ns = LONG_MIN,
> > + }
> > +};
> > +
> > +/* Test cases for timespec_norm */
> > +struct timespec_norm_test_case norm_cases[] = {
> > + // Positive cases
> > + {.time = {.tv_sec = 0, .tv_nsec = 0},
> > + .norm = {.tv_sec = 0, .tv_nsec = 0}
> > + },
> > + {.time = {.tv_sec = 1, .tv_nsec = 0},
> > + .norm = {.tv_sec = 1, .tv_nsec = 0}
> > + },
> > + {.time = {.tv_sec = 0, .tv_nsec = 1},
> > + .norm = {.tv_sec = 0, .tv_nsec = 1}
> > + },
> > + {.time = {.tv_sec = 0, .tv_nsec = TIMESPEC_HZ},
> > + .norm = {.tv_sec = 1, .tv_nsec = 0}
> > + },
> > + {.time = {.tv_sec = 0, .tv_nsec = TIMESPEC_HZ + 1},
> > + .norm = {.tv_sec = 1, .tv_nsec = 1}
> > + },
> > + {.time = {.tv_sec = 1, .tv_nsec = TIMESPEC_HZ},
> > + .norm = {.tv_sec = 2, .tv_nsec = 0}
> > + },
> > + {.time = {.tv_sec = 1, .tv_nsec = TIMESPEC_HZ + 1},
> > + .norm = {.tv_sec = 2, .tv_nsec = 1}
> > + },
> > + // Negative cases
> > + {.time = {.tv_sec = 0, .tv_nsec = -TIMESPEC_HZ},
> > + .norm = {.tv_sec = -1, .tv_nsec = 0}
> > + },
> > + {.time = {.tv_sec = 0, .tv_nsec = -TIMESPEC_HZ - 1},
> > + .norm = {.tv_sec = -1, .tv_nsec = -1}
> > + },
> > + {.time = {.tv_sec = -1, .tv_nsec = -TIMESPEC_HZ},
> > + .norm = {.tv_sec = -2, .tv_nsec = 0}
> > + },
> > + {.time = {.tv_sec = -1, .tv_nsec = -TIMESPEC_HZ - 1},
> > + .norm = {.tv_sec = -2, .tv_nsec = -1}
> > + },
> > + // Overflow bondary by 2
> > + {.time = {.tv_sec = LONG_MAX - 2, .tv_nsec = TIMESPEC_HZ + 1},
> > + .norm = {.tv_sec = LONG_MAX - 1, 1},
> > + },
> > + // Overflow bondary by 1
> > + {.time = {.tv_sec = LONG_MAX - 1, .tv_nsec = TIMESPEC_HZ + 1},
> > + .norm = {.tv_sec = LONG_MAX, .tv_nsec = 1},
> > + },
> > + // Underflow bondary by 2
> > + {.time = {.tv_sec = LONG_MIN + 2, .tv_nsec = -TIMESPEC_HZ - 1},
> > + .norm = {.tv_sec = LONG_MIN + 1, -1},
> > + },
> > + // Underflow bondary by 1
> > + {.time = {.tv_sec = LONG_MIN + 1, .tv_nsec = -TIMESPEC_HZ - 1},
> > + .norm = {.tv_sec = LONG_MIN, .tv_nsec = -1},
> > + },
> > + // SUM overflow
> > + {.time = {.tv_sec = LONG_MAX, .tv_nsec = TIMESPEC_HZ},
> > + .norm = {.tv_sec = LONG_MAX, .tv_nsec = TIMESPEC_HZ - 1},
> > + },
> > + // SUM underflow
> > + {.time = {.tv_sec = LONG_MIN, .tv_nsec = -TIMESPEC_HZ},
> > + .norm = {.tv_sec = LONG_MIN, .tv_nsec = -1 * (TIMESPEC_HZ - 1)},
> > + }
> > +};
> > +
> > +/* Test cases for timespec_check_in_range */
> > +struct timespec_test_case check_cases[] = {
> > + // 0 - In range
> > + {.expected = {.tv_sec = 1, .tv_nsec = 0},
> > + .observed = {.tv_sec = 1, .tv_nsec = 0},
> > + .upper_bound = 1, .lower_bound = 1, .result = 1,
> > + },
> > + // 1 - Out of range
> > + {.expected = {.tv_sec = 1, .tv_nsec = 0},
> > + .observed = {.tv_sec = 2, .tv_nsec = 0},
> > + .upper_bound = 1, .lower_bound = 1, .result = 0,
> > + },
> > + // 2 - Upper Bound
> > + {.expected = {.tv_sec = 1, .tv_nsec = 0},
> > + .observed = {.tv_sec = 2, .tv_nsec = 0},
> > + .upper_bound = 2, .lower_bound = 1, .result = 1,
> > + },
> > + // 3 - Lower Bound
> > + {.expected = {.tv_sec = 1, .tv_nsec = 0},
> > + .observed = {.tv_sec = 0, .tv_nsec = 0},
> > + .upper_bound = 1, .lower_bound = 0, .result = 1,
> > + },
> > + // 4 - Out of range by nanosecs
> > + {.expected = {.tv_sec = 1, .tv_nsec = 0},
> > + .observed = {.tv_sec = 1, .tv_nsec = 500},
> > + .upper_bound = 1, .lower_bound = 1, .result = 0,
> > + },
> > + // 5 - In range by nanosecs
> > + {.expected = {.tv_sec = 1, .tv_nsec = 0},
> > + .observed = {.tv_sec = 1, .tv_nsec = 50000},
> > + .upper_bound = 1.3, .lower_bound = 1, .result = 1,
> > + },
> > + // 6 - Big nanosecs
> > + {.expected = {.tv_sec = 1, .tv_nsec = 0},
> > + .observed = {.tv_sec = 0, .tv_nsec = 4000000},
> > + .upper_bound = 1, .lower_bound = .001, .result = 1,
> > + },
> > + // 7 - In range Negative values
> > + {.expected = {.tv_sec = -1, .tv_nsec = 0},
> > + .observed = {.tv_sec = -1, .tv_nsec = 0},
> > + .upper_bound = 1, .lower_bound = 1, .result = 1,
> > + },
> > + // 8 - Out of range Negative values
> > + {.expected = {.tv_sec = -1, .tv_nsec = 0},
> > + .observed = {.tv_sec = -1, .tv_nsec = 0},
> > + .upper_bound = -1, .lower_bound = -1, .result = 0,
> > + },
> > + // 9 - Negative values with negative nanosecs
> > + {.expected = {.tv_sec = -1, .tv_nsec = 0},
> > + .observed = {.tv_sec = -1, .tv_nsec = -2000},
> > + .upper_bound = 1, .lower_bound = 1, .result = 0,
> > + },
> > + // 10 - Strict bounds
> > + {.expected = {.tv_sec = -1, .tv_nsec = 0},
> > + .observed = {.tv_sec = -1, .tv_nsec = -20000},
> > + .upper_bound = 1.00002, .lower_bound = 1.0000191, .result = 1,
> > + },
> > + // 11 - Strict bounds with loose upper bound
> > + {.expected = {.tv_sec = 1, .tv_nsec = 20000},
> > + .observed = {.tv_sec = 1, .tv_nsec = 30000},
> > + .upper_bound = 1.0000100000, .lower_bound = 1.0000099998, .result = 1,
> > + },
> > + // 12 - Strict bounds with loose lower bound
> > + {.expected = {.tv_sec = 1, .tv_nsec = 20000},
> > + .observed = {.tv_sec = 1, .tv_nsec = 30000},
> > + .upper_bound = 1.0000099999, .lower_bound = 1.00000999979, .result = 1,
> > + },
> > + // 13 - Strict bounds highest precision
> > + {.expected = {.tv_sec = 1, .tv_nsec = 20000},
> > + .observed = {.tv_sec = 1, .tv_nsec = 30000},
> > + .upper_bound = 1.00000999980001, .lower_bound = 1.00000999979999, .result = 1,
> > + },
> > + /* Maximum/Minimum long values */
> > + // 14
> > + {.expected = {.tv_sec = LONG_MAX, .tv_nsec = TIMESPEC_HZ - 1},
> > + .observed = {.tv_sec = LONG_MAX, .tv_nsec = TIMESPEC_HZ - 2},
> > + .upper_bound = 1, .lower_bound = .9, .result = 1,
> > + },
> > + // 15 - support_timespec_ns overflow
> > + {.expected = {.tv_sec = LONG_MAX, .tv_nsec = TIMESPEC_HZ},
> > + .observed = {.tv_sec = LONG_MAX, .tv_nsec = TIMESPEC_HZ},
> > + .upper_bound = 1, .lower_bound = 1, .result = 1,
> > + },
> > + // 16 - support_timespec_ns overflow + underflow
> > + {.expected = {.tv_sec = LONG_MAX, .tv_nsec = TIMESPEC_HZ},
> > + .observed = {.tv_sec = LONG_MIN, .tv_nsec = -TIMESPEC_HZ},
> > + .upper_bound = 1, .lower_bound = 1, .result = 0,
> > + },
> > + // 17 - support_timespec_ns underflow
> > + {.expected = {.tv_sec = LONG_MIN, .tv_nsec = -TIMESPEC_HZ},
> > + .observed = {.tv_sec = LONG_MIN, .tv_nsec = -TIMESPEC_HZ},
> > + .upper_bound = 1, .lower_bound = 1, .result = 1,
> > + },
> > + // 18 - support_timespec_ns underflow + overflow
> > + {.expected = {.tv_sec = LONG_MIN, .tv_nsec = -TIMESPEC_HZ},
> > + .observed = {.tv_sec = LONG_MAX, .tv_nsec = TIMESPEC_HZ},
> > + .upper_bound = 1, .lower_bound = 1, .result = 0,
> > + },
> > + // 19 - Biggest division
> > + {.expected = {.tv_sec = LONG_MAX / TIMESPEC_HZ , .tv_nsec = TIMESPEC_HZ - 1},
> > + .observed = {.tv_sec = 0, .tv_nsec = 1},
> > + .upper_bound = 1, .lower_bound = 1.0842021724855044e-19, .result = 1,
> > + },
> > + // 20 - Lowest division
> > + {.expected = {.tv_sec = 0, .tv_nsec = 1},
> > + .observed = {.tv_sec = LONG_MAX / TIMESPEC_HZ , .tv_nsec = TIMESPEC_HZ - 1},
> > + .upper_bound = LONG_MAX, .lower_bound = 1, .result = 1,
> > + },
> > +};
> > +
> > +static int
> > +do_test (void)
> > +{
> > + int i = 0;
> > + int ntests = sizeof (ns_cases) / sizeof (ns_cases[0]);
> > +
> > + printf("Testing support_timespec_ns\n");
> > + for (i = 0; i < ntests; i++)
> > + {
> > + TEST_COMPARE (support_timespec_ns (ns_cases[i].time),
> > + ns_cases[i].time_ns);
> > + }
> > +
> > + ntests = sizeof (norm_cases) / sizeof (norm_cases[0]);
> > + struct timespec result;
> > + printf("Testing support_timespec_normalize\n");
> > + for (i = 0; i < ntests; i++)
> > + {
> > + result = support_timespec_normalize (norm_cases[i].time);
> > + TEST_COMPARE (norm_cases[i].norm.tv_sec, result.tv_sec);
> > + TEST_COMPARE (norm_cases[i].norm.tv_nsec, result.tv_nsec);
> > + }
> > +
> > + ntests = sizeof (check_cases) / sizeof (check_cases[0]);
> > + printf("Testing support_timespec_check_in_range\n");
> > + for (i = 0; i < ntests; i++)
> > + {
> > + /* Its hard to find which test failed with just the TEST_COMPARE report.
> > + So here we print every running testcase as well. */
> > + printf("Test case %d\n", i);
> > + TEST_COMPARE (support_timespec_check_in_range
> > + (check_cases[i].expected, check_cases[i].observed,
> > + check_cases[i].lower_bound,
> > + check_cases[i].upper_bound), check_cases[i].result);
> > + }
> > + return 0;
> > +}
> > +
> > +#include <support/test-driver.c>
> > diff --git a/time/tst-cpuclock1.c b/time/tst-cpuclock1.c
> > index 0120906f23..1ac611a92b 100644
> > --- a/time/tst-cpuclock1.c
> > +++ b/time/tst-cpuclock1.c
> > @@ -26,6 +26,7 @@
> > #include <signal.h>
> > #include <stdint.h>
> > #include <sys/wait.h>
> > +#include <support/timespec.h>
> >
> > /* This function is intended to rack up both user and system time. */
> > static void
> > @@ -155,16 +156,12 @@ 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)
> > + /* The bound values are empirically defined by testing this code over high cpu
> > + usage and different nice values. Of all the values we keep the 90th
> > + percentile of values and use those values for our testing allowed range. */
> > + struct timespec diff = timespec_sub (support_timespec_normalize (after),
> > + support_timespec_normalize (before));
> > + if (!support_timespec_check_in_range (sleeptime, diff, .9, 1.1))
> > {
> > printf ("before - after %ju.%.9ju outside reasonable range\n",
> > (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
> > @@ -194,19 +191,16 @@ 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)
> > + /* The bound values are empirically defined by testing this code over
> > + high cpu usage and different nice values. Of all the values we keep
> > + the 90th percentile of values and use those values for our testing
> > + allowed range. */
> > + diff = timespec_sub (support_timespec_normalize (afterns),
> > + support_timespec_normalize (after));
> > + if (!support_timespec_check_in_range (sleeptime, diff, .9, 1.2))
> > {
> > 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;
> > }
> > }
> > @@ -240,15 +234,13 @@ do_test (void)
> > /* 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)
> > + /* The bound values are empirically defined by testing this code over high cpu
> > + usage and different nice values. Of all the values we keep the 90th
> > + percentile of values and use those values for our testing allowed range. */
> > + diff = timespec_sub (support_timespec_normalize (dead),
> > + support_timespec_normalize (after));
> > + sleeptime.tv_nsec = 100000000;
> > + if (!support_timespec_check_in_range (sleeptime, diff, .9, 1.2))
> > {
> > printf ("dead - after %ju.%.9ju outside reasonable range\n",
> > (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
> > --
> > 2.20.1
> >
More information about the Libc-alpha
mailing list