S390: Fix building with --disable-mutli-arch [BZ #31196]
[platform/upstream/glibc.git] / rt / tst-timer4.c
1 /* Tests for POSIX timer implementation.
2    Copyright (C) 2004-2024 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 <string.h>
23 #include <time.h>
24 #include <unistd.h>
25 #include <stdint.h>
26 #if _POSIX_THREADS && defined SA_SIGINFO
27 # include <pthread.h>
28
29 # ifndef TEST_CLOCK
30 #  define TEST_CLOCK            CLOCK_REALTIME
31 # endif
32
33 pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
34 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
35
36 timer_t timer_none, timer_sig1, timer_sig2, timer_thr1, timer_thr2;
37
38 int thr1_cnt, thr1_err;
39 union sigval thr1_sigval;
40 struct timespec thr1_ts;
41
42 static void
43 thr1 (union sigval sigval)
44 {
45   pthread_mutex_lock (&lock);
46   thr1_err = clock_gettime (TEST_CLOCK, &thr1_ts);
47   if (thr1_cnt >= 5)
48     {
49       struct itimerspec it = { };
50       thr1_err |= timer_settime (timer_thr1, 0, &it, NULL);
51     }
52   thr1_sigval = sigval;
53   ++thr1_cnt;
54   pthread_cond_signal (&cond);
55   pthread_mutex_unlock (&lock);
56 }
57
58 int thr2_cnt, thr2_err;
59 union sigval thr2_sigval;
60 size_t thr2_guardsize;
61 struct timespec thr2_ts;
62
63 static void
64 thr2 (union sigval sigval)
65 {
66   pthread_attr_t nattr;
67   int err = 0;
68   size_t guardsize = -1;
69   int ret = pthread_getattr_np (pthread_self (), &nattr);
70   if (ret)
71     {
72       errno = ret;
73       printf ("*** pthread_getattr_np failed: %m\n");
74       err = 1;
75     }
76   else
77     {
78       ret = pthread_attr_getguardsize (&nattr, &guardsize);
79       if (ret)
80         {
81           errno = ret;
82           printf ("*** pthread_attr_getguardsize failed: %m\n");
83           err = 1;
84         }
85       if (pthread_attr_destroy (&nattr) != 0)
86         {
87           puts ("*** pthread_attr_destroy failed");
88           err = 1;
89         }
90     }
91   pthread_mutex_lock (&lock);
92   thr2_err = clock_gettime (TEST_CLOCK, &thr2_ts) | err;
93   if (thr2_cnt >= 5)
94     {
95       struct itimerspec it = { };
96       thr2_err |= timer_settime (timer_thr2, 0, &it, NULL);
97     }
98   thr2_sigval = sigval;
99   ++thr2_cnt;
100   thr2_guardsize = guardsize;
101   pthread_cond_signal (&cond);
102   pthread_mutex_unlock (&lock);
103 }
104
105 volatile int sig1_cnt, sig1_err;
106 volatile union sigval sig1_sigval;
107 struct timespec sig1_ts;
108
109 static void
110 sig1_handler (int sig, siginfo_t *info, void *ctx)
111 {
112   int err = 0;
113   if (sig != SIGRTMIN) err |= 1 << 0;
114   if (info->si_signo != SIGRTMIN) err |= 1 << 1;
115   if (info->si_code != SI_TIMER) err |= 1 << 2;
116   if (clock_gettime (TEST_CLOCK, &sig1_ts) != 0)
117     err |= 1 << 3;
118   if (sig1_cnt >= 5)
119     {
120       struct itimerspec it = { };
121       if (timer_settime (timer_sig1, 0, &it, NULL))
122         err |= 1 << 4;
123     }
124   sig1_err |= err;
125   sig1_sigval = info->si_value;
126   ++sig1_cnt;
127 }
128
129 volatile int sig2_cnt, sig2_err;
130 volatile union sigval sig2_sigval;
131 struct timespec sig2_ts;
132
133 static void
134 sig2_handler (int sig, siginfo_t *info, void *ctx)
135 {
136   int err = 0;
137   if (sig != SIGRTMIN + 1) err |= 1 << 0;
138   if (info->si_signo != SIGRTMIN + 1) err |= 1 << 1;
139   if (info->si_code != SI_TIMER) err |= 1 << 2;
140   if (clock_gettime (TEST_CLOCK, &sig2_ts) != 0)
141     err |= 1 << 3;
142   if (sig2_cnt >= 5)
143     {
144       struct itimerspec it = { };
145       if (timer_settime (timer_sig2, 0, &it, NULL))
146         err |= 1 << 4;
147     }
148   sig2_err |= err;
149   sig2_sigval = info->si_value;
150   ++sig2_cnt;
151 }
152
153 /* Check if end is later or equal to start + nsec.  */
154 static int
155 check_ts (const char *name, const struct timespec *start,
156           const struct timespec *end, long msec)
157 {
158   struct timespec ts = *start;
159
160   ts.tv_sec += msec / 1000000;
161   ts.tv_nsec += (msec % 1000000) * 1000;
162   if (ts.tv_nsec >= 1000000000)
163     {
164       ++ts.tv_sec;
165       ts.tv_nsec -= 1000000000;
166     }
167   if (end->tv_sec < ts.tv_sec
168       || (end->tv_sec == ts.tv_sec && end->tv_nsec < ts.tv_nsec))
169     {
170       printf ("\
171 *** timer %s invoked too soon: %ld.%09jd instead of expected %ld.%09jd\n",
172               name, (long) end->tv_sec, (intmax_t) end->tv_nsec,
173               (long) ts.tv_sec, (intmax_t) ts.tv_nsec);
174       return 1;
175     }
176   else
177     return 0;
178 }
179
180 #define TEST_FUNCTION do_test ()
181 static int
182 do_test (void)
183 {
184   int result = 0;
185
186 #ifdef TEST_CLOCK_MISSING
187   const char *missing = TEST_CLOCK_MISSING (TEST_CLOCK);
188   if (missing != NULL)
189     {
190       printf ("%s missing, skipping test\n", missing);
191       return 0;
192     }
193 #endif
194
195   struct timespec ts;
196   if (clock_gettime (TEST_CLOCK, &ts) != 0)
197     {
198       printf ("*** clock_gettime failed: %m\n");
199       result = 1;
200     }
201   else
202     printf ("clock_gettime returned timespec = { %ld, %jd }\n",
203             (long) ts.tv_sec, (intmax_t) ts.tv_nsec);
204
205   if (clock_getres (TEST_CLOCK, &ts) != 0)
206     {
207       printf ("*** clock_getres failed: %m\n");
208       result = 1;
209     }
210   else
211     printf ("clock_getres returned timespec = { %ld, %jd }\n",
212             (long) ts.tv_sec, (intmax_t) ts.tv_nsec);
213
214   struct sigevent ev;
215   memset (&ev, 0x11, sizeof (ev));
216   ev.sigev_notify = SIGEV_NONE;
217   if (timer_create (TEST_CLOCK, &ev, &timer_none) != 0)
218     {
219       printf ("*** timer_create for timer_none failed: %m\n");
220       return 1;
221     }
222
223   struct sigaction sa = { .sa_sigaction = sig1_handler,
224                           .sa_flags = SA_SIGINFO };
225   sigemptyset (&sa.sa_mask);
226   sigaction (SIGRTMIN, &sa, NULL);
227   sa.sa_sigaction = sig2_handler;
228   sigaction (SIGRTMIN + 1, &sa, NULL);
229
230   memset (&ev, 0x22, sizeof (ev));
231   ev.sigev_notify = SIGEV_SIGNAL;
232   ev.sigev_signo = SIGRTMIN;
233   ev.sigev_value.sival_ptr = &ev;
234   if (timer_create (TEST_CLOCK, &ev, &timer_sig1) != 0)
235     {
236       printf ("*** timer_create for timer_sig1 failed: %m\n");
237       return 1;
238     }
239
240   memset (&ev, 0x33, sizeof (ev));
241   ev.sigev_notify = SIGEV_SIGNAL;
242   ev.sigev_signo = SIGRTMIN + 1;
243   ev.sigev_value.sival_int = 163;
244   if (timer_create (TEST_CLOCK, &ev, &timer_sig2) != 0)
245     {
246       printf ("*** timer_create for timer_sig2 failed: %m\n");
247       return 1;
248     }
249
250   memset (&ev, 0x44, sizeof (ev));
251   ev.sigev_notify = SIGEV_THREAD;
252   ev.sigev_notify_function = thr1;
253   ev.sigev_notify_attributes = NULL;
254   ev.sigev_value.sival_ptr = &ev;
255   if (timer_create (TEST_CLOCK, &ev, &timer_thr1) != 0)
256     {
257       printf ("*** timer_create for timer_thr1 failed: %m\n");
258       return 1;
259     }
260
261   pthread_attr_t nattr;
262   if (pthread_attr_init (&nattr)
263       || pthread_attr_setguardsize (&nattr, 0))
264     {
265       puts ("*** pthread_attr_t setup failed");
266       result = 1;
267     }
268
269   memset (&ev, 0x55, sizeof (ev));
270   ev.sigev_notify = SIGEV_THREAD;
271   ev.sigev_notify_function = thr2;
272   ev.sigev_notify_attributes = &nattr;
273   ev.sigev_value.sival_int = 111;
274   if (timer_create (TEST_CLOCK, &ev, &timer_thr2) != 0)
275     {
276       printf ("*** timer_create for timer_thr2 failed: %m\n");
277       return 1;
278     }
279
280   int ret = timer_getoverrun (timer_thr1);
281   if (ret != 0)
282     {
283       if (ret == -1)
284         printf ("*** timer_getoverrun failed: %m\n");
285       else
286         printf ("*** timer_getoverrun returned %d != 0\n", ret);
287       result = 1;
288     }
289
290   struct itimerspec it;
291   it.it_value.tv_sec = 0;
292   it.it_value.tv_nsec = -26;
293   it.it_interval.tv_sec = 0;
294   it.it_interval.tv_nsec = 0;
295   if (timer_settime (timer_sig1, 0, &it, NULL) == 0)
296     {
297       puts ("*** timer_settime with negative tv_nsec unexpectedly succeeded");
298       result = 1;
299     }
300   else if (errno != EINVAL)
301     {
302       printf ("*** timer_settime with negative tv_nsec did not fail with "
303               "EINVAL: %m\n");
304       result = 1;
305     }
306
307   it.it_value.tv_nsec = 100000;
308   it.it_interval.tv_nsec = 1000000000;
309   if (timer_settime (timer_sig2, 0, &it, NULL) == 0)
310     {
311       puts ("\
312 *** timer_settime with tv_nsec 1000000000 unexpectedly succeeded");
313       result = 1;
314     }
315   else if (errno != EINVAL)
316     {
317       printf ("*** timer_settime with tv_nsec 1000000000 did not fail with "
318               "EINVAL: %m\n");
319       result = 1;
320     }
321
322 #if 0
323   it.it_value.tv_nsec = 0;
324   it.it_interval.tv_nsec = -26;
325   if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
326     {
327       printf ("\
328 !!! timer_settime with it_value 0 it_interval invalid failed: %m\n");
329       /* FIXME: is this mandated by POSIX?
330       result = 1; */
331     }
332
333   it.it_interval.tv_nsec = 3000000000;
334   if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
335     {
336       printf ("\
337 !!! timer_settime with it_value 0 it_interval invalid failed: %m\n");
338       /* FIXME: is this mandated by POSIX?
339       result = 1; */
340     }
341 #endif
342
343   struct timespec startts;
344   if (clock_gettime (TEST_CLOCK, &startts) != 0)
345     {
346       printf ("*** clock_gettime failed: %m\n");
347       result = 1;
348     }
349
350   it.it_value.tv_nsec = 100000000;
351   it.it_interval.tv_nsec = 0;
352   if (timer_settime (timer_none, 0, &it, NULL) != 0)
353     {
354       printf ("*** timer_settime timer_none failed: %m\n");
355       result = 1;
356     }
357
358   it.it_value.tv_nsec = 200000000;
359   if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
360     {
361       printf ("*** timer_settime timer_thr1 failed: %m\n");
362       result = 1;
363     }
364
365   it.it_value.tv_nsec = 300000000;
366   if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
367     {
368       printf ("*** timer_settime timer_thr2 failed: %m\n");
369       result = 1;
370     }
371
372   it.it_value.tv_nsec = 400000000;
373   if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
374     {
375       printf ("*** timer_settime timer_sig1 failed: %m\n");
376       result = 1;
377     }
378
379   it.it_value.tv_nsec = 500000000;
380   if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
381     {
382       printf ("*** timer_settime timer_sig2 failed: %m\n");
383       result = 1;
384     }
385
386   pthread_mutex_lock (&lock);
387   while (thr1_cnt == 0 || thr2_cnt == 0)
388     pthread_cond_wait (&cond, &lock);
389   pthread_mutex_unlock (&lock);
390
391   while (sig1_cnt == 0 || sig2_cnt == 0)
392     {
393       ts.tv_sec = 0;
394       ts.tv_nsec = 100000000;
395       nanosleep (&ts, NULL);
396     }
397
398   pthread_mutex_lock (&lock);
399
400   if (thr1_cnt != 1)
401     {
402       printf ("*** thr1 not called exactly once, but %d times\n", thr1_cnt);
403       result = 1;
404     }
405   else if (thr1_err)
406     {
407       puts ("*** an error occurred in thr1");
408       result = 1;
409     }
410   else if (thr1_sigval.sival_ptr != &ev)
411     {
412       printf ("*** thr1_sigval.sival_ptr %p != %p\n",
413               thr1_sigval.sival_ptr, &ev);
414       result = 1;
415     }
416   else if (check_ts ("thr1", &startts, &thr1_ts, 200000))
417     result = 1;
418
419   if (thr2_cnt != 1)
420     {
421       printf ("*** thr2 not called exactly once, but %d times\n", thr2_cnt);
422       result = 1;
423     }
424   else if (thr2_err)
425     {
426       puts ("*** an error occurred in thr2");
427       result = 1;
428     }
429   else if (thr2_sigval.sival_int != 111)
430     {
431       printf ("*** thr2_sigval.sival_ptr %d != 111\n", thr2_sigval.sival_int);
432       result = 1;
433     }
434   else if (check_ts ("thr2", &startts, &thr2_ts, 300000))
435     result = 1;
436   else if (thr2_guardsize != 0)
437     {
438       printf ("*** thr2 guardsize %zd != 0\n", thr2_guardsize);
439       result = 1;
440     }
441
442   pthread_mutex_unlock (&lock);
443
444   if (sig1_cnt != 1)
445     {
446       printf ("*** sig1 not called exactly once, but %d times\n", sig1_cnt);
447       result = 1;
448     }
449   else if (sig1_err)
450     {
451       printf ("*** errors occurred in sig1 handler %x\n", sig1_err);
452       result = 1;
453     }
454   else if (sig1_sigval.sival_ptr != &ev)
455     {
456       printf ("*** sig1_sigval.sival_ptr %p != %p\n",
457               sig1_sigval.sival_ptr, &ev);
458       result = 1;
459     }
460   else if (check_ts ("sig1", &startts, &sig1_ts, 400000))
461     result = 1;
462
463   if (sig2_cnt != 1)
464     {
465       printf ("*** sig2 not called exactly once, but %d times\n", sig2_cnt);
466       result = 1;
467     }
468   else if (sig2_err)
469     {
470       printf ("*** errors occurred in sig2 handler %x\n", sig2_err);
471       result = 1;
472     }
473   else if (sig2_sigval.sival_int != 163)
474     {
475       printf ("*** sig2_sigval.sival_ptr %d != 163\n", sig2_sigval.sival_int);
476       result = 1;
477     }
478   else if (check_ts ("sig2", &startts, &sig2_ts, 500000))
479     result = 1;
480
481   if (timer_gettime (timer_none, &it) != 0)
482     {
483       printf ("*** timer_gettime timer_none failed: %m\n");
484       result = 1;
485     }
486   else if (it.it_value.tv_sec || it.it_value.tv_nsec
487            || it.it_interval.tv_sec || it.it_interval.tv_nsec)
488     {
489       printf ("\
490 *** timer_gettime timer_none returned { %ld.%09jd, %ld.%09jd }\n",
491               (long) it.it_value.tv_sec, (intmax_t) it.it_value.tv_nsec,
492               (long) it.it_interval.tv_sec, (intmax_t) it.it_interval.tv_nsec);
493       result = 1;
494     }
495
496   if (clock_gettime (TEST_CLOCK, &startts) != 0)
497     {
498       printf ("*** clock_gettime failed: %m\n");
499       result = 1;
500     }
501
502   it.it_value.tv_sec = 1;
503   it.it_value.tv_nsec = 0;
504   it.it_interval.tv_sec = 0;
505   it.it_interval.tv_nsec = 100000000;
506   if (timer_settime (timer_none, 0, &it, NULL) != 0)
507     {
508       printf ("*** timer_settime timer_none failed: %m\n");
509       result = 1;
510     }
511
512   it.it_value.tv_nsec = 100000000;
513   it.it_interval.tv_nsec = 200000000;
514   if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
515     {
516       printf ("*** timer_settime timer_thr1 failed: %m\n");
517       result = 1;
518     }
519
520   it.it_value.tv_nsec = 200000000;
521   it.it_interval.tv_nsec = 300000000;
522   if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
523     {
524       printf ("*** timer_settime timer_thr2 failed: %m\n");
525       result = 1;
526     }
527
528   it.it_value.tv_nsec = 300000000;
529   it.it_interval.tv_nsec = 400000000;
530   if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
531     {
532       printf ("*** timer_settime timer_sig1 failed: %m\n");
533       result = 1;
534     }
535
536   it.it_value.tv_nsec = 400000000;
537   it.it_interval.tv_nsec = 500000000;
538   if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
539     {
540       printf ("*** timer_settime timer_sig2 failed: %m\n");
541       result = 1;
542     }
543
544   pthread_mutex_lock (&lock);
545   while (thr1_cnt < 6 || thr2_cnt < 6)
546     pthread_cond_wait (&cond, &lock);
547   pthread_mutex_unlock (&lock);
548
549   while (sig1_cnt < 6 || sig2_cnt < 6)
550     {
551       ts.tv_sec = 0;
552       ts.tv_nsec = 100000000;
553       nanosleep (&ts, NULL);
554     }
555
556   pthread_mutex_lock (&lock);
557
558   if (thr1_err)
559     {
560       puts ("*** an error occurred in thr1");
561       result = 1;
562     }
563   else if (check_ts ("thr1", &startts, &thr1_ts, 1100000 + 4 * 200000))
564     result = 1;
565
566   if (thr2_err)
567     {
568       puts ("*** an error occurred in thr2");
569       result = 1;
570     }
571   else if (check_ts ("thr2", &startts, &thr2_ts, 1200000 + 4 * 300000))
572     result = 1;
573   else if (thr2_guardsize != 0)
574     {
575       printf ("*** thr2 guardsize %zd != 0\n", thr2_guardsize);
576       result = 1;
577     }
578
579   pthread_mutex_unlock (&lock);
580
581   if (sig1_err)
582     {
583       printf ("*** errors occurred in sig1 handler %x\n", sig1_err);
584       result = 1;
585     }
586   else if (check_ts ("sig1", &startts, &sig1_ts, 1300000 + 4 * 400000))
587     result = 1;
588
589   if (sig2_err)
590     {
591       printf ("*** errors occurred in sig2 handler %x\n", sig2_err);
592       result = 1;
593     }
594   else if (check_ts ("sig2", &startts, &sig2_ts, 1400000 + 4 * 500000))
595     result = 1;
596
597   if (timer_gettime (timer_none, &it) != 0)
598     {
599       printf ("*** timer_gettime timer_none failed: %m\n");
600       result = 1;
601     }
602   else if (it.it_interval.tv_sec || it.it_interval.tv_nsec != 100000000)
603     {
604       printf ("\
605 !!! second timer_gettime timer_none returned it_interval %ld.%09jd\n",
606               (long) it.it_interval.tv_sec, (intmax_t) it.it_interval.tv_nsec);
607       /* FIXME: For now disabled.
608       result = 1; */
609     }
610
611   if (timer_delete (timer_none) != 0)
612     {
613       printf ("*** timer_delete for timer_none failed: %m\n");
614       result = 1;
615     }
616
617   if (timer_delete (timer_sig1) != 0)
618     {
619       printf ("*** timer_delete for timer_sig1 failed: %m\n");
620       result = 1;
621     }
622
623   if (timer_delete (timer_sig2) != 0)
624     {
625       printf ("*** timer_delete for timer_sig2 failed: %m\n");
626       result = 1;
627     }
628
629   if (timer_delete (timer_thr1) != 0)
630     {
631       printf ("*** timer_delete for timer_thr1 failed: %m\n");
632       result = 1;
633     }
634
635   if (timer_delete (timer_thr2) != 0)
636     {
637       printf ("*** timer_delete for timer_thr2 failed: %m\n");
638       result = 1;
639     }
640   return result;
641 }
642
643 #elif defined TEST_CLOCK_MISSING
644 /* This just ensures that any functions called in TEST_CLOCK_MISSING
645    are not diagnosed as unused.  */
646 # define TEST_FUNCTION (TEST_CLOCK_MISSING (TEST_CLOCK), 0)
647 #else
648 # define TEST_FUNCTION 0
649 #endif
650
651 #include "../test-skeleton.c"