Updated to fedora-glibc-20041006T0900
[kopensolaris-gnu/glibc.git] / nptl / tst-clock2.c
1 /* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
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
7    License as published by the Free Software Foundation; either
8    version 2.1 of the 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; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <errno.h>
21 #include <pthread.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <time.h>
25 #include <unistd.h>
26
27
28 #if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
29 static pthread_barrier_t b2;
30 static pthread_barrier_t bN;
31
32
33 static void *
34 tf (void *arg)
35 {
36   int e = pthread_barrier_wait (&b2);
37   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
38     {
39       puts ("barrier_wait failed");
40       exit (1);
41     }
42
43   e = pthread_barrier_wait (&bN);
44   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
45     {
46       puts ("barrier_wait failed");
47       exit (1);
48     }
49
50   return NULL;
51 }
52 #endif
53
54
55 int
56 do_test (void)
57 {
58 #if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
59 # define N 10
60
61   if (pthread_barrier_init (&b2, NULL, 2) != 0
62       || pthread_barrier_init (&bN, NULL, N + 1) != 0)
63     {
64       puts ("barrier_init failed");
65       return 1;
66     }
67
68   struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
69   TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
70
71   pthread_t th[N + 1];
72   clockid_t cl[N + 1];
73 # ifndef CLOCK_THREAD_CPUTIME_ID
74   if (pthread_getcpuclockid (pthread_self (), &cl[0]) != 0)
75     {
76       puts ("own pthread_getcpuclockid failed");
77       return 1;
78     }
79 # else
80   cl[0] = CLOCK_THREAD_CPUTIME_ID;
81 # endif
82
83   pthread_attr_t at;
84
85   if (pthread_attr_init (&at) != 0)
86     {
87       puts ("attr_init failed");
88       return 1;
89     }
90
91   if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
92     {
93       puts ("attr_setstacksize failed");
94       return 1;
95     }
96
97   int i;
98   int e;
99   for (i = 0; i < N; ++i)
100     {
101       if (pthread_create (&th[i], &at, tf, NULL) != 0)
102         {
103           puts ("create failed");
104           return 1;
105         }
106
107       e = pthread_barrier_wait (&b2);
108       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
109         {
110           puts ("barrier_wait failed");
111           return 1;
112         }
113
114       ts.tv_sec = 0;
115       ts.tv_nsec = 100000000;
116       TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
117
118       if (pthread_getcpuclockid (th[i], &cl[i + 1]) != 0)
119         {
120           puts ("pthread_getcpuclockid failed");
121           return 1;
122         }
123     }
124
125   if (pthread_attr_destroy (&at) != 0)
126     {
127       puts ("attr_destroy failed");
128       return 1;
129     }
130
131   struct timespec t[N + 1];
132   for (i = 0; i < N + 1; ++i)
133     if (clock_gettime (cl[i], &t[i]) != 0)
134       {
135         printf ("clock_gettime round %d failed\n", i);
136         return 1;
137       }
138
139   for (i = 0; i < N; ++i)
140     {
141       struct timespec diff;
142
143       diff.tv_sec = t[i].tv_sec - t[i + 1].tv_sec;
144       diff.tv_nsec = t[i].tv_nsec - t[i + 1].tv_nsec;
145       if (diff.tv_nsec < 0)
146         {
147           diff.tv_nsec += 1000000000;
148           --diff.tv_sec;
149         }
150
151       if (diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_nsec < 100000000))
152         {
153           printf ("\
154 difference between thread %d and %d too small (%ld.%09ld)\n",
155                   i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
156           return 1;
157         }
158
159       printf ("diff %d->%d: %ld.%09ld\n",
160               i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
161     }
162
163   ts.tv_sec = 0;
164   ts.tv_nsec = 0;
165   for (i = 0; i < N + 1; ++i)
166     if (clock_settime (cl[i], &ts) != 0)
167       {
168         printf ("clock_settime(%d) round %d failed\n", cl[i], i);
169         return 1;
170       }
171
172   for (i = 0; i < N + 1; ++i)
173     {
174       if (clock_gettime (cl[i], &ts) != 0)
175         {
176           puts ("clock_gettime failed");
177           return 1;
178         }
179
180       if (ts.tv_sec > t[i].tv_sec
181           || (ts.tv_sec == t[i].tv_sec && ts.tv_nsec > t[i].tv_nsec))
182         {
183           puts ("clock_settime didn't reset clock");
184           return 1;
185         }
186     }
187 #endif
188
189   return 0;
190 }
191
192
193 #define TEST_FUNCTION do_test ()
194 #include "../test-skeleton.c"