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