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