1/*
2 * Copyright (c) 2002, Intel Corporation. All rights reserved.
3 * Created by:  julie.n.fleischer REMOVE-THIS AT intel DOT com
4 * This file is licensed under the GPL license.  For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7 *
8 * Test that clock_settime() does not affect clock_nanosleep()
9 * relative timers expiration times.
10 *
11 * Steps:
12 * - get time T0
13 * - in child:  set clock_nanosleep() to sleep for SLEEPSEC seconds
14 * - in parent:  sleep SMALLTIME (< SLEEPSEC)
15 * - in parent:  set time back to T0
16 * - in child:  ensure time when clock_nanosleep() expires is within
17 *   ACCEPTABLEDELTA of T0+(SLEEPSEC-SMALLTIME)
18 */
19#include <stdio.h>
20#include <time.h>
21#include <signal.h>
22#include <unistd.h>
23#include <sys/wait.h>
24#include "posixtest.h"
25#include "helpers.h"
26
27#define SLEEPSEC 5
28#define SMALLTIME 2
29#define ACCEPTABLEDELTA 1
30
31#define CHILDPASS 1
32#define CHILDFAIL 0
33
34int main(int argc, char *argv[])
35{
36	struct timespec tsT0, tssleep;
37	int pid;
38
39	/* Check that we're root...can't call clock_settime with CLOCK_REALTIME otherwise */
40	if(getuid() != 0)
41	{
42		printf("Run this test as ROOT, not as a Regular User\n");
43		return PTS_UNTESTED;
44	}
45
46	if (clock_gettime(CLOCK_REALTIME, &tsT0) != 0) {
47		perror("clock_gettime() did not return success\n");
48		return PTS_UNRESOLVED;
49	}
50
51	if ((pid = fork()) == 0) {
52		/* child here */
53		struct timespec tsend;
54		int expectedsec;
55
56		tssleep.tv_sec = SLEEPSEC;
57		tssleep.tv_nsec = 0;
58
59		if (clock_nanosleep(CLOCK_REALTIME, 0, &tssleep, NULL) != 0) {
60			printf("clock_nanosleep() did not return success\n");
61			return CHILDFAIL;
62		}
63
64		if (clock_gettime(CLOCK_REALTIME, &tsend) != 0) {
65			perror("clock_gettime() did not return success\n");
66			return CHILDFAIL;
67		}
68
69		expectedsec = tsT0.tv_sec + (SLEEPSEC-SMALLTIME);
70
71		if (tsend.tv_sec >= expectedsec) {
72			if ( (tsend.tv_sec-expectedsec) <= ACCEPTABLEDELTA) {
73				return CHILDPASS;
74			} else {
75				printf("Ended too late.  %d >> %d\n",
76						(int) tsend.tv_sec,
77						(int) expectedsec);
78				return CHILDFAIL;
79			}
80		} else {
81			printf("Did not sleep for long enough %d < %d\n",
82					(int) tsend.tv_sec, (int) expectedsec);
83			return CHILDFAIL;
84		}
85
86		return CHILDFAIL;
87	} else {
88		/* parent here */
89		int i;
90		struct timespec tsreset;
91
92		sleep(SMALLTIME);
93
94		if (clock_settime(CLOCK_REALTIME, &tsT0) != 0) {
95			printf("clock_settime() did not return success\n");
96			return PTS_UNRESOLVED;
97		}
98
99		if (wait(&i) == -1) {
100			perror("Error waiting for child to exit\n");
101			return PTS_UNRESOLVED;
102		}
103
104		getBeforeTime(&tsreset); // get current time
105		tsreset.tv_sec += SMALLTIME;
106		setBackTime(tsreset);
107
108		if (WIFEXITED(i) && WEXITSTATUS(i)) {
109			printf("Test PASSED\n");
110			return PTS_PASS;
111		} else {
112			printf("Test FAILED\n");
113			return PTS_FAIL;
114		}
115	}
116
117	return PTS_UNRESOLVED;
118}
119