blob: 6fbe75b343f199d2bc8ab4b4d2e3d0a8f2553a8b [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
Wanlong Gao4548c6c2012-10-19 18:03:36 +080017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
plars865695b2001-08-27 22:15:12 +000018 */
19
20/*
21 * Test Name: nanosleep02
22 *
23 * Test Description:
24 * Verify that nanosleep() will be successful to suspend the execution
25 * of a process, returns after the receipt of a signal and writes the
26 * remaining sleep time into the structure.
27 *
28 * Expected Result:
29 * nanosleep() should return with after receipt of a signal and write
30 * remaining sleep time into a structure. if called again, succeeds to
31 * suspend execution of process for the specified sleep time.
32 *
33 * Algorithm:
34 * Setup:
35 * Setup signal handling.
36 * Pause for SIGUSR1 if option specified.
37 *
38 * Test:
39 * Loop if the proper options are given.
40 * Execute system call
41 * Check return code, if system call failed (return=-1)
subrata_modak56207ce2009-03-23 13:35:39 +000042 * Log the errno and Issue a FAIL message.
plars865695b2001-08-27 22:15:12 +000043 * Otherwise,
subrata_modak56207ce2009-03-23 13:35:39 +000044 * Verify the Functionality of system call
plars865695b2001-08-27 22:15:12 +000045 * if successful,
46 * Issue Functionality-Pass message.
47 * Otherwise,
48 * Issue Functionality-Fail message.
49 * Cleanup:
50 * Print errno log and/or timing stats if options given
51 *
52 * Usage: <for command-line>
53 * nanosleep02 [-c n] [-f] [-i n] [-I x] [-P x] [-t]
54 * where, -c n : Run n copies concurrently.
55 * -f : Turn off functionality Testing.
56 * -i n : Execute test n times.
57 * -I x : Execute test for x seconds.
58 * -P x : Pause for x seconds between iterations.
59 * -t : Turn on syscall timing.
60 *
61 * HISTORY
62 * 07/2001 Ported by Wayne Boyer
subrata_modakbdbaec52009-02-26 12:14:51 +000063 * 05/2004 Changed USEC_PRECISION from 100 to 2000 to get around glibc failure
mridge4238f342004-05-10 19:24:02 +000064 * that's years old.
plars865695b2001-08-27 22:15:12 +000065 *
66 * RESTRICTIONS:
67 * None.
plars865695b2001-08-27 22:15:12 +000068 */
subrata_modak56207ce2009-03-23 13:35:39 +000069
plars865695b2001-08-27 22:15:12 +000070#include <errno.h>
71#include <unistd.h>
72#include <fcntl.h>
73#include <signal.h>
74#include <time.h>
robbiew01be3332003-03-26 23:48:41 +000075#include <wait.h>
76#include <sys/time.h>
subrata_modak923b23f2009-11-02 13:57:16 +000077#include <stdint.h>
yaberauneyaf00ed7a2009-12-22 17:35:13 +000078#include <inttypes.h>
plars865695b2001-08-27 22:15:12 +000079
80#include "test.h"
plars865695b2001-08-27 22:15:12 +000081
Cyril Hrubisfdce7d52013-04-04 18:35:48 +020082char *TCID = "nanosleep02";
83int TST_TOTAL = 1;
plars865695b2001-08-27 22:15:12 +000084
plars865695b2001-08-27 22:15:12 +000085struct timespec timereq; /* time struct. buffer for nanosleep() */
86struct timespec timerem; /* time struct. buffer for nanosleep() */
87
robbiewd34d5812005-07-11 22:28:09 +000088void do_child(); /* Child process */
plars865695b2001-08-27 22:15:12 +000089void setup(); /* Main setup function of test */
90void cleanup(); /* cleanup function for the test */
91void sig_handler(); /* signal catching function */
92
robbiew9b919472002-09-10 15:11:44 +000093/*
94 * Define here the "rem" precision in microseconds,
95 * Various implementations will provide different
96 * precisions. The -aa tree provides up to usec precision.
97 * NOTE: all the trees that don't provide a precision of
98 * the order of the microseconds are subject to an userspace
99 * live lock condition with glibc under a flood of signals,
100 * the "rem" field would never change without the increased
101 * usec precision in the -aa tree.
102 */
subrata_modak56207ce2009-03-23 13:35:39 +0000103#define USEC_PRECISION 250000 /* Error margin allowed in usec */
robbiew9b919472002-09-10 15:11:44 +0000104
subrata_modak56207ce2009-03-23 13:35:39 +0000105int main(int ac, char **av)
plars865695b2001-08-27 22:15:12 +0000106{
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200107 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200108 const char *msg;
plars865695b2001-08-27 22:15:12 +0000109 pid_t cpid; /* Child process id */
plars865695b2001-08-27 22:15:12 +0000110 int status; /* child exit status */
subrata_modak56207ce2009-03-23 13:35:39 +0000111
Garrett Coopera9e49f12010-12-16 10:54:03 -0800112 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800113 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
robbiewd34d5812005-07-11 22:28:09 +0000114#ifdef UCLINUX
115 maybe_run_child(&do_child, "dddd", &timereq.tv_sec, &timereq.tv_nsec,
116 &timerem.tv_sec, &timerem.tv_nsec);
117#endif
118
plars865695b2001-08-27 22:15:12 +0000119 setup();
120
plars865695b2001-08-27 22:15:12 +0000121 for (lc = 0; TEST_LOOPING(lc); lc++) {
122
Caspar Zhangd59a6592013-03-07 14:59:12 +0800123 tst_count = 0;
plars865695b2001-08-27 22:15:12 +0000124
125 /*
126 * Creat a child process and suspend its
127 * execution using nanosleep()
128 */
robbiewd34d5812005-07-11 22:28:09 +0000129 if ((cpid = FORK_OR_VFORK()) == -1) {
plars865695b2001-08-27 22:15:12 +0000130 tst_brkm(TBROK, cleanup,
131 "fork() failed to create child process");
132 }
133
subrata_modak56207ce2009-03-23 13:35:39 +0000134 if (cpid == 0) { /* Child process */
robbiewd34d5812005-07-11 22:28:09 +0000135#ifdef UCLINUX
136 if (self_exec(av[0], "dddd",
137 timereq.tv_sec, timereq.tv_nsec,
138 timerem.tv_sec, timerem.tv_nsec) < 0) {
139 tst_brkm(TBROK, cleanup, "self_exec failed");
plars865695b2001-08-27 22:15:12 +0000140 }
robbiewd34d5812005-07-11 22:28:09 +0000141#else
142 do_child();
143#endif
plars865695b2001-08-27 22:15:12 +0000144 }
145
146 /* wait for child to time slot for execution */
147 sleep(1);
148
149 /* Now send signal to child */
150 if (kill(cpid, SIGINT) < 0) {
151 tst_brkm(TBROK, cleanup,
152 "kill() fails send signal to child");
153 }
154
155 /* Wait for child to execute */
156 wait(&status);
yaberauneyaf00ed7a2009-12-22 17:35:13 +0000157 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
158 tst_resm(TPASS, "Functionality of nanosleep() is "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800159 "correct");
yaberauneyaf00ed7a2009-12-22 17:35:13 +0000160 } else {
161 tst_resm(TFAIL, "child process exited abnormally; "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800162 "status = %d", status);
plars865695b2001-08-27 22:15:12 +0000163 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800164 }
plars865695b2001-08-27 22:15:12 +0000165
plars865695b2001-08-27 22:15:12 +0000166 cleanup();
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800167 tst_exit();
plars865695b2001-08-27 22:15:12 +0000168
Garrett Cooper2c282152010-12-16 00:55:50 -0800169}
plars865695b2001-08-27 22:15:12 +0000170
171/*
robbiewd34d5812005-07-11 22:28:09 +0000172 * do_child()
173 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400174void do_child(void)
robbiewd34d5812005-07-11 22:28:09 +0000175{
subrata_modak56207ce2009-03-23 13:35:39 +0000176 unsigned long req, rem, elapsed; /* usec */
177 struct timeval otime; /* time before child execution suspended */
178 struct timeval ntime; /* time after child resumes execution */
robbiewd34d5812005-07-11 22:28:09 +0000179
180 /* Note down the current time */
181 gettimeofday(&otime, NULL);
subrata_modak4bb656a2009-02-26 12:02:09 +0000182 /*
robbiewd34d5812005-07-11 22:28:09 +0000183 * Call nanosleep() to suspend child process
184 * for specified time 'tv_sec'.
185 * Call should return before suspending execution
186 * for the specified time due to receipt of signal
187 * from Parent.
188 */
189 TEST(nanosleep(&timereq, &timerem));
190 /* time after child resumes execution */
191 gettimeofday(&ntime, NULL);
192
193 /*
194 * Check whether the remaining sleep of child updated
195 * in 'timerem' structure.
196 * The time remaining should be equal to the
197 * Total time for sleep - time spent on sleep bfr signal
subrata_modak56207ce2009-03-23 13:35:39 +0000198 * Change precision from msec to usec.
robbiewd34d5812005-07-11 22:28:09 +0000199 */
subrata_modak56207ce2009-03-23 13:35:39 +0000200 req = timereq.tv_sec * 1000000 + timereq.tv_nsec / 1000;
201 rem = timerem.tv_sec * 1000000 + timerem.tv_nsec / 1000;
202 elapsed =
203 (ntime.tv_sec - otime.tv_sec) * 1000000 + ntime.tv_usec -
204 otime.tv_usec;
robbiewd34d5812005-07-11 22:28:09 +0000205
subrata_modak56207ce2009-03-23 13:35:39 +0000206 if (rem - (req - elapsed) > USEC_PRECISION) {
207 tst_resm(TWARN,
208 "This test could fail if the system was under load");
209 tst_resm(TWARN,
210 "due to the limitation of the way it calculates the");
211 tst_resm(TWARN, "system call execution time.");
212 tst_resm(TFAIL, "Remaining sleep time %lu usec doesn't "
213 "match with the expected %lu usec time",
robbiewd34d5812005-07-11 22:28:09 +0000214 rem, (req - elapsed));
robbiewd34d5812005-07-11 22:28:09 +0000215 } else {
yaberauneyacba23872010-01-06 06:06:15 +0000216
217 /* Record the time before suspension */
218 gettimeofday(&otime, NULL);
219
220 /*
221 * Invoke nanosleep() again to suspend child
222 * for the specified sleep time specified by
223 * 'timereq' structure.
224 */
225 TEST(nanosleep(&timereq, &timerem));
226
227 /* Record the time after suspension */
228 gettimeofday(&ntime, NULL);
229
yaberauneyacba23872010-01-06 06:06:15 +0000230 if (TEST_RETURN == -1) {
231 tst_resm(TFAIL | TTERRNO, "nanosleep() failed");
Cyril Hrubise38b9612014-06-02 17:20:57 +0200232 } else {
yaberauneyacba23872010-01-06 06:06:15 +0000233 /*
234 * Verify whether child execution was
235 * actually suspended for the remaining
236 * sleep time specified by 'timerem'
237 * structure.
238 */
239 req = timereq.tv_sec * 1000000 + timereq.tv_nsec / 1000;
240 elapsed =
Wanlong Gao354ebb42012-12-07 10:10:04 +0800241 (ntime.tv_sec - otime.tv_sec) * 1000000 +
242 ntime.tv_usec - otime.tv_usec;
yaberauneyacba23872010-01-06 06:06:15 +0000243 if (elapsed - req > USEC_PRECISION) {
244 tst_resm(TWARN,
245 "This test could fail if the system "
246 "was under load due to the limitation "
247 "of the way it calculates the system "
248 "call execution time.");
249 tst_resm(TFAIL, "Child execution not suspended "
Wanlong Gao354ebb42012-12-07 10:10:04 +0800250 "for %jd seconds %lu "
251 "nanoseconds",
252 (intmax_t) timereq.tv_sec,
253 timereq.tv_nsec);
yaberauneyacba23872010-01-06 06:06:15 +0000254 } else {
255 tst_resm(TINFO, "call succeeded");
256 }
257
258 }
259
robbiewd34d5812005-07-11 22:28:09 +0000260 }
yaberauneyacba23872010-01-06 06:06:15 +0000261
262 tst_exit();
263
robbiewd34d5812005-07-11 22:28:09 +0000264}
265
266/*
plars865695b2001-08-27 22:15:12 +0000267 * setup() - performs all ONE TIME setup for this test.
268 * Setup signal handler to catch the interrupt signal sent by parent
269 * to child process.
270 * Initialise time structure elements.
271 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400272void setup(void)
plars865695b2001-08-27 22:15:12 +0000273{
Garrett Cooper2c282152010-12-16 00:55:50 -0800274
plars865695b2001-08-27 22:15:12 +0000275 tst_sig(FORK, DEF_HANDLER, cleanup);
276
plars865695b2001-08-27 22:15:12 +0000277 TEST_PAUSE;
278
279 /* Setup signal handler */
280 if (signal(SIGINT, sig_handler) == SIG_ERR) {
281 tst_brkm(TBROK, cleanup,
282 "signal() fails to setup signal handler");
283 }
284
285 /* Initialise time variables which used to suspend child execution */
286 timereq.tv_sec = 5;
287 timereq.tv_nsec = 9999;
288
289 /* Initialise 'time remaining' structure elements to NULL */
290 timerem.tv_sec = 0;
291 timerem.tv_nsec = 0;
292}
293
294/*
295 * sig_handler() - signal catching function.
296 * This function gets executed when a parnet sends a signal 'SIGINT'
subrata_modak4bb656a2009-02-26 12:02:09 +0000297 * to child to awake it from sleep.
plars865695b2001-08-27 22:15:12 +0000298 * This function just returns without doing anything.
299 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400300void sig_handler(void)
plars865695b2001-08-27 22:15:12 +0000301{
302}
303
304/*
305 * void
306 * cleanup() - performs all ONE TIME cleanup for this test at
307 * completion or premature exit.
308 */
Mike Frysingerc57fba52014-04-09 18:56:30 -0400309void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000310{
plars865695b2001-08-27 22:15:12 +0000311
Chris Dearmanec6edca2012-10-17 19:54:01 -0700312}