1 /*
2  * Copyright (c) 2018 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <ztest.h>
8 #include <time.h>
9 #include <unistd.h>
10 
11 #define SECS_TO_SLEEP 2
12 #define DURATION_SECS 1
13 #define DURATION_NSECS 0
14 #define PERIOD_SECS 0
15 #define PERIOD_NSECS 100000000
16 
17 static int exp_count;
18 
handler(union sigval val)19 void handler(union sigval val)
20 {
21 	printk("Handler Signal value :%d for %d times\n", val.sival_int,
22 	       ++exp_count);
23 }
24 
test_posix_timer(void)25 void test_posix_timer(void)
26 {
27 	int ret;
28 	struct sigevent sig = { 0 };
29 	timer_t timerid;
30 	struct itimerspec value, ovalue;
31 	struct timespec ts, te;
32 	int64_t nsecs_elapsed, secs_elapsed, total_secs_timer;
33 
34 	sig.sigev_notify = SIGEV_SIGNAL;
35 	sig.sigev_notify_function = handler;
36 	sig.sigev_value.sival_int = 20;
37 
38 	printk("POSIX timer test\n");
39 	ret = timer_create(CLOCK_MONOTONIC, &sig, &timerid);
40 
41 	/*TESTPOINT: Check if timer is created successfully*/
42 	zassert_false(ret, "POSIX timer create failed");
43 
44 	value.it_value.tv_sec = DURATION_SECS;
45 	value.it_value.tv_nsec = DURATION_NSECS;
46 	value.it_interval.tv_sec = PERIOD_SECS;
47 	value.it_interval.tv_nsec = PERIOD_NSECS;
48 	ret = timer_settime(timerid, 0, &value, &ovalue);
49 	usleep(100 * USEC_PER_MSEC);
50 	ret = timer_gettime(timerid, &value);
51 	zassert_false(ret, "Failed to get time to expire.");
52 
53 	if (ret == 0) {
54 		printk("Timer fires every %d secs and  %d nsecs\n",
55 		       (int) value.it_interval.tv_sec,
56 		       (int) value.it_interval.tv_nsec);
57 		printk("Time remaining to fire %d secs and  %d nsecs\n",
58 		       (int) value.it_value.tv_sec,
59 		       (int) value.it_value.tv_nsec);
60 	}
61 
62 	clock_gettime(CLOCK_MONOTONIC, &ts);
63 
64 	/*TESTPOINT: Check if timer has started successfully*/
65 	zassert_false(ret, "POSIX timer failed to start");
66 
67 	sleep(SECS_TO_SLEEP);
68 
69 	clock_gettime(CLOCK_MONOTONIC, &te);
70 	timer_delete(timerid);
71 
72 	if (te.tv_nsec >= ts.tv_nsec) {
73 		secs_elapsed = te.tv_sec - ts.tv_sec;
74 		nsecs_elapsed = te.tv_nsec - ts.tv_nsec;
75 	} else {
76 		nsecs_elapsed = NSEC_PER_SEC + te.tv_nsec - ts.tv_nsec;
77 		secs_elapsed = (te.tv_sec - ts.tv_sec - 1);
78 	}
79 
80 	total_secs_timer = (value.it_value.tv_sec * NSEC_PER_SEC +
81 			    value.it_value.tv_nsec + (uint64_t) exp_count *
82 			    (value.it_interval.tv_sec * NSEC_PER_SEC +
83 			     value.it_interval.tv_nsec)) / NSEC_PER_SEC;
84 
85 	/*TESTPOINT: Check if POSIX timer test passed*/
86 	zassert_equal(total_secs_timer, secs_elapsed,
87 		      "POSIX timer test has failed");
88 }
89