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 * Note:  This test is not based on the POSIX spec, but is a speculation
9 * about behavior for an assertion where the POSIX spec does not make a
10 * statement about the behavior in either case.
11 *
12 * Test that if clock_settime() changes the value for CLOCK_REALTIME,
13 * a repeating absolute timer uses this new value for expires.
14 *
15 * Document whether expirations which have already happened happen again or
16 * not.
17 *
18 * Steps:
19 * - get time T0
20 * - create/enable a timer to expire at T1 = T0 + TIMERINTERVAL and repeat
21 *   at interval TIMERINTERVAL
22 * - sleep for time TIMERINTERVAL+ADDITIONALEXPIRES*TIMERINTERAL (must do
23 *   in a loop to catch all expires)
24 * - set time backward to T0
25 * - sleep for time TIMERINTERVAL and ensure timer expires (2X)
26 *
27 * signal SIGTOTEST is used.
28 */
29#include <stdio.h>
30#include <time.h>
31#include <signal.h>
32#include <unistd.h>
33#include <stdlib.h>
34#include "posixtest.h"
35#include "../helpers.h"
36
37#define TIMERINTERVAL 5
38#define ADDITIONALEXPIRES 2
39
40#define ADDITIONALDELTA 1
41
42#define SIGTOTEST SIGALRM
43
44int caught = 0;
45
46void handler(int signo)
47{
48	printf("Caught signal\n");
49	caught++;
50}
51
52int main(int argc, char *argv[])
53{
54	struct sigevent ev;
55	struct sigaction act;
56	struct timespec tpT0, tpclock, tsreset;
57	struct itimerspec its;
58	timer_t tid;
59	int i, flags = 0, nocaught = 0;
60
61	/*
62	 * set up sigevent for timer
63	 * set up sigaction to catch signal
64	 */
65	ev.sigev_notify = SIGEV_SIGNAL;
66	ev.sigev_signo = SIGTOTEST;
67
68	act.sa_handler=handler;
69	act.sa_flags=0;
70
71	if (sigemptyset(&act.sa_mask) != 0) {
72		perror("sigemptyset() was not successful\n");
73		return PTS_UNRESOLVED;
74	}
75
76	if (sigaction(SIGTOTEST, &act, 0) != 0) {
77		perror("sigaction() was not successful\n");
78		return PTS_UNRESOLVED;
79	}
80
81	if (clock_gettime(CLOCK_REALTIME, &tpT0) != 0) {
82		perror("clock_gettime() was not successful\n");
83		return PTS_UNRESOLVED;
84	}
85
86 	if (timer_create(CLOCK_REALTIME, &ev, &tid) != 0) {
87		perror("timer_create() did not return success\n");
88		return PTS_UNRESOLVED;
89	}
90
91	flags |= TIMER_ABSTIME;
92	its.it_interval.tv_sec = TIMERINTERVAL;
93	its.it_interval.tv_nsec = 0;
94	its.it_value.tv_sec = tpT0.tv_sec + TIMERINTERVAL;
95	its.it_value.tv_nsec = tpT0.tv_nsec;
96	if (timer_settime(tid, flags, &its, NULL) != 0) {
97		perror("timer_settime() did not return success\n");
98		return PTS_UNRESOLVED;
99	}
100
101	sleep(TIMERINTERVAL);
102	for (i = 0; i < ADDITIONALEXPIRES; i++) {
103		sleep(TIMERINTERVAL);
104	}
105
106	tpclock.tv_sec = tpT0.tv_sec;
107	tpclock.tv_nsec = tpT0.tv_nsec;
108	getBeforeTime(&tsreset);
109	if (clock_settime(CLOCK_REALTIME, &tpclock) != 0) {
110		printf("clock_settime() was not successful\n");
111		return PTS_UNRESOLVED;
112	}
113
114	caught = 0;
115
116	sleep(TIMERINTERVAL+ADDITIONALDELTA);
117
118	if (caught == 1) {
119		printf("Caught the first signal\n");
120	} else {
121		printf("FAIL:  Didn't catch timer after TIMERINTERVAL.\n");
122		nocaught = 1;
123	}
124
125	sleep(TIMERINTERVAL+ADDITIONALDELTA);
126
127	if (caught >= 2) {
128		printf("Caught another signal\n");
129	} else {
130		printf("Caught %d < 2 signals\n", caught);
131		nocaught = 1;
132	}
133
134	if (nocaught) {
135		printf("Implementation does not repeat signals on clock reset\n");
136	} else {
137		printf("Implementation does repeat signals on clock reset\n");
138	}
139
140	// If we finish, pass
141	tsreset.tv_sec += 2*(TIMERINTERVAL+ADDITIONALDELTA);
142	setBackTime(tsreset);
143	return PTS_PASS;
144}
145