1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 * Copyright (C) 2017 Cyril Hrubis <chrubis@suse.cz>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 /*
20 * DESCRIPTION
21 * Testcase to check the basic functionality of the times() system call.
22 *
23 * ALGORITHM
24 * This testcase checks the values that times(2) system call returns.
25 * Start a process, and spend some CPU time by performing a spin in
26 * a for-loop. Then use the times() system call, to determine the
27 * cpu time/sleep time, and other statistics.
28 *
29 * History
30 * 07/2001 John George
31 */
32
33 #include <sys/types.h>
34 #include <sys/times.h>
35 #include <errno.h>
36 #include <sys/wait.h>
37 #include <time.h>
38 #include <signal.h>
39 #include <stdlib.h>
40
41 #include "tst_test.h"
42
43 static volatile int timeout;
44
sighandler(int signal)45 static void sighandler(int signal)
46 {
47 if (signal == SIGALRM)
48 timeout = 1;
49 }
50
51 static volatile int k;
52
work(void)53 static void work(void)
54 {
55 int i, j;
56
57 while (!timeout)
58 for (i = 0; i < 10000; i++)
59 for (j = 0; j < 100; j++)
60 k = i * j;
61 timeout = 0;
62 }
63
generate_utime(void)64 static void generate_utime(void)
65 {
66 alarm(1);
67 work();
68 }
69
generate_stime(void)70 static void generate_stime(void)
71 {
72 time_t start_time, end_time;
73 struct tms buf;
74
75 /*
76 * At least some CPU time must be used in system space. This is
77 * achieved by executing the times(2) call for
78 * atleast 2 secs. This logic makes it independant
79 * of the processor speed.
80 */
81 start_time = time(NULL);
82 for (;;) {
83 if (times(&buf) == -1)
84 tst_res(TFAIL | TERRNO, "times failed");
85 end_time = time(NULL);
86 if ((end_time - start_time) > 2)
87 return;
88 }
89 }
90
verify_times(void)91 static void verify_times(void)
92 {
93 int pid;
94 struct tms buf1, buf2, buf3;
95
96 if (times(&buf1) == -1)
97 tst_brk(TBROK | TERRNO, "times()");
98
99 if (buf1.tms_utime > 5)
100 tst_res(TFAIL, "buf1.tms_utime = %li", buf1.tms_utime);
101 else
102 tst_res(TPASS, "buf1.tms_utime <= 5");
103
104 if (buf1.tms_stime > 5)
105 tst_res(TFAIL, "buf1.tms_stime = %li", buf1.tms_stime);
106 else
107 tst_res(TPASS, "buf1.tms_stime <= 5");
108
109 generate_utime();
110 generate_stime();
111
112 if (times(&buf2) == -1)
113 tst_brk(TBROK | TERRNO, "times()");
114
115 if (buf2.tms_utime == 0)
116 tst_res(TFAIL, "buf2.tms_utime = 0");
117 else
118 tst_res(TPASS, "buf2.tms_utime = %li", buf2.tms_utime);
119
120 if (buf1.tms_utime >= buf2.tms_utime) {
121 tst_res(TFAIL, "buf1.tms_utime (%li) >= buf2.tms_utime (%li)",
122 buf1.tms_utime, buf2.tms_utime);
123 } else {
124 tst_res(TPASS, "buf1.tms_utime (%li) < buf2.tms_utime (%li)",
125 buf1.tms_utime, buf2.tms_utime);
126 }
127
128 if (buf2.tms_stime == 0)
129 tst_res(TFAIL, "buf2.tms_stime = 0");
130 else
131 tst_res(TPASS, "buf2.tms_stime = %li", buf2.tms_stime);
132
133 if (buf1.tms_stime >= buf2.tms_stime) {
134 tst_res(TFAIL, "buf1.tms_stime (%li) >= buf2.tms_stime (%li)",
135 buf1.tms_stime, buf2.tms_stime);
136 } else {
137 tst_res(TPASS, "buf1.tms_stime (%li) < buf2.tms_stime (%li)",
138 buf1.tms_stime, buf2.tms_stime);
139 }
140
141 if (buf2.tms_cutime != 0)
142 tst_res(TFAIL, "buf2.tms_cutime = %li", buf2.tms_cutime);
143 else
144 tst_res(TPASS, "buf2.tms_cutime = 0");
145
146 if (buf2.tms_cstime != 0)
147 tst_res(TFAIL, "buf2.tms_cstime = %li", buf2.tms_cstime);
148 else
149 tst_res(TPASS, "buf2.tms_cstime = 0");
150
151 pid = SAFE_FORK();
152
153 if (!pid) {
154 generate_utime();
155 generate_stime();
156 exit(0);
157 }
158
159 SAFE_WAITPID(pid, NULL, 0);
160
161 if (times(&buf3) == -1)
162 tst_brk(TBROK | TERRNO, "times()");
163
164 if (buf2.tms_utime > buf3.tms_utime) {
165 tst_res(TFAIL, "buf2.tms_utime (%li) > buf3.tms_utime (%li)",
166 buf2.tms_utime, buf3.tms_utime);
167 } else {
168 tst_res(TPASS, "buf2.tms_utime (%li) <= buf3.tms_utime (%li)",
169 buf2.tms_utime, buf3.tms_utime);
170 }
171
172 if (buf2.tms_stime > buf3.tms_stime) {
173 tst_res(TFAIL, "buf2.tms_stime (%li) > buf3.tms_stime (%li)",
174 buf2.tms_stime, buf3.tms_stime);
175 } else {
176 tst_res(TPASS, "buf2.tms_stime (%li) <= buf3.tms_stime (%li)",
177 buf2.tms_stime, buf3.tms_stime);
178 }
179
180 if (buf3.tms_cutime == 0)
181 tst_res(TFAIL, "buf3.tms_cutime = 0");
182 else
183 tst_res(TPASS, "buf3.tms_cutime = %ld", buf3.tms_cutime);
184
185 if (buf3.tms_cstime == 0)
186 tst_res(TFAIL, "buf3.tms_cstime = 0");
187 else
188 tst_res(TPASS, "buf3.tms_cstime = %ld", buf3.tms_cstime);
189
190 exit(0);
191 }
192
193 /*
194 * Run the test in a child to reset times in case of -i option.
195 */
do_test(void)196 static void do_test(void)
197 {
198 int pid = SAFE_FORK();
199
200 if (!pid)
201 verify_times();
202 }
203
setup(void)204 static void setup(void)
205 {
206 SAFE_SIGNAL(SIGALRM, sighandler);
207 }
208
209 static struct tst_test test = {
210 .setup = setup,
211 .forks_child = 1,
212 .test_all = do_test,
213 };
214