* stdlib/stdlib.h: Remove warn_unused_result attribute from strtol etc.
[glibc.git] / rt / tst-cpuclock2.c
blob9a74eb014b64aab417b19e43293afe35f50837cd
1 /* Test program for process and thread CPU clocks.
2 Copyright (C) 2005, 2012 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #include <unistd.h>
21 #if (_POSIX_THREADS - 0) <= 0
23 # define TEST_FUNCTION 0
25 #else
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <time.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <pthread.h>
35 static pthread_barrier_t barrier;
37 /* This function is intended to rack up both user and system time. */
38 static void *
39 chew_cpu (void *arg)
41 pthread_barrier_wait (&barrier);
43 while (1)
45 static volatile char buf[4096];
46 for (int i = 0; i < 100; ++i)
47 for (size_t j = 0; j < sizeof buf; ++j)
48 buf[j] = 0xaa;
49 int nullfd = open ("/dev/null", O_WRONLY);
50 for (int i = 0; i < 100; ++i)
51 for (size_t j = 0; j < sizeof buf; ++j)
52 buf[j] = 0xbb;
53 write (nullfd, (char *) buf, sizeof buf);
54 close (nullfd);
57 return NULL;
60 static unsigned long long int
61 tsdiff (const struct timespec *before, const struct timespec *after)
63 struct timespec diff = { .tv_sec = after->tv_sec - before->tv_sec,
64 .tv_nsec = after->tv_nsec - before->tv_nsec };
65 while (diff.tv_nsec < 0)
67 --diff.tv_sec;
68 diff.tv_nsec += 1000000000;
70 return diff.tv_sec * 1000000000ULL + diff.tv_nsec;
73 static unsigned long long int
74 test_nanosleep (clockid_t clock, const char *which,
75 const struct timespec *before, int *bad)
77 const struct timespec sleeptime = { .tv_nsec = 100000000 };
78 int e = clock_nanosleep (clock, 0, &sleeptime, NULL);
79 if (e == EINVAL || e == ENOTSUP || e == ENOSYS)
81 printf ("clock_nanosleep not supported for %s CPU clock: %s\n",
82 which, strerror (e));
83 return 0;
85 if (e != 0)
87 printf ("clock_nanosleep on %s CPU clock: %s\n", which, strerror (e));
88 *bad = 1;
89 return 0;
92 struct timespec after;
93 if (clock_gettime (clock, &after) < 0)
95 printf ("clock_gettime on %s CPU clock %lx => %s\n",
96 which, (unsigned long int) clock, strerror (errno));
97 *bad = 1;
98 return 0;
101 unsigned long long int diff = tsdiff (before, &after);
102 if (diff < sleeptime.tv_nsec || diff > sleeptime.tv_nsec * 2)
104 printf ("clock_nanosleep on %s slept %llu (outside reasonable range)\n",
105 which, diff);
106 *bad = 1;
107 return diff;
110 struct timespec sleeptimeabs = sleeptime;
111 sleeptimeabs.tv_sec += after.tv_sec;
112 sleeptimeabs.tv_nsec += after.tv_nsec;
113 while (sleeptimeabs.tv_nsec >= 1000000000)
115 ++sleeptimeabs.tv_sec;
116 sleeptimeabs.tv_nsec -= 1000000000;
118 e = clock_nanosleep (clock, TIMER_ABSTIME, &sleeptimeabs, NULL);
119 if (e != 0)
121 printf ("absolute clock_nanosleep on %s CPU clock: %s\n",
122 which, strerror (e));
123 *bad = 1;
124 return diff;
127 struct timespec afterabs;
128 if (clock_gettime (clock, &afterabs) < 0)
130 printf ("clock_gettime on %s CPU clock %lx => %s\n",
131 which, (unsigned long int) clock, strerror (errno));
132 *bad = 1;
133 return diff;
136 unsigned long long int sleepdiff = tsdiff (&sleeptimeabs, &afterabs);
137 if (sleepdiff > sleeptime.tv_nsec)
139 printf ("\
140 absolute clock_nanosleep on %s %llu past target (outside reasonable range)\n",
141 which, sleepdiff);
142 *bad = 1;
145 unsigned long long int diffabs = tsdiff (&after, &afterabs);
146 if (diffabs < sleeptime.tv_nsec || diffabs > sleeptime.tv_nsec * 2)
148 printf ("\
149 absolute clock_nanosleep on %s slept %llu (outside reasonable range)\n",
150 which, diffabs);
151 *bad = 1;
154 return diff + diffabs;
159 static int
160 do_test (void)
162 int result = 0;
163 clockid_t process_clock, th_clock, my_thread_clock;
164 int e;
165 pthread_t th;
167 e = clock_getcpuclockid (0, &process_clock);
168 if (e != 0)
170 printf ("clock_getcpuclockid on self => %s\n", strerror (e));
171 return 1;
174 e = pthread_getcpuclockid (pthread_self (), &my_thread_clock);
175 if (e != 0)
177 printf ("pthread_getcpuclockid on self => %s\n", strerror (e));
178 return 1;
181 /* This is a kludge. This test fails if the semantics of thread and
182 process clocks are wrong. The old code using hp-timing without kernel
183 support has bogus semantics if there are context switches. We don't
184 fail to report failure when the proper functionality is not available
185 in the kernel. It so happens that Linux kernels without correct CPU
186 clock support also lack CPU timer support, so we use use that to guess
187 that we are using the bogus code and not test it. */
188 timer_t t;
189 if (timer_create (my_thread_clock, NULL, &t) != 0)
191 printf ("timer_create: %m\n");
192 puts ("No support for CPU clocks with good semantics, skipping test");
193 return 0;
195 timer_delete (t);
198 pthread_barrier_init (&barrier, NULL, 2);
200 e = pthread_create (&th, NULL, chew_cpu, NULL);
201 if (e != 0)
203 printf ("pthread_create: %s\n", strerror (e));
204 return 1;
207 e = pthread_getcpuclockid (th, &th_clock);
208 if (e == ENOENT || e == ENOSYS || e == ENOTSUP)
210 puts ("pthread_getcpuclockid does not support other threads");
211 return 1;
214 pthread_barrier_wait (&barrier);
216 struct timespec res;
217 if (clock_getres (th_clock, &res) < 0)
219 printf ("clock_getres on live thread clock %lx => %s\n",
220 (unsigned long int) th_clock, strerror (errno));
221 result = 1;
222 return 1;
224 printf ("live thread clock %lx resolution %lu.%.9lu\n",
225 (unsigned long int) th_clock, res.tv_sec, res.tv_nsec);
227 struct timespec process_before, process_after;
228 if (clock_gettime (process_clock, &process_before) < 0)
230 printf ("clock_gettime on process clock %lx => %s\n",
231 (unsigned long int) process_clock, strerror (errno));
232 return 1;
235 struct timespec before, after;
236 if (clock_gettime (th_clock, &before) < 0)
238 printf ("clock_gettime on live thread clock %lx => %s\n",
239 (unsigned long int) th_clock, strerror (errno));
240 return 1;
242 printf ("live thread before sleep => %lu.%.9lu\n",
243 before.tv_sec, before.tv_nsec);
245 struct timespec me_before, me_after;
246 if (clock_gettime (my_thread_clock, &me_before) < 0)
248 printf ("clock_gettime on self thread clock %lx => %s\n",
249 (unsigned long int) my_thread_clock, strerror (errno));
250 return 1;
252 printf ("self thread before sleep => %lu.%.9lu\n",
253 me_before.tv_sec, me_before.tv_nsec);
255 struct timespec sleeptime = { .tv_nsec = 500000000 };
256 if (nanosleep (&sleeptime, NULL) != 0)
258 perror ("nanosleep");
259 return 1;
262 if (clock_gettime (th_clock, &after) < 0)
264 printf ("clock_gettime on live thread clock %lx => %s\n",
265 (unsigned long int) th_clock, strerror (errno));
266 return 1;
268 printf ("live thread after sleep => %lu.%.9lu\n",
269 after.tv_sec, after.tv_nsec);
271 if (clock_gettime (process_clock, &process_after) < 0)
273 printf ("clock_gettime on process clock %lx => %s\n",
274 (unsigned long int) process_clock, strerror (errno));
275 return 1;
278 if (clock_gettime (my_thread_clock, &me_after) < 0)
280 printf ("clock_gettime on self thread clock %lx => %s\n",
281 (unsigned long int) my_thread_clock, strerror (errno));
282 return 1;
284 printf ("self thread after sleep => %lu.%.9lu\n",
285 me_after.tv_sec, me_after.tv_nsec);
287 unsigned long long int th_diff = tsdiff (&before, &after);
288 unsigned long long int pdiff = tsdiff (&process_before, &process_after);
289 unsigned long long int my_diff = tsdiff (&me_before, &me_after);
291 if (th_diff < 100000000 || th_diff > 600000000)
293 printf ("live thread before - after %llu outside reasonable range\n",
294 th_diff);
295 result = 1;
298 if (my_diff > 100000000)
300 printf ("self thread before - after %llu outside reasonable range\n",
301 my_diff);
302 result = 1;
305 if (pdiff < th_diff)
307 printf ("process before - after %llu outside reasonable range (%llu)\n",
308 pdiff, th_diff);
309 result = 1;
312 process_after.tv_nsec += test_nanosleep (th_clock, "live thread",
313 &after, &result);
314 process_after.tv_nsec += test_nanosleep (process_clock, "process",
315 &process_after, &result);
316 test_nanosleep (CLOCK_PROCESS_CPUTIME_ID,
317 "PROCESS_CPUTIME_ID", &process_after, &result);
319 pthread_cancel (th);
321 e = clock_nanosleep (CLOCK_THREAD_CPUTIME_ID, 0, &sleeptime, NULL);
322 if (e != EINVAL)
324 printf ("clock_nanosleep CLOCK_THREAD_CPUTIME_ID: %s\n",
325 strerror (e));
326 result = 1;
329 return result;
331 # define TIMEOUT 8
332 # define TEST_FUNCTION do_test ()
333 #endif
335 #include "../test-skeleton.c"