1 | /* Tests for POSIX timer implementation. |
2 | Copyright (C) 2000-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public License as |
7 | published by the Free Software Foundation; either version 2.1 of the |
8 | License, or (at your option) any later version. |
9 | |
10 | The GNU C Library 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 the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; see the file COPYING.LIB. If |
17 | not, see <https://www.gnu.org/licenses/>. */ |
18 | |
19 | #include <errno.h> |
20 | #include <signal.h> |
21 | #include <stdio.h> |
22 | #include <time.h> |
23 | #include <unistd.h> |
24 | #include <stdlib.h> |
25 | #include <stdint.h> |
26 | |
27 | |
28 | static void |
29 | notify_func1 (union sigval sigval) |
30 | { |
31 | puts (s: "notify_func1" ); |
32 | } |
33 | |
34 | |
35 | static void |
36 | notify_func2 (union sigval sigval) |
37 | { |
38 | puts (s: "notify_func2" ); |
39 | } |
40 | |
41 | |
42 | static void |
43 | signal_func (int sig) |
44 | { |
45 | static const char text[] = "signal_func\n" ; |
46 | signal (sig: sig, handler: signal_func); |
47 | write (STDOUT_FILENO, text, sizeof text - 1); |
48 | } |
49 | |
50 | static void |
51 | intr_sleep (int sec) |
52 | { |
53 | struct timespec ts; |
54 | |
55 | ts.tv_sec = sec; |
56 | ts.tv_nsec = 0; |
57 | |
58 | while (nanosleep (requested_time: &ts, remaining: &ts) == -1 && errno == EINTR) |
59 | ; |
60 | } |
61 | |
62 | #define ZSIGALRM 14 |
63 | |
64 | |
65 | int |
66 | main (void) |
67 | { |
68 | struct timespec ts; |
69 | timer_t timer_sig, timer_thr1, timer_thr2; |
70 | int retval; |
71 | struct sigevent sigev1 = |
72 | { |
73 | .sigev_notify = SIGEV_SIGNAL, |
74 | .sigev_signo = ZSIGALRM |
75 | }; |
76 | struct sigevent sigev2; |
77 | struct itimerspec itimer1 = { { 0, 200000000 }, { 0, 200000000 } }; |
78 | struct itimerspec itimer2 = { { 0, 100000000 }, { 0, 500000000 } }; |
79 | struct itimerspec itimer3 = { { 0, 150000000 }, { 0, 300000000 } }; |
80 | struct itimerspec old; |
81 | |
82 | retval = clock_gettime (CLOCK_REALTIME, tp: &ts); |
83 | |
84 | sigev2.sigev_notify = SIGEV_THREAD; |
85 | sigev2.sigev_notify_function = notify_func1; |
86 | sigev2.sigev_notify_attributes = NULL; |
87 | /* It is unnecessary to do the following but to set a good example |
88 | we do it anyhow. */ |
89 | sigev2.sigev_value.sival_ptr = NULL; |
90 | |
91 | setvbuf (stdout, buf: 0, _IOLBF, n: 0); |
92 | |
93 | printf (format: "clock_gettime returned %d, timespec = { %jd, %jd }\n" , |
94 | retval, (intmax_t) ts.tv_sec, (intmax_t) ts.tv_nsec); |
95 | |
96 | retval = clock_getres (CLOCK_REALTIME, res: &ts); |
97 | |
98 | printf (format: "clock_getres returned %d, timespec = { %jd, %jd }\n" , |
99 | retval, (intmax_t) ts.tv_sec, (intmax_t) ts.tv_nsec); |
100 | |
101 | if (timer_create (CLOCK_REALTIME, evp: &sigev1, timerid: &timer_sig) != 0) |
102 | { |
103 | printf (format: "timer_create for timer_sig failed: %m\n" ); |
104 | exit (1); |
105 | } |
106 | if (timer_create (CLOCK_REALTIME, evp: &sigev2, timerid: &timer_thr1) != 0) |
107 | { |
108 | printf (format: "timer_create for timer_thr1 failed: %m\n" ); |
109 | exit (1); |
110 | } |
111 | sigev2.sigev_notify_function = notify_func2; |
112 | if (timer_create (CLOCK_REALTIME, evp: &sigev2, timerid: &timer_thr2) != 0) |
113 | { |
114 | printf (format: "timer_create for timer_thr2 failed: %m\n" ); |
115 | exit (1); |
116 | } |
117 | |
118 | if (timer_settime (timerid: timer_thr1, flags: 0, value: &itimer2, ovalue: &old) != 0) |
119 | { |
120 | printf (format: "timer_settime for timer_thr1 failed: %m\n" ); |
121 | exit (1); |
122 | } |
123 | if (timer_settime (timerid: timer_thr2, flags: 0, value: &itimer3, ovalue: &old) != 0) |
124 | { |
125 | printf (format: "timer_settime for timer_thr2 failed: %m\n" ); |
126 | exit (1); |
127 | } |
128 | |
129 | signal (ZSIGALRM, handler: signal_func); |
130 | |
131 | if (timer_settime (timerid: timer_sig, flags: 0, value: &itimer1, ovalue: &old) != 0) |
132 | { |
133 | printf (format: "timer_settime for timer_sig failed: %m\n" ); |
134 | exit (1); |
135 | } |
136 | |
137 | intr_sleep (sec: 3); |
138 | |
139 | if (timer_delete (timerid: timer_sig) != 0) |
140 | { |
141 | printf (format: "timer_delete for timer_sig failed: %m\n" ); |
142 | exit (1); |
143 | } |
144 | if (timer_delete (timerid: timer_thr1) != 0) |
145 | { |
146 | printf (format: "timer_delete for timer_thr1 failed: %m\n" ); |
147 | exit (1); |
148 | } |
149 | |
150 | intr_sleep (sec: 3); |
151 | |
152 | if (timer_delete (timerid: timer_thr2) != 0) |
153 | { |
154 | printf (format: "timer_delete for timer_thr2 failed: %m\n" ); |
155 | exit (1); |
156 | } |
157 | |
158 | return 0; |
159 | } |
160 | |