1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2001 4 * 07/2001 Ported by Wayne Boyer 5 * Copyright (C) Cyril Hrubis <chrubis@suse.cz> 6 */ 7 8/* 9 * Test Description: 10 * Verify that nanosleep() will be successful to suspend the execution 11 * of a process, returns after the receipt of a signal and writes the 12 * remaining sleep time into the structure. 13 * 14 * This test also verifies that if the call is interrupted by a signal 15 * handler, nanosleep() returns -1, sets errno to EINTR. 16 */ 17 18#include <errno.h> 19 20#include "tst_test.h" 21#include "tst_timer.h" 22#include "tst_safe_macros.h" 23 24/* 25 * Define here the "rem" precision in microseconds, 26 * Various implementations will provide different 27 * precisions. The -aa tree provides up to usec precision. 28 * NOTE: all the trees that don't provide a precision of 29 * the order of the microseconds are subject to an userspace 30 * live lock condition with glibc under a flood of signals, 31 * the "rem" field would never change without the increased 32 * usec precision in the -aa tree. 33 */ 34#define USEC_PRECISION 250000 /* Error margin allowed in usec */ 35 36static void do_child(void) 37{ 38 struct timespec timereq = {.tv_sec = 5, .tv_nsec = 9999}; 39 struct timespec timerem, exp_rem; 40 41 tst_timer_start(CLOCK_MONOTONIC); 42 TEST(nanosleep(&timereq, &timerem)); 43 tst_timer_stop(); 44 45 if (TST_RET != -1) { 46 tst_res(TFAIL, 47 "nanosleep was not interrupted, returned %ld, expected -1", 48 TST_RET); 49 return; 50 } 51 if (TST_ERR != EINTR) { 52 tst_res(TFAIL | TTERRNO, 53 "nanosleep() failed, expected EINTR, got"); 54 return; 55 } 56 57 tst_res(TPASS, "nanosleep() returned -1, set errno to EINTR"); 58 59 if (tst_timespec_lt(timereq, tst_timer_elapsed())) 60 tst_brk(TFAIL, "nanosleep() slept more than timereq"); 61 62 exp_rem = tst_timespec_diff(timereq, tst_timer_elapsed()); 63 64 if (tst_timespec_abs_diff_us(timerem, exp_rem) > USEC_PRECISION) { 65 tst_res(TFAIL, 66 "nanosleep() remaining time %llius, expected %llius, diff %llius", 67 tst_timespec_to_us(timerem), tst_timespec_to_us(exp_rem), 68 tst_timespec_abs_diff_us(timerem, exp_rem)); 69 } else { 70 tst_res(TPASS, 71 "nanosleep() slept for %llius, remaining time difference %llius", 72 tst_timer_elapsed_us(), 73 tst_timespec_abs_diff_us(timerem, exp_rem)); 74 } 75} 76 77void run(void) 78{ 79 pid_t cpid; 80 81 cpid = SAFE_FORK(); 82 if (cpid == 0) { 83 do_child(); 84 } else { 85 sleep(1); 86 87 SAFE_KILL(cpid, SIGINT); 88 89 tst_reap_children(); 90 } 91} 92 93static void sig_handler(int si LTP_ATTRIBUTE_UNUSED) 94{ 95} 96 97static void setup(void) 98{ 99 tst_timer_check(CLOCK_MONOTONIC); 100 SAFE_SIGNAL(SIGINT, sig_handler); 101} 102 103static struct tst_test test = { 104 .forks_child = 1, 105 .setup = setup, 106 .test_all = run, 107}; 108