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