Update.
[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 <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 ("timer %s invoked too soon: %ld.%09ld instead of expected %ld.%09ld\n",
167               name, (long) end->tv_sec, end->tv_nsec,
168               (long) ts.tv_sec, ts.tv_nsec);
169       return 1;
170     }
171   else
172     return 0;
173 }
174
175 #define TIMEOUT 15
176 #define TEST_FUNCTION do_test ()
177 static int
178 do_test (void)
179 {
180   int result = 0;
181
182   struct timespec ts;
183   if (clock_gettime (CLOCK_REALTIME, &ts) != 0)
184     {
185       printf ("clock_gettime failed: %m\n");
186       result = 1;
187     }
188   else
189     printf ("clock_gettime returned timespec = { %ld, %ld }\n",
190             (long) ts.tv_sec, ts.tv_nsec);
191
192   if (clock_getres (CLOCK_REALTIME, &ts) != 0)
193     {
194       printf ("clock_getres failed: %m\n");
195       result = 1;
196     }
197   else
198     printf ("clock_getres returned timespec = { %ld, %ld }\n",
199             (long) ts.tv_sec, ts.tv_nsec);
200
201   struct sigevent ev;
202   memset (&ev, 0x11, sizeof (ev));
203   ev.sigev_notify = SIGEV_NONE;
204   if (timer_create (CLOCK_REALTIME, &ev, &timer_none) != 0)
205     {
206       printf ("timer_create for timer_none failed: %m\n");
207       result = 1;
208     }
209
210   struct sigaction sa = { .sa_sigaction = sig1_handler,
211                           .sa_flags = SA_SIGINFO };
212   sigemptyset (&sa.sa_mask);
213   sigaction (SIGRTMIN, &sa, NULL);
214   sa.sa_sigaction = sig2_handler;
215   sigaction (SIGRTMIN + 1, &sa, NULL);
216
217   memset (&ev, 0x22, sizeof (ev));
218   ev.sigev_notify = SIGEV_SIGNAL;
219   ev.sigev_signo = SIGRTMIN;
220   ev.sigev_value.sival_ptr = &ev;
221   if (timer_create (CLOCK_REALTIME, &ev, &timer_sig1) != 0)
222     {
223       printf ("timer_create for timer_sig1 failed: %m\n");
224       result = 1;
225     }
226
227   memset (&ev, 0x33, sizeof (ev));
228   ev.sigev_notify = SIGEV_SIGNAL;
229   ev.sigev_signo = SIGRTMIN + 1;
230   ev.sigev_value.sival_int = 163;
231   if (timer_create (CLOCK_REALTIME, &ev, &timer_sig2) != 0)
232     {
233       printf ("timer_create for timer_sig2 failed: %m\n");
234       result = 1;
235     }
236
237   memset (&ev, 0x44, sizeof (ev));
238   ev.sigev_notify = SIGEV_THREAD;
239   ev.sigev_notify_function = thr1;
240   ev.sigev_notify_attributes = NULL;
241   ev.sigev_value.sival_ptr = &ev;
242   if (timer_create (CLOCK_REALTIME, &ev, &timer_thr1) != 0)
243     {
244       printf ("timer_create for timer_thr1 failed: %m\n");
245       result = 1;
246     }
247
248   pthread_attr_t nattr;
249   if (pthread_attr_init (&nattr)
250       || pthread_attr_setguardsize (&nattr, 0))
251     {
252       puts ("pthread_attr_t setup failed");
253       result = 1;
254     }
255
256   memset (&ev, 0x55, sizeof (ev));
257   ev.sigev_notify = SIGEV_THREAD;
258   ev.sigev_notify_function = thr2;
259   ev.sigev_notify_attributes = &nattr;
260   ev.sigev_value.sival_int = 111;
261   if (timer_create (CLOCK_REALTIME, &ev, &timer_thr2) != 0)
262     {
263       printf ("timer_create for timer_thr2 failed: %m\n");
264       result = 1;
265     }
266
267   int ret = timer_getoverrun (timer_thr1);
268   if (ret != 0)
269     {
270       if (ret == -1)
271         printf ("timer_getoverrun failed: %m\n");
272       else
273         printf ("timer_getoverrun returned %d != 0\n", ret);
274       result = 1;
275     }
276
277   struct itimerspec it;
278   it.it_value.tv_sec = 0;
279   it.it_value.tv_nsec = -26;
280   it.it_interval.tv_sec = 0;
281   it.it_interval.tv_nsec = 0;
282   if (timer_settime (timer_sig1, 0, &it, NULL) == 0)
283     {
284       puts ("timer_settime with negative tv_nsec unexpectedly succeeded");
285       result = 1;
286     }
287   else if (errno != EINVAL)
288     {
289       printf ("timer_settime with negative tv_nsec did not fail with "
290               "EINVAL: %m\n");
291       result = 1;
292     }
293
294   it.it_value.tv_nsec = 100000;
295   it.it_interval.tv_nsec = 1000000000;
296   if (timer_settime (timer_sig2, 0, &it, NULL) == 0)
297     {
298       puts ("timer_settime with tv_nsec 1000000000 unexpectedly succeeded");
299       result = 1;
300     }
301   else if (errno != EINVAL)
302     {
303       printf ("timer_settime with tv_nsec 1000000000 did not fail with "
304               "EINVAL: %m\n");
305       result = 1;
306     }
307
308   it.it_value.tv_nsec = 0;
309   it.it_interval.tv_nsec = -26;
310   if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
311     {
312       printf ("timer_settime with it_value 0 it_interval invalid failed: %m\n");
313       /* FIXME: is this mandated by POSIX?
314       result = 1; */
315     }
316
317   it.it_interval.tv_nsec = 3000000000;
318   if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
319     {
320       printf ("timer_settime with it_value 0 it_interval invalid failed: %m\n");
321       /* FIXME: is this mandated by POSIX?
322       result = 1; */
323     }
324
325   struct timespec startts;
326   if (clock_gettime (CLOCK_REALTIME, &startts) != 0)
327     {
328       printf ("clock_gettime failed: %m\n");
329       result = 1;
330     }
331
332   it.it_value.tv_nsec = 100000000;
333   it.it_interval.tv_nsec = 0;
334   if (timer_settime (timer_none, 0, &it, NULL) != 0)
335     {
336       printf ("timer_settime timer_none failed: %m\n");
337       result = 1;
338     }
339
340   it.it_value.tv_nsec = 200000000;
341   if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
342     {
343       printf ("timer_settime timer_thr1 failed: %m\n");
344       result = 1;
345     }
346
347   it.it_value.tv_nsec = 300000000;
348   if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
349     {
350       printf ("timer_settime timer_thr2 failed: %m\n");
351       result = 1;
352     }
353
354   it.it_value.tv_nsec = 400000000;
355   if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
356     {
357       printf ("timer_settime timer_sig1 failed: %m\n");
358       result = 1;
359     }
360
361   it.it_value.tv_nsec = 500000000;
362   if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
363     {
364       printf ("timer_settime timer_sig2 failed: %m\n");
365       result = 1;
366     }
367
368   pthread_mutex_lock (&lock);
369   while (thr1_cnt == 0 || thr2_cnt == 0)
370     pthread_cond_wait (&cond, &lock);
371   pthread_mutex_unlock (&lock);
372
373   while (sig1_cnt == 0 || sig2_cnt == 0)
374     {
375       ts.tv_sec = 0;
376       ts.tv_nsec = 100000000;
377       nanosleep (&ts, NULL);
378     }
379
380   pthread_mutex_lock (&lock);
381
382   if (thr1_cnt != 1)
383     {
384       printf ("thr1 not called exactly once, but %d times\n", thr1_cnt);
385       result = 1;
386     }
387   else if (thr1_err)
388     {
389       puts ("an error occurred in thr1");
390       result = 1;
391     }
392   else if (thr1_sigval.sival_ptr != &ev)
393     {
394       printf ("thr1_sigval.sival_ptr %p != %p\n", thr1_sigval.sival_ptr, &ev);
395       result = 1;
396     }
397   else if (check_ts ("thr1", &startts, &thr1_ts, 200000))
398     result = 1;
399
400   if (thr2_cnt != 1)
401     {
402       printf ("thr2 not called exactly once, but %d times\n", thr2_cnt);
403       result = 1;
404     }
405   else if (thr2_err)
406     {
407       puts ("an error occurred in thr2");
408       result = 1;
409     }
410   else if (thr2_sigval.sival_int != 111)
411     {
412       printf ("thr2_sigval.sival_ptr %d != 111\n", thr2_sigval.sival_int);
413       result = 1;
414     }
415   else if (check_ts ("thr2", &startts, &thr2_ts, 300000))
416     result = 1;
417   else if (thr2_guardsize != 0)
418     {
419       printf ("thr2 guardsize %zd != 0\n", thr2_guardsize);
420       result = 1;
421     }
422
423   pthread_mutex_unlock (&lock);
424
425   if (sig1_cnt != 1)
426     {
427       printf ("sig1 not called exactly once, but %d times\n", sig1_cnt);
428       result = 1;
429     }
430   else if (sig1_err)
431     {
432       printf ("errors occurred in sig1 handler %x\n", sig1_err);
433       result = 1;
434     }
435   else if (sig1_sigval.sival_ptr != &ev)
436     {
437       printf ("sig1_sigval.sival_ptr %p != %p\n", sig1_sigval.sival_ptr, &ev);
438       result = 1;
439     }
440   else if (check_ts ("sig1", &startts, &sig1_ts, 400000))
441     result = 1;
442
443   if (sig2_cnt != 1)
444     {
445       printf ("sig2 not called exactly once, but %d times\n", sig2_cnt);
446       result = 1;
447     }
448   else if (sig2_err)
449     {
450       printf ("errors occurred in sig2 handler %x\n", sig2_err);
451       result = 1;
452     }
453   else if (sig2_sigval.sival_int != 163)
454     {
455       printf ("sig2_sigval.sival_ptr %d != 163\n", sig2_sigval.sival_int);
456       result = 1;
457     }
458   else if (check_ts ("sig2", &startts, &sig2_ts, 500000))
459     result = 1;
460
461   if (timer_gettime (timer_none, &it) != 0)
462     {
463       printf ("timer_gettime timer_none failed: %m\n");
464       result = 1;
465     }
466   else if (it.it_value.tv_sec || it.it_value.tv_nsec
467            || it.it_interval.tv_sec || it.it_interval.tv_nsec)
468     {
469       printf ("timer_gettime timer_none returned { %ld.%09ld, %ld.%09ld }\n",
470               (long) it.it_value.tv_sec, it.it_value.tv_nsec,
471               (long) it.it_interval.tv_sec, it.it_interval.tv_nsec);
472       result = 1;
473     }
474
475   if (clock_gettime (CLOCK_REALTIME, &startts) != 0)
476     {
477       printf ("clock_gettime failed: %m\n");
478       result = 1;
479     }
480
481   it.it_value.tv_sec = 1;
482   it.it_value.tv_nsec = 0;
483   it.it_interval.tv_sec = 0;
484   it.it_interval.tv_nsec = 100000000;
485   if (timer_settime (timer_none, 0, &it, NULL) != 0)
486     {
487       printf ("timer_settime timer_none failed: %m\n");
488       result = 1;
489     }
490
491   it.it_value.tv_nsec = 100000000;
492   it.it_interval.tv_nsec = 200000000;
493   if (timer_settime (timer_thr1, 0, &it, NULL) != 0)
494     {
495       printf ("timer_settime timer_thr1 failed: %m\n");
496       result = 1;
497     }
498
499   it.it_value.tv_nsec = 200000000;
500   it.it_interval.tv_nsec = 300000000;
501   if (timer_settime (timer_thr2, 0, &it, NULL) != 0)
502     {
503       printf ("timer_settime timer_thr2 failed: %m\n");
504       result = 1;
505     }
506
507   it.it_value.tv_nsec = 300000000;
508   it.it_interval.tv_nsec = 400000000;
509   if (timer_settime (timer_sig1, 0, &it, NULL) != 0)
510     {
511       printf ("timer_settime timer_sig1 failed: %m\n");
512       result = 1;
513     }
514
515   it.it_value.tv_nsec = 400000000;
516   it.it_interval.tv_nsec = 500000000;
517   if (TEMP_FAILURE_RETRY (timer_settime (timer_sig2, 0, &it, NULL)) != 0)
518     {
519       printf ("timer_settime timer_sig2 failed: %m\n");
520       result = 1;
521     }
522
523   pthread_mutex_lock (&lock);
524   while (thr1_cnt < 6 || thr2_cnt < 6)
525     pthread_cond_wait (&cond, &lock);
526   pthread_mutex_unlock (&lock);
527
528   while (sig1_cnt < 6 || sig2_cnt < 6)
529     {
530       ts.tv_sec = 0;
531       ts.tv_nsec = 100000000;
532       nanosleep (&ts, NULL);
533     }
534
535   pthread_mutex_lock (&lock);
536
537   if (thr1_err)
538     {
539       puts ("an error occurred in thr1");
540       result = 1;
541     }
542   else if (check_ts ("thr1", &startts, &thr1_ts, 1100000 + 4 * 200000))
543     result = 1;
544
545   if (thr2_err)
546     {
547       puts ("an error occurred in thr2");
548       result = 1;
549     }
550   else if (check_ts ("thr2", &startts, &thr2_ts, 1200000 + 4 * 300000))
551     result = 1;
552   else if (thr2_guardsize != 0)
553     {
554       printf ("thr2 guardsize %zd != 0\n", thr2_guardsize);
555       result = 1;
556     }
557
558   pthread_mutex_unlock (&lock);
559
560   if (sig1_err)
561     {
562       printf ("errors occurred in sig1 handler %x\n", sig1_err);
563       result = 1;
564     }
565   else if (check_ts ("sig1", &startts, &sig1_ts, 1300000 + 4 * 400000))
566     result = 1;
567
568   if (sig2_err)
569     {
570       printf ("errors occurred in sig2 handler %x\n", sig2_err);
571       result = 1;
572     }
573   else if (check_ts ("sig2", &startts, &sig2_ts, 1400000 + 4 * 500000))
574     result = 1;
575
576   if (timer_gettime (timer_none, &it) != 0)
577     {
578       printf ("timer_gettime timer_none failed: %m\n");
579       result = 1;
580     }
581   else if (it.it_interval.tv_sec || it.it_interval.tv_nsec != 100000000)
582     {
583       printf ("second timer_gettime timer_none returned it_interval %ld.%09ld\n",
584               (long) it.it_interval.tv_sec, it.it_interval.tv_nsec);
585       /* FIXME: For now disabled.
586       result = 1; */
587     }
588
589   if (timer_delete (timer_none) != 0)
590     {
591       printf ("timer_delete for timer_none failed: %m\n");
592       result = 1;
593     }
594
595   if (timer_delete (timer_sig1) != 0)
596     {
597       printf ("timer_delete for timer_sig1 failed: %m\n");
598       result = 1;
599     }
600
601   if (timer_delete (timer_sig2) != 0)
602     {
603       printf ("timer_delete for timer_sig2 failed: %m\n");
604       result = 1;
605     }
606
607   if (timer_delete (timer_thr1) != 0)
608     {
609       printf ("timer_delete for timer_thr1 failed: %m\n");
610       result = 1;
611     }
612
613   if (timer_delete (timer_thr2) != 0)
614     {
615       printf ("timer_delete for timer_thr2 failed: %m\n");
616       result = 1;
617     }
618   return result;
619 }
620 #else
621 # define TEST_FUNCTION 0
622 #endif
623
624 #include "../test-skeleton.c"