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/>. */
21 #if (_POSIX_THREADS - 0) <= 0
23 # define TEST_FUNCTION 0
35 static pthread_barrier_t barrier
;
37 /* This function is intended to rack up both user and system time. */
41 pthread_barrier_wait (&barrier
);
45 static volatile char buf
[4096];
46 for (int i
= 0; i
< 100; ++i
)
47 for (size_t j
= 0; j
< sizeof buf
; ++j
)
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
)
53 write (nullfd
, (char *) buf
, sizeof buf
);
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)
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",
87 printf ("clock_nanosleep on %s CPU clock: %s\n", which
, strerror (e
));
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
));
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",
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
);
121 printf ("absolute clock_nanosleep on %s CPU clock: %s\n",
122 which
, strerror (e
));
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
));
136 unsigned long long int sleepdiff
= tsdiff (&sleeptimeabs
, &afterabs
);
137 if (sleepdiff
> sleeptime
.tv_nsec
)
140 absolute clock_nanosleep on %s %llu past target (outside reasonable range)\n",
145 unsigned long long int diffabs
= tsdiff (&after
, &afterabs
);
146 if (diffabs
< sleeptime
.tv_nsec
|| diffabs
> sleeptime
.tv_nsec
* 2)
149 absolute clock_nanosleep on %s slept %llu (outside reasonable range)\n",
154 return diff
+ diffabs
;
163 clockid_t process_clock
, th_clock
, my_thread_clock
;
167 e
= clock_getcpuclockid (0, &process_clock
);
170 printf ("clock_getcpuclockid on self => %s\n", strerror (e
));
174 e
= pthread_getcpuclockid (pthread_self (), &my_thread_clock
);
177 printf ("pthread_getcpuclockid on self => %s\n", strerror (e
));
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. */
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");
198 pthread_barrier_init (&barrier
, NULL
, 2);
200 e
= pthread_create (&th
, NULL
, chew_cpu
, NULL
);
203 printf ("pthread_create: %s\n", strerror (e
));
207 e
= pthread_getcpuclockid (th
, &th_clock
);
208 if (e
== ENOENT
|| e
== ENOSYS
|| e
== ENOTSUP
)
210 puts ("pthread_getcpuclockid does not support other threads");
214 pthread_barrier_wait (&barrier
);
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
));
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
));
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
));
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
));
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");
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
));
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
));
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
));
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",
298 if (my_diff
> 100000000)
300 printf ("self thread before - after %llu outside reasonable range\n",
307 printf ("process before - after %llu outside reasonable range (%llu)\n",
312 process_after
.tv_nsec
+= test_nanosleep (th_clock
, "live thread",
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
);
321 e
= clock_nanosleep (CLOCK_THREAD_CPUTIME_ID
, 0, &sleeptime
, NULL
);
324 printf ("clock_nanosleep CLOCK_THREAD_CPUTIME_ID: %s\n",
332 # define TEST_FUNCTION do_test ()
335 #include "../test-skeleton.c"