Use Linux 6.12 in build-many-glibcs.py
[glibc.git] / time / tst-cpuclock1.c
blob1ee6382de103067139b16c91d3953738e990a9de
1 /* Test program for process CPU clocks.
2 Copyright (C) 2004-2024 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>
30 #include <support/xunistd.h>
32 /* This function is intended to rack up both user and system time. */
33 static void
34 chew_cpu (void)
36 while (1)
38 static volatile char buf[4096];
39 for (int i = 0; i < 100; ++i)
40 for (size_t j = 0; j < sizeof buf; ++j)
41 buf[j] = 0xaa;
42 int nullfd = open ("/dev/null", O_WRONLY);
43 for (int i = 0; i < 100; ++i)
44 for (size_t j = 0; j < sizeof buf; ++j)
45 buf[j] = 0xbb;
46 xwrite (nullfd, (char *) buf, sizeof buf);
47 close (nullfd);
48 if (getppid () == 1)
49 _exit (2);
53 static int
54 do_test (void)
56 int result = 0;
57 clockid_t cl;
58 int e;
59 pid_t dead_child, child;
61 /* Fork a child and let it die, to give us a PID known not be valid
62 (assuming PIDs don't wrap around during the test). */
64 dead_child = fork ();
65 if (dead_child == 0)
66 _exit (0);
67 if (dead_child < 0)
69 perror ("fork");
70 return 1;
72 int x;
73 if (wait (&x) != dead_child)
75 perror ("wait");
76 return 2;
80 /* POSIX says we should get ESRCH for this. */
81 e = clock_getcpuclockid (dead_child, &cl);
82 if (e != ENOSYS && e != ESRCH && e != EPERM)
84 printf ("clock_getcpuclockid on dead PID %d => %s\n",
85 dead_child, strerror (e));
86 result = 1;
89 /* Now give us a live child eating up CPU time. */
90 child = fork ();
91 if (child == 0)
93 chew_cpu ();
94 _exit (1);
96 if (child < 0)
98 perror ("fork");
99 return 1;
102 e = clock_getcpuclockid (child, &cl);
103 if (e == EPERM)
105 puts ("clock_getcpuclockid does not support other processes");
106 goto done;
108 if (e != 0)
110 printf ("clock_getcpuclockid on live PID %d => %s\n",
111 child, strerror (e));
112 result = 1;
113 goto done;
116 const clockid_t child_clock = cl;
117 struct timespec res;
118 if (clock_getres (child_clock, &res) < 0)
120 printf ("clock_getres on live PID %d clock %lx => %s\n",
121 child, (unsigned long int) child_clock, strerror (errno));
122 result = 1;
123 goto done;
125 printf ("live PID %d clock %lx resolution %ju.%.9ju\n",
126 child, (unsigned long int) child_clock,
127 (uintmax_t) res.tv_sec, (uintmax_t) res.tv_nsec);
129 struct timespec before;
130 if (clock_gettime (child_clock, &before) < 0)
132 printf ("clock_gettime on live PID %d clock %lx => %s\n",
133 child, (unsigned long int) child_clock, strerror (errno));
134 result = 1;
135 goto done;
137 /* Should be close to 0.0. */
138 printf ("live PID %d before sleep => %ju.%.9ju\n",
139 child, (uintmax_t) before.tv_sec, (uintmax_t) before.tv_nsec);
141 struct timespec sleeptime = { .tv_nsec = 100000000 };
142 e = clock_nanosleep (child_clock, 0, &sleeptime, NULL);
143 if (e == EINVAL || e == ENOTSUP || e == ENOSYS)
145 printf ("clock_nanosleep not supported for other process clock: %s\n",
146 strerror (e));
148 else if (e != 0)
150 printf ("clock_nanosleep on other process clock: %s\n", strerror (e));
151 result = 1;
153 else
155 struct timespec afterns;
156 if (clock_gettime (child_clock, &afterns) < 0)
158 printf ("clock_gettime on live PID %d clock %lx => %s\n",
159 child, (unsigned long int) child_clock, strerror (errno));
160 result = 1;
162 else
164 printf ("live PID %d after sleep => %ju.%.9ju\n",
165 child, (uintmax_t) afterns.tv_sec,
166 (uintmax_t) afterns.tv_nsec);
170 if (kill (child, SIGKILL) != 0)
172 perror ("kill");
173 result = 2;
174 goto done;
177 /* Wait long enough to let the child finish dying. */
179 sleeptime.tv_nsec = 200000000;
180 if (nanosleep (&sleeptime, NULL) != 0)
182 perror ("nanosleep");
183 result = 1;
184 goto done;
187 struct timespec dead;
188 if (clock_gettime (child_clock, &dead) < 0)
190 printf ("clock_gettime on dead PID %d clock %lx => %s\n",
191 child, (unsigned long int) child_clock, strerror (errno));
192 result = 1;
193 goto done;
195 /* Should be close to 0.1. */
196 printf ("dead PID %d => %ju.%.9ju\n",
197 child, (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
199 /* Now reap the child and verify that its clock is no longer valid. */
201 int x;
202 if (waitpid (child, &x, 0) != child)
204 perror ("waitpid");
205 result = 1;
209 if (clock_gettime (child_clock, &dead) == 0)
211 printf ("clock_gettime on reaped PID %d clock %lx => %ju%.9ju\n",
212 child, (unsigned long int) child_clock,
213 (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
214 result = 1;
216 else
218 if (errno != EINVAL)
219 result = 1;
220 printf ("clock_gettime on reaped PID %d clock %lx => %s\n",
221 child, (unsigned long int) child_clock, strerror (errno));
224 if (clock_getres (child_clock, &dead) == 0)
226 printf ("clock_getres on reaped PID %d clock %lx => %ju%.9ju\n",
227 child, (unsigned long int) child_clock,
228 (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
229 result = 1;
231 else
233 if (errno != EINVAL)
234 result = 1;
235 printf ("clock_getres on reaped PID %d clock %lx => %s\n",
236 child, (unsigned long int) child_clock, strerror (errno));
239 return result;
241 done:
243 if (kill (child, SIGKILL) != 0 && errno != ESRCH)
245 perror ("kill");
246 return 2;
248 int x;
249 if (waitpid (child, &x, 0) != child && errno != ECHILD)
251 perror ("waitpid");
252 return 2;
256 return result;
260 #define TEST_FUNCTION do_test ()
261 #include "../test-skeleton.c"