1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (c) International Business Machines Corp., 2001 4 * Copyright (C) 2017 Cyril Hrubis <chrubis@suse.cz> 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 30static volatile int timeout; 31 32static void sighandler(int signal) 33{ 34 if (signal == SIGALRM) 35 timeout = 1; 36} 37 38static volatile int k; 39 40static 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 51static void generate_utime(void) 52{ 53 alarm(1); 54 work(); 55} 56 57static 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 78static 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 */ 183static void do_test(void) 184{ 185 int pid = SAFE_FORK(); 186 187 if (!pid) 188 verify_times(); 189} 190 191static void setup(void) 192{ 193 SAFE_SIGNAL(SIGALRM, sighandler); 194} 195 196static struct tst_test test = { 197 .setup = setup, 198 .forks_child = 1, 199 .test_all = do_test, 200}; 201