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 if clock_settime() changes the value for CLOCK_REALTIME,
9 * an absolute timer which would now have expired in the past
10 * will expire immediately (with no error).
11 * Test with a repeating absolute timer and set the clock forward past
12 * > 1 expirations of that timer.
13 *
14 * Steps:
15 * - get time T0
16 * - create/enable a timer to expire at T1 = T0 + TIMEROFFSET and repeat
17 *   at interval TIMERINTERVAL
18 * - set time forward to T1 + EXPECTEDOVERRUNS*TIMERINTERVAL
19 * - ensure that timer has expired with no error
20 * - ensure that the overrun count is EXPECTEDOVERRUNS
21 *   * Note:  The POSIX spec is unclear what exactly the overrun count
22 *            should be in this case.  It is only speculation that it ==
23 *            EXPECTEDOVERRUNS.  Either way passes.
24 *            Information based on discussions with:
25 *            benjamin.thery REMOVE-THIS AT bull DOT net
26 *            george REMOVE-THIS AT mvista DOT com
27 *
28 * signal SIGTOTEST is used.
29 */
30#include <stdio.h>
31#include <time.h>
32#include <signal.h>
33#include <unistd.h>
34#include <stdlib.h>
35#include "posixtest.h"
36#include "../helpers.h"
37
38#define TIMEROFFSET 3
39#define TIMERINTERVAL 5
40#define EXPECTEDOVERRUNS 3
41
42#define SHORTTIME 1
43
44#define SIGTOTEST SIGALRM
45
46int caught = 0;
47
48void handler(int signo)
49{
50	printf("Caught signal\n");
51	caught++;
52}
53
54int main(int argc, char *argv[])
55{
56	struct sigevent ev;
57	struct sigaction act;
58	struct timespec tpT0, tpclock, tpreset;
59	struct itimerspec its;
60	timer_t tid;
61	int flags = 0, overruns;
62
63	/*
64	 * set up sigevent for timer
65	 * set up sigaction to catch signal
66	 */
67	ev.sigev_notify = SIGEV_SIGNAL;
68	ev.sigev_signo = SIGTOTEST;
69
70	act.sa_handler=handler;
71	act.sa_flags=0;
72
73	if (sigemptyset(&act.sa_mask) != 0) {
74		perror("sigemptyset() was not successful\n");
75		return PTS_UNRESOLVED;
76	}
77
78	if (sigaction(SIGTOTEST, &act, 0) != 0) {
79		perror("sigaction() was not successful\n");
80		return PTS_UNRESOLVED;
81	}
82
83	if (clock_gettime(CLOCK_REALTIME, &tpT0) != 0) {
84		perror("clock_gettime() was not successful\n");
85		return PTS_UNRESOLVED;
86	}
87
88 	if (timer_create(CLOCK_REALTIME, &ev, &tid) != 0) {
89		perror("timer_create() did not return success\n");
90		return PTS_UNRESOLVED;
91	}
92
93	flags |= TIMER_ABSTIME;
94	its.it_interval.tv_sec = TIMERINTERVAL;
95	its.it_interval.tv_nsec = 0;
96	its.it_value.tv_sec = tpT0.tv_sec + TIMEROFFSET;
97	its.it_value.tv_nsec = tpT0.tv_nsec;
98	if (timer_settime(tid, flags, &its, NULL) != 0) {
99		perror("timer_settime() did not return success\n");
100		return PTS_UNRESOLVED;
101	}
102
103	tpclock.tv_sec = its.it_value.tv_sec + EXPECTEDOVERRUNS*TIMERINTERVAL;
104	tpclock.tv_nsec = its.it_value.tv_nsec;
105	getBeforeTime(&tpreset);
106	if (clock_settime(CLOCK_REALTIME, &tpclock) != 0) {
107		printf("clock_settime() was not successful\n");
108		return PTS_UNRESOLVED;
109	}
110
111	sleep(SHORTTIME);
112
113	overruns = timer_getoverrun(tid);
114	if (overruns == EXPECTEDOVERRUNS) {
115		printf("Overrun count == # of repeating timer expirys\n");
116	} else {
117		printf("Overrun count =%d, not # of repeating timer expirys\n",
118				overruns);
119	}
120
121	tpreset.tv_sec += SHORTTIME;
122	setBackTime(tpreset);
123
124	if (caught == 1) {
125		printf("Caught the correct number of signals\n");
126	} else {
127		printf("FAIL:  Caught %d signals, not 1\n", caught);
128		printf("Test FAILED\n");
129		return PTS_FAIL;
130	}
131
132	printf("Test PASSED\n");
133	return PTS_PASS;
134}
135