From patchwork Thu Feb 6 14:48:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Lucas A. M. Magalhaes" X-Patchwork-Id: 37709 X-Patchwork-Delegate: azanella@linux.vnet.ibm.com Received: (qmail 72797 invoked by alias); 6 Feb 2020 14:48:52 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 72385 invoked by uid 89); 6 Feb 2020 14:48:30 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-19.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_SHORT, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.1 spammy=rack, heavy X-HELO: mx0a-001b2d01.pphosted.com From: "Lucas A. M. Magalhaes" To: libc-alpha@sourceware.org Cc: codonell@redhat.com Subject: [PATCH v2] Fix time/tst-cpuclock1 intermitent failures Date: Thu, 6 Feb 2020 11:48:19 -0300 Message-Id: <20200206144819.19046-1-lamm@linux.ibm.com> MIME-Version: 1.0 This test fails intermittently in systems with heavy load as CLOCK_PROCESS_CPUTIME_ID is subject to scheduler pressure. Thus the test boundaries where relaxed to keep it from fail on this systems. A refactor of the spent time checking was made with some support functions. With the advantage to represent time jitter in percent of the target. The values used by the test boundaries are all empirical. --- Hi, Please Carlos see if this is what you asked. I spent sometime gathering the spent times to find the values for the boundaries. From this I selected values that will fail less than 1% of the time, in the tested machines. Also as I found the spent time deviation completely asymmetrical I choose to separate the values in upper and lower bounds. changes from V2: - Add support functions support/Makefile | 1 + support/cpuclock.c | 51 ++++++++++++++++++++++++++++++++++++++++++++ support/cpuclock.h | 30 ++++++++++++++++++++++++++ time/tst-cpuclock1.c | 43 ++++++++++--------------------------- 4 files changed, 93 insertions(+), 32 deletions(-) create mode 100644 support/cpuclock.c create mode 100644 support/cpuclock.h diff --git a/support/Makefile b/support/Makefile index 3325feb790..b308fe0856 100644 --- a/support/Makefile +++ b/support/Makefile @@ -31,6 +31,7 @@ libsupport-routines = \ check_dns_packet \ check_hostent \ check_netent \ + cpuclock \ delayed_exit \ ignore_stderr \ next_to_fault \ diff --git a/support/cpuclock.c b/support/cpuclock.c new file mode 100644 index 0000000000..f40c7e8d4a --- /dev/null +++ b/support/cpuclock.c @@ -0,0 +1,51 @@ +/* Support functions for cpuclock tests. + Copyright (C) 2018-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 "cpuclock.h" +#include + +#define T_1s 1000000000.0 + +struct timespec time_normalize(struct timespec t) { + int diff; + diff = (t.tv_nsec / T_1s); + t.tv_sec += diff; + t.tv_nsec += -(diff * T_1s); + return t; +} + +struct timespec time_add(struct timespec a, struct timespec b) { + struct timespec s = {.tv_sec = a.tv_sec + b.tv_sec, + .tv_nsec = a.tv_nsec + b.tv_nsec}; + return time_normalize(s); +} + +struct timespec time_sub(struct timespec a, struct timespec b) { + struct timespec d = {.tv_sec = a.tv_sec - b.tv_sec, + .tv_nsec = a.tv_nsec - b.tv_nsec}; + return time_normalize(d); +} + +int percent_diff_check(struct timespec base, struct timespec dev, + float upper_bound, float lower_bound) { + double timea = base.tv_sec + base.tv_nsec / T_1s; + double timeb = dev.tv_sec + dev.tv_nsec / T_1s; + double diff = (timea - timeb) / (0.5 * (timea + timeb)); + return (diff >= -upper_bound && diff <= lower_bound ); +} + diff --git a/support/cpuclock.h b/support/cpuclock.h new file mode 100644 index 0000000000..2505fbdcff --- /dev/null +++ b/support/cpuclock.h @@ -0,0 +1,30 @@ +/* Support functions for cpuclock tests. + Copyright (C) 2018-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 time_normalize(struct timespec t); +struct timespec time_add(struct timespec a, struct timespec b); +struct timespec time_sub(struct timespec a, struct timespec b); +int percent_diff_check(struct timespec base, struct timespec dev, + float upper_bound, float lower_bound); + +#endif /* SUPPORT_CPUCLOCK_H */ diff --git a/time/tst-cpuclock1.c b/time/tst-cpuclock1.c index 0120906f23..4051de1646 100644 --- a/time/tst-cpuclock1.c +++ b/time/tst-cpuclock1.c @@ -26,6 +26,7 @@ #include #include #include +#include /* This function is intended to rack up both user and system time. */ static void @@ -155,19 +156,11 @@ 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) + struct timespec diff = time_sub(after, before); + if (!percent_diff_check(sleeptime, diff, .3, 2)) { 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 +187,11 @@ 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) + diff = time_sub(afterns, after); + if (!percent_diff_check(sleeptime, diff, .6, .34)) { 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,20 +226,14 @@ 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) + diff = time_sub(dead, after); + sleeptime.tv_nsec = 100000000; + if (!percent_diff_check(sleeptime, diff, .6, .36)) { 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; } - /* Now reap the child and verify that its clock is no longer valid. */ { int x;