OSDN Git Service

Replace FSF snail mail address with URLs
[uclinux-h8/uClibc.git] / test / 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, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <errno.h>
20 #include <pthread.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <time.h>
24 #include <unistd.h>
25
26
27 #if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
28 static pthread_barrier_t b2;
29 static pthread_barrier_t bN;
30
31
32 static void *
33 tf (void *arg)
34 {
35   int e = pthread_barrier_wait (&b2);
36   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
37     {
38       puts ("barrier_wait failed");
39       exit (1);
40     }
41
42   e = pthread_barrier_wait (&bN);
43   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
44     {
45       puts ("barrier_wait failed");
46       exit (1);
47     }
48
49   return NULL;
50 }
51 #endif
52
53
54 int
55 do_test (void)
56 {
57 #if defined _POSIX_THREAD_CPUTIME && _POSIX_THREAD_CPUTIME >= 0
58 # define N 10
59
60 # if _POSIX_THREAD_CPUTIME == 0
61   if (sysconf (_SC_THREAD_CPUTIME) < 0)
62     {
63       puts ("_POSIX_THREAD_CPUTIME option not available");
64       return 0;
65     }
66 # endif
67
68   if (pthread_barrier_init (&b2, NULL, 2) != 0
69       || pthread_barrier_init (&bN, NULL, N + 1) != 0)
70     {
71       puts ("barrier_init failed");
72       return 1;
73     }
74
75   struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
76   TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
77
78   pthread_t th[N + 1];
79   clockid_t cl[N + 1];
80 # ifndef CLOCK_THREAD_CPUTIME_ID
81   if (pthread_getcpuclockid (pthread_self (), &cl[0]) != 0)
82     {
83       puts ("own pthread_getcpuclockid failed");
84       return 1;
85     }
86 # else
87   cl[0] = CLOCK_THREAD_CPUTIME_ID;
88 # endif
89
90   pthread_attr_t at;
91
92   if (pthread_attr_init (&at) != 0)
93     {
94       puts ("attr_init failed");
95       return 1;
96     }
97
98   if (pthread_attr_setstacksize (&at, 1 * 1024 * 1024) != 0)
99     {
100       puts ("attr_setstacksize failed");
101       return 1;
102     }
103
104   int i;
105   int e;
106   for (i = 0; i < N; ++i)
107     {
108       if (pthread_create (&th[i], &at, tf, NULL) != 0)
109         {
110           puts ("create failed");
111           return 1;
112         }
113
114       e = pthread_barrier_wait (&b2);
115       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
116         {
117           puts ("barrier_wait failed");
118           return 1;
119         }
120
121       ts.tv_sec = 0;
122       ts.tv_nsec = 100000000;
123       TEMP_FAILURE_RETRY (nanosleep (&ts, &ts));
124
125       if (pthread_getcpuclockid (th[i], &cl[i + 1]) != 0)
126         {
127           puts ("pthread_getcpuclockid failed");
128           return 1;
129         }
130     }
131
132   if (pthread_attr_destroy (&at) != 0)
133     {
134       puts ("attr_destroy failed");
135       return 1;
136     }
137
138   struct timespec t[N + 1];
139   for (i = 0; i < N + 1; ++i)
140     if (clock_gettime (cl[i], &t[i]) != 0)
141       {
142         printf ("clock_gettime round %d failed\n", i);
143         return 1;
144       }
145
146   for (i = 0; i < N; ++i)
147     {
148       struct timespec diff;
149
150       diff.tv_sec = t[i].tv_sec - t[i + 1].tv_sec;
151       diff.tv_nsec = t[i].tv_nsec - t[i + 1].tv_nsec;
152       if (diff.tv_nsec < 0)
153         {
154           diff.tv_nsec += 1000000000;
155           --diff.tv_sec;
156         }
157
158       if (diff.tv_sec < 0 || (diff.tv_sec == 0 && diff.tv_nsec < 100000000))
159         {
160           printf ("\
161 difference between thread %d and %d too small (%ld.%09ld)\n",
162                   i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
163           return 1;
164         }
165
166       printf ("diff %d->%d: %ld.%09ld\n",
167               i, i + 1, (long int) diff.tv_sec, (long int) diff.tv_nsec);
168     }
169
170   ts.tv_sec = 0;
171   ts.tv_nsec = 0;
172   for (i = 0; i < N + 1; ++i)
173     if (clock_settime (cl[i], &ts) != 0)
174       {
175         printf ("clock_settime(%d) round %d failed\n", cl[i], i);
176         return 1;
177       }
178
179   for (i = 0; i < N + 1; ++i)
180     {
181       if (clock_gettime (cl[i], &ts) != 0)
182         {
183           puts ("clock_gettime failed");
184           return 1;
185         }
186
187       if (ts.tv_sec > t[i].tv_sec
188           || (ts.tv_sec == t[i].tv_sec && ts.tv_nsec > t[i].tv_nsec))
189         {
190           puts ("clock_settime didn't reset clock");
191           return 1;
192         }
193     }
194 #endif
195
196   return 0;
197 }
198
199
200 #define TEST_FUNCTION do_test ()
201 #include "../test-skeleton.c"