1/* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 07/2001 Ported by Wayne Boyer 4 * Copyright (C) Cyril Hrubis <chrubis@suse.cz> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14 * the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21/* 22 * Test Description: 23 * Verify that nanosleep() will be successful to suspend the execution 24 * of a process, returns after the receipt of a signal and writes the 25 * remaining sleep time into the structure. 26 */ 27 28#include <errno.h> 29#include <unistd.h> 30#include <fcntl.h> 31#include <signal.h> 32#include <time.h> 33#include <sys/wait.h> 34#include <sys/time.h> 35#include <stdint.h> 36#include <inttypes.h> 37 38#include "test.h" 39#include "safe_macros.h" 40 41char *TCID = "nanosleep02"; 42int TST_TOTAL = 1; 43 44static void do_child(void); 45static void setup(void); 46static void sig_handler(); 47 48/* 49 * Define here the "rem" precision in microseconds, 50 * Various implementations will provide different 51 * precisions. The -aa tree provides up to usec precision. 52 * NOTE: all the trees that don't provide a precision of 53 * the order of the microseconds are subject to an userspace 54 * live lock condition with glibc under a flood of signals, 55 * the "rem" field would never change without the increased 56 * usec precision in the -aa tree. 57 */ 58#define USEC_PRECISION 250000 /* Error margin allowed in usec */ 59 60int main(int ac, char **av) 61{ 62 int lc; 63 pid_t cpid; 64 65 tst_parse_opts(ac, av, NULL, NULL); 66 67#ifdef UCLINUX 68 maybe_run_child(&do_child, ""); 69#endif 70 71 setup(); 72 73 for (lc = 0; TEST_LOOPING(lc); lc++) { 74 75 tst_count = 0; 76 77 if ((cpid = FORK_OR_VFORK()) == -1) { 78 tst_brkm(TBROK, NULL, 79 "fork() failed to create child process"); 80 } 81 82 if (cpid == 0) { 83#ifdef UCLINUX 84 if (self_exec(av[0], "")) { 85 tst_brkm(TBROK, NULL, "self_exec failed"); 86 } 87#else 88 do_child(); 89#endif 90 } 91 92 /* wait for child to time slot for execution */ 93 sleep(1); 94 95 /* Now send signal to child */ 96 SAFE_KILL(NULL, cpid, SIGINT); 97 98 tst_record_childstatus(NULL, cpid); 99 } 100 101 tst_exit(); 102} 103 104static void do_child(void) 105{ 106 struct timespec timereq = {.tv_sec = 5, .tv_nsec = 9999}; 107 struct timespec timerem, exp_rem; 108 109 tst_timer_start(CLOCK_MONOTONIC); 110 TEST(nanosleep(&timereq, &timerem)); 111 tst_timer_stop(); 112 113 if (tst_timespec_lt(timereq, tst_timer_elapsed())) { 114 tst_resm(TFAIL, "nanosleep() slept more than timereq"); 115 return; 116 } 117 118 exp_rem = tst_timespec_diff(timereq, tst_timer_elapsed()); 119 120 if (tst_timespec_abs_diff_us(timerem, exp_rem) > USEC_PRECISION) { 121 tst_resm(TFAIL, 122 "nanosleep() remaining time %llius, expected %llius, diff %llius", 123 tst_timespec_to_us(timerem), tst_timespec_to_us(exp_rem), 124 tst_timespec_abs_diff_us(timerem, exp_rem)); 125 } else { 126 tst_resm(TPASS, 127 "nanosleep() slept for %llius, remaining time difference %llius", 128 tst_timer_elapsed_us(), 129 tst_timespec_abs_diff_us(timerem, exp_rem)); 130 } 131 132 tst_exit(); 133} 134 135static void setup(void) 136{ 137 tst_sig(FORK, DEF_HANDLER, NULL); 138 139 tst_timer_check(CLOCK_MONOTONIC); 140 141 TEST_PAUSE; 142 143 if (signal(SIGINT, sig_handler) == SIG_ERR) { 144 tst_brkm(TBROK, NULL, 145 "signal() fails to setup signal handler"); 146 } 147} 148 149static void sig_handler(void) 150{ 151} 152