1 /* 2 * Copyright (c) International Business Machines Corp., 2001 3 * 07/2001 Ported by Wayne Boyer 4 * Copyright (C) Cyril Hrubis <chrubis (at) 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 40 char *TCID = "nanosleep02"; 41 int TST_TOTAL = 1; 42 43 static void do_child(void); 44 static void setup(void); 45 static void sig_handler(); 46 47 /* 48 * Define here the "rem" precision in microseconds, 49 * Various implementations will provide different 50 * precisions. The -aa tree provides up to usec precision. 51 * NOTE: all the trees that don't provide a precision of 52 * the order of the microseconds are subject to an userspace 53 * live lock condition with glibc under a flood of signals, 54 * the "rem" field would never change without the increased 55 * usec precision in the -aa tree. 56 */ 57 #define USEC_PRECISION 250000 /* Error margin allowed in usec */ 58 59 int main(int ac, char **av) 60 { 61 int lc; 62 pid_t cpid; 63 64 tst_parse_opts(ac, av, NULL, NULL); 65 66 #ifdef UCLINUX 67 maybe_run_child(&do_child, ""); 68 #endif 69 70 setup(); 71 72 for (lc = 0; TEST_LOOPING(lc); lc++) { 73 74 tst_count = 0; 75 76 if ((cpid = FORK_OR_VFORK()) == -1) { 77 tst_brkm(TBROK, NULL, 78 "fork() failed to create child process"); 79 } 80 81 if (cpid == 0) { 82 #ifdef UCLINUX 83 if (self_exec(av[0], "")) { 84 tst_brkm(TBROK, NULL, "self_exec failed"); 85 } 86 #else 87 do_child(); 88 #endif 89 } 90 91 /* wait for child to time slot for execution */ 92 sleep(1); 93 94 /* Now send signal to child */ 95 if (kill(cpid, SIGINT) < 0) { 96 tst_brkm(TBROK, NULL, 97 "kill() fails send signal to child"); 98 } 99 100 tst_record_childstatus(NULL, cpid); 101 } 102 103 tst_exit(); 104 } 105 106 static void do_child(void) 107 { 108 struct timespec timereq = {.tv_sec = 5, .tv_nsec = 9999}; 109 struct timespec timerem, exp_rem; 110 111 tst_timer_start(CLOCK_MONOTONIC); 112 TEST(nanosleep(&timereq, &timerem)); 113 tst_timer_stop(); 114 115 if (tst_timespec_lt(timereq, tst_timer_elapsed())) { 116 tst_resm(TFAIL, "nanosleep() slept more than timereq"); 117 return; 118 } 119 120 exp_rem = tst_timespec_diff(timereq, tst_timer_elapsed()); 121 122 if (tst_timespec_abs_diff_us(timerem, exp_rem) > USEC_PRECISION) { 123 tst_resm(TFAIL, 124 "nanosleep() remaining time %llius, expected %llius, diff %llius", 125 tst_timespec_to_us(timerem), tst_timespec_to_us(exp_rem), 126 tst_timespec_abs_diff_us(timerem, exp_rem)); 127 } else { 128 tst_resm(TPASS, 129 "nanosleep() slept for %llius, remaining time difference %llius", 130 tst_timer_elapsed_us(), 131 tst_timespec_abs_diff_us(timerem, exp_rem)); 132 } 133 134 tst_exit(); 135 } 136 137 static void setup(void) 138 { 139 tst_sig(FORK, DEF_HANDLER, NULL); 140 141 tst_timer_check(CLOCK_MONOTONIC); 142 143 TEST_PAUSE; 144 145 if (signal(SIGINT, sig_handler) == SIG_ERR) { 146 tst_brkm(TBROK, NULL, 147 "signal() fails to setup signal handler"); 148 } 149 } 150 151 static void sig_handler(void) 152 { 153 } 154