]> git.ipfire.org Git - thirdparty/glibc.git/blame - time/tst-cpuclock1.c
INSTALL, install.texi: minor updates, regenerate
[thirdparty/glibc.git] / time / tst-cpuclock1.c
CommitLineData
84060bad 1/* Test program for process CPU clocks.
dff8da6b 2 Copyright (C) 2004-2024 Free Software Foundation, Inc.
84060bad
RM
3 This file is part of the GNU C Library.
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
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
84060bad
RM
18
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>
5d619de4 27#include <stdint.h>
84060bad
RM
28#include <sys/wait.h>
29
026a84a5
FB
30#include <support/xunistd.h>
31
84060bad
RM
32/* This function is intended to rack up both user and system time. */
33static void
34chew_cpu (void)
35{
36 while (1)
37 {
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;
026a84a5 46 xwrite (nullfd, (char *) buf, sizeof buf);
84060bad
RM
47 close (nullfd);
48 if (getppid () == 1)
49 _exit (2);
50 }
51}
52
53static int
54do_test (void)
55{
56 int result = 0;
57 clockid_t cl;
58 int e;
59 pid_t dead_child, child;
60
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). */
63 {
64 dead_child = fork ();
65 if (dead_child == 0)
66 _exit (0);
67 if (dead_child < 0)
68 {
69 perror ("fork");
70 return 1;
71 }
72 int x;
73 if (wait (&x) != dead_child)
74 {
75 perror ("wait");
76 return 2;
77 }
78 }
79
80 /* POSIX says we should get ESRCH for this. */
81 e = clock_getcpuclockid (dead_child, &cl);
82 if (e != ENOSYS && e != ESRCH && e != EPERM)
83 {
84 printf ("clock_getcpuclockid on dead PID %d => %s\n",
85 dead_child, strerror (e));
86 result = 1;
87 }
88
89 /* Now give us a live child eating up CPU time. */
90 child = fork ();
91 if (child == 0)
92 {
93 chew_cpu ();
94 _exit (1);
95 }
96 if (child < 0)
97 {
98 perror ("fork");
99 return 1;
100 }
101
102 e = clock_getcpuclockid (child, &cl);
103 if (e == EPERM)
104 {
105 puts ("clock_getcpuclockid does not support other processes");
106 goto done;
107 }
108 if (e != 0)
109 {
110 printf ("clock_getcpuclockid on live PID %d => %s\n",
111 child, strerror (e));
112 result = 1;
113 goto done;
114 }
115
116 const clockid_t child_clock = cl;
117 struct timespec res;
118 if (clock_getres (child_clock, &res) < 0)
119 {
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;
124 }
5d619de4
L
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);
84060bad 128
9a29f1a2 129 struct timespec before;
84060bad
RM
130 if (clock_gettime (child_clock, &before) < 0)
131 {
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;
136 }
fb779be7 137 /* Should be close to 0.0. */
5d619de4
L
138 printf ("live PID %d before sleep => %ju.%.9ju\n",
139 child, (uintmax_t) before.tv_sec, (uintmax_t) before.tv_nsec);
84060bad 140
9a29f1a2 141 struct timespec sleeptime = { .tv_nsec = 100000000 };
84060bad
RM
142 e = clock_nanosleep (child_clock, 0, &sleeptime, NULL);
143 if (e == EINVAL || e == ENOTSUP || e == ENOSYS)
144 {
145 printf ("clock_nanosleep not supported for other process clock: %s\n",
146 strerror (e));
147 }
148 else if (e != 0)
149 {
150 printf ("clock_nanosleep on other process clock: %s\n", strerror (e));
151 result = 1;
152 }
153 else
154 {
155 struct timespec afterns;
156 if (clock_gettime (child_clock, &afterns) < 0)
157 {
158 printf ("clock_gettime on live PID %d clock %lx => %s\n",
159 child, (unsigned long int) child_clock, strerror (errno));
160 result = 1;
161 }
162 else
163 {
9a29f1a2
SL
164 printf ("live PID %d after sleep => %ju.%.9ju\n",
165 child, (uintmax_t) afterns.tv_sec,
166 (uintmax_t) afterns.tv_nsec);
84060bad
RM
167 }
168 }
169
170 if (kill (child, SIGKILL) != 0)
171 {
172 perror ("kill");
173 result = 2;
174 goto done;
175 }
176
177 /* Wait long enough to let the child finish dying. */
178
179 sleeptime.tv_nsec = 200000000;
fb779be7
TS
180 if (nanosleep (&sleeptime, NULL) != 0)
181 {
182 perror ("nanosleep");
183 result = 1;
184 goto done;
185 }
84060bad
RM
186
187 struct timespec dead;
188 if (clock_gettime (child_clock, &dead) < 0)
189 {
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;
194 }
9a29f1a2 195 /* Should be close to 0.1. */
5d619de4
L
196 printf ("dead PID %d => %ju.%.9ju\n",
197 child, (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
84060bad
RM
198
199 /* Now reap the child and verify that its clock is no longer valid. */
200 {
201 int x;
202 if (waitpid (child, &x, 0) != child)
203 {
204 perror ("waitpid");
205 result = 1;
206 }
207 }
208
209 if (clock_gettime (child_clock, &dead) == 0)
210 {
5d619de4 211 printf ("clock_gettime on reaped PID %d clock %lx => %ju%.9ju\n",
84060bad 212 child, (unsigned long int) child_clock,
5d619de4 213 (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
84060bad
RM
214 result = 1;
215 }
216 else
217 {
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));
222 }
223
224 if (clock_getres (child_clock, &dead) == 0)
225 {
5d619de4 226 printf ("clock_getres on reaped PID %d clock %lx => %ju%.9ju\n",
84060bad 227 child, (unsigned long int) child_clock,
5d619de4 228 (uintmax_t) dead.tv_sec, (uintmax_t) dead.tv_nsec);
84060bad
RM
229 result = 1;
230 }
231 else
232 {
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));
237 }
238
239 return result;
240
241 done:
242 {
243 if (kill (child, SIGKILL) != 0 && errno != ESRCH)
244 {
245 perror ("kill");
246 return 2;
247 }
248 int x;
249 if (waitpid (child, &x, 0) != child && errno != ECHILD)
250 {
251 perror ("waitpid");
252 return 2;
253 }
254 }
255
256 return result;
257}
258
259
84060bad
RM
260#define TEST_FUNCTION do_test ()
261#include "../test-skeleton.c"