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