• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 
main(int ac,char ** av)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 
do_child(void)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 
setup(void)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 
sig_handler(void)151 static void sig_handler(void)
152 {
153 }
154