arm: remove string/tst-memmove-overflow XFAIL
[glibc.git] / time / tst-cpuclock1.c
blob1ac611a92b733e259a35ee27779300b83ceda524
1 /* Test program for process CPU clocks.
2 Copyright (C) 2004-2020 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 <https://www.gnu.org/licenses/>. */
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <time.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <signal.h>
27 #include <stdint.h>
28 #include <sys/wait.h>
29 #include <support/timespec.h>
31 /* This function is intended to rack up both user and system time. */
32 static void
33 chew_cpu (void)
35 while (1)
37 static volatile char buf[4096];
38 for (int i = 0; i < 100; ++i)
39 for (size_t j = 0; j < sizeof buf; ++j)
40 buf[j] = 0xaa;
41 int nullfd = open ("/dev/null", O_WRONLY);
42 for (int i = 0; i < 100; ++i)
43 for (size_t j = 0; j < sizeof buf; ++j)
44 buf[j] = 0xbb;
45 write (nullfd, (char *) buf, sizeof buf);
46 close (nullfd);
47 if (getppid () == 1)
48 _exit (2);
52 static int
53 do_test (void)
55 int result = 0;
56 clockid_t cl;
57 int e;
58 pid_t dead_child, child;
60 /* Fork a child and let it die, to give us a PID known not be valid
61 (assuming PIDs don't wrap around during the test). */
63 dead_child = fork ();
64 if (dead_child == 0)
65 _exit (0);
66 if (dead_child < 0)
68 perror ("fork");
69 return 1;
71 int x;
72 if (wait (&x) != dead_child)
74 perror ("wait");
75 return 2;
79 /* POSIX says we should get ESRCH for this. */
80 e = clock_getcpuclockid (dead_child, &cl);
81 if (e != ENOSYS && e != ESRCH && e != EPERM)
83 printf ("clock_getcpuclockid on dead PID %d => %s\n",
84 dead_child, strerror (e));
85 result = 1;
88 /* Now give us a live child eating up CPU time. */
89 child = fork ();
90 if (child == 0)
92 chew_cpu ();
93 _exit (1);
95 if (child < 0)
97 perror ("fork");
98 return 1;
101 e = clock_getcpuclockid (child, &cl);
102 if (e == EPERM)
104 puts ("clock_getcpuclockid does not support other processes");
105 goto done;
107 if (e != 0)
109 printf ("clock_getcpuclockid on live PID %d => %s\n",
110 child, strerror (e));
111 result = 1;
112 goto done;
115 const clockid_t child_clock = cl;
116 struct timespec res;
117 if (clock_getres (child_clock, &res) < 0)
119 printf ("clock_getres on live PID %d clock %lx => %s\n",
120 child, (unsigned long int) child_clock, strerror (errno));
121 result = 1;
122 goto done;
124 printf ("live PID %d clock %lx resolution %ju.%.9ju\n",
125 child, (unsigned long int) child_clock,
126 (uintmax_t) res.tv_sec, (uintmax_t) res.tv_nsec);
128 struct timespec before, after;
129 if (clock_gettime (child_clock, &before) < 0)
131 printf ("clock_gettime on live PID %d clock %lx => %s\n",
132 child, (unsigned long int) child_clock, strerror (errno));
133 result = 1;
134 goto done;
136 /* Should be close to 0.0. */
137 printf ("live PID %d before sleep => %ju.%.9ju\n",
138 child, (uintmax_t) before.tv_sec, (uintmax_t) before.tv_nsec);
140 struct timespec sleeptime = { .tv_nsec = 500000000 };
141 if (nanosleep (&sleeptime, NULL) != 0)
143 perror ("nanosleep");
144 result = 1;
145 goto done;
148 if (clock_gettime (child_clock, &after) < 0)
150 printf ("clock_gettime on live PID %d clock %lx => %s\n",
151 child, (unsigned long int) child_clock, strerror (errno));
152 result = 1;
153 goto done;
155 /* Should be close to 0.5. */
156 printf ("live PID %d after sleep => %ju.%.9ju\n",
157 child, (uintmax_t) after.tv_sec, (uintmax_t) after.tv_nsec);
159 /* The bound values are empirically defined by testing this code over high cpu
160 usage and different nice values. Of all the values we keep the 90th
161 percentile of values and use those values for our testing allowed range. */
162 struct timespec diff = timespec_sub (support_timespec_normalize (after),
163 support_timespec_normalize (before));
164 if (!support_timespec_check_in_range (sleeptime, diff, .9, 1.1))
166 printf ("before - after %ju.%.9ju outside reasonable range\n",
167 (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
168 result = 1;
171 sleeptime.tv_nsec = 100000000;
172 e = clock_nanosleep (child_clock, 0, &sleeptime, NULL);
173 if (e == EINVAL || e == ENOTSUP || e == ENOSYS)
175 printf ("clock_nanosleep not supported for other process clock: %s\n",
176 strerror (e));
178 else if (e != 0)
180 printf ("clock_nanosleep on other process clock: %s\n", strerror (e));
181 result = 1;
183 else
185 struct timespec afterns;
186 if (clock_gettime (child_clock, &afterns) < 0)
188 printf ("clock_gettime on live PID %d clock %lx => %s\n",
189 child, (unsigned long int) child_clock, strerror (errno));
190 result = 1;
192 else
194 /* The bound values are empirically defined by testing this code over
195 high cpu usage and different nice values. Of all the values we keep
196 the 90th percentile of values and use those values for our testing
197 allowed range. */
198 diff = timespec_sub (support_timespec_normalize (afterns),
199 support_timespec_normalize (after));
200 if (!support_timespec_check_in_range (sleeptime, diff, .9, 1.2))
202 printf ("nanosleep time %ju.%.9ju outside reasonable range\n",
203 (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
204 result = 1;
209 if (kill (child, SIGKILL) != 0)
211 perror ("kill");
212 result = 2;
213 goto done;
216 /* Wait long enough to let the child finish dying. */
218 sleeptime.tv_nsec = 200000000;
219 if (nanosleep (&sleeptime, NULL) != 0)
221 perror ("nanosleep");
222 result = 1;
223 goto done;
226 struct timespec dead;
227 if (clock_gettime (child_clock, &dead) < 0)
229 printf ("clock_gettime on dead PID %d clock %lx => %s\n",
230 child, (unsigned long int) child_clock, strerror (errno));
231 result = 1;
232 goto done;
234 /* Should be close to 0.6. */
235 printf ("dead PID %d => %ju.%.9ju\n",
236 child, (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
237 /* The bound values are empirically defined by testing this code over high cpu
238 usage and different nice values. Of all the values we keep the 90th
239 percentile of values and use those values for our testing allowed range. */
240 diff = timespec_sub (support_timespec_normalize (dead),
241 support_timespec_normalize (after));
242 sleeptime.tv_nsec = 100000000;
243 if (!support_timespec_check_in_range (sleeptime, diff, .9, 1.2))
245 printf ("dead - after %ju.%.9ju outside reasonable range\n",
246 (uintmax_t) diff.tv_sec, (uintmax_t) diff.tv_nsec);
247 result = 1;
250 /* Now reap the child and verify that its clock is no longer valid. */
252 int x;
253 if (waitpid (child, &x, 0) != child)
255 perror ("waitpid");
256 result = 1;
260 if (clock_gettime (child_clock, &dead) == 0)
262 printf ("clock_gettime on reaped PID %d clock %lx => %ju%.9ju\n",
263 child, (unsigned long int) child_clock,
264 (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
265 result = 1;
267 else
269 if (errno != EINVAL)
270 result = 1;
271 printf ("clock_gettime on reaped PID %d clock %lx => %s\n",
272 child, (unsigned long int) child_clock, strerror (errno));
275 if (clock_getres (child_clock, &dead) == 0)
277 printf ("clock_getres on reaped PID %d clock %lx => %ju%.9ju\n",
278 child, (unsigned long int) child_clock,
279 (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
280 result = 1;
282 else
284 if (errno != EINVAL)
285 result = 1;
286 printf ("clock_getres on reaped PID %d clock %lx => %s\n",
287 child, (unsigned long int) child_clock, strerror (errno));
290 return result;
292 done:
294 if (kill (child, SIGKILL) != 0 && errno != ESRCH)
296 perror ("kill");
297 return 2;
299 int x;
300 if (waitpid (child, &x, 0) != child && errno != ECHILD)
302 perror ("waitpid");
303 return 2;
307 return result;
311 #define TEST_FUNCTION do_test ()
312 #include "../test-skeleton.c"