From patchwork Tue Oct 8 01:56:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: DJ Delorie X-Patchwork-Id: 1993933 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=UaaBkBYt; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XMzhY0cBSz1xsn for ; Tue, 8 Oct 2024 12:58:53 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EA0B5385C6C6 for ; Tue, 8 Oct 2024 01:58:50 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id C79463857000 for ; Tue, 8 Oct 2024 01:57:04 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C79463857000 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C79463857000 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728352667; cv=none; b=Dnmymo5IAZxJ53XhsuoIYwENil11vtYmtYlm+IoJjKcpJo42brNQias0HMY9KY89WhKv92eIRO7844vy02g2Na6cjarbt8VTURRSrZdLdrf1OYn70FtQGJ3x+Lxx0dtSZhwzW+Uo3VUSdPW7ZKtwdJL0QPw7hDvORych732J9Tg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1728352667; c=relaxed/simple; bh=uu5nZm7nv63nWzRCJ0piMzlRsYQYzPlff0BJ0AdUFo4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=Q1zhD8Y2uAQDKjUeQlt/7VlW9EgpWlBsCJi+WYSV6Y20NqGAyMEQshPRLX/TnK2DTrsAv1u0D9HZNaA9NeFKRrkC6eu0NXjSEa7a+XjyWvGJ9GAg0d25ig6RKaNTQg0AMEaYmH+xRMJMBwrOtg2CA8OGPcJWefHhTGXy8DDigo8= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1728352624; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type; bh=CTloSiNGqchq26XLHCpbw6rxNOuam9/A4XMz+9TD4B8=; b=UaaBkBYt69lv9w+XSgg/Of2wUZ49YspAYlnSG+3bbwtDf7utHbsMjzfTMzQ/YaHvxJuw5+ z4BcVkE397P0LT/wvGijGcmxUFR/7w2VU39VC/mkhheaNDpoXkAV+SYvjePg1Ui7dmdWc/ jx7U3dHF39L7REoeqogQfdV054BowSM= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-184-K4gsnhAPOj-RLt6yHecV1A-1; Mon, 07 Oct 2024 21:57:01 -0400 X-MC-Unique: K4gsnhAPOj-RLt6yHecV1A-1 Received: from mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.40]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A331E1956096; Tue, 8 Oct 2024 01:57:00 +0000 (UTC) Received: from greed.delorie.com (unknown [10.22.8.53]) by mx-prod-int-04.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 526FB19560AA; Tue, 8 Oct 2024 01:57:00 +0000 (UTC) Received: from greed.delorie.com.redhat.com (localhost [127.0.0.1]) by greed.delorie.com (8.16.1/8.16.1) with ESMTP id 4981uwF41656848; Mon, 7 Oct 2024 21:56:58 -0400 From: DJ Delorie To: Adhemerval Zanella Netto Cc: libc-alpha@sourceware.org Subject: [patch v2] rt: more clock_nanosleep tests Date: Mon, 07 Oct 2024 21:56:58 -0400 Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.40 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-10.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org 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 diff --git a/rt/Makefile b/rt/Makefile index 7b50c64f76..c1c7cbfe6d 100644 --- a/rt/Makefile +++ b/rt/Makefile @@ -77,6 +77,7 @@ tests := tst-shm tst-timer tst-timer2 \ tst-bz28213 \ tst-timer3 tst-timer4 tst-timer5 \ tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \ + tst-cpuclock3 \ tst-shm-cancel \ tst-mqueue10 tests-internal := tst-timer-sigmask @@ -84,6 +85,7 @@ tests-internal := tst-timer-sigmask tests-time64 := \ tst-aio6-time64 \ tst-cpuclock2-time64 \ + tst-cpuclock3-time64 \ tst-mqueue1-time64 \ tst-mqueue2-time64 \ tst-mqueue4-time64 \ diff --git a/rt/tst-cpuclock3-time64.c b/rt/tst-cpuclock3-time64.c new file mode 100644 index 0000000000..01cb55f1d6 --- /dev/null +++ b/rt/tst-cpuclock3-time64.c @@ -0,0 +1 @@ +#include "tst-cpuclock3.c" diff --git a/rt/tst-cpuclock3.c b/rt/tst-cpuclock3.c new file mode 100644 index 0000000000..10c822fd54 --- /dev/null +++ b/rt/tst-cpuclock3.c @@ -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 + . */ + +/* 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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* 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