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 43static volatile int timeout; 44 45static void sighandler(int signal) 46{ 47 if (signal == SIGALRM) 48 timeout = 1; 49} 50 51static volatile int k; 52 53static 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 64static void generate_utime(void) 65{ 66 alarm(1); 67 work(); 68} 69 70static 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 91static 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 != 0) 100 tst_res(TFAIL, "buf1.tms_utime = %li", buf1.tms_utime); 101 else 102 tst_res(TPASS, "buf1.tms_utime = 0"); 103 104 if (buf1.tms_stime != 0) 105 tst_res(TFAIL, "buf1.tms_stime = %li", buf1.tms_stime); 106 else 107 tst_res(TPASS, "buf1.tms_stime = 0"); 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 */ 196static void do_test(void) 197{ 198 int pid = SAFE_FORK(); 199 200 if (!pid) 201 verify_times(); 202} 203 204static void setup(void) 205{ 206 SAFE_SIGNAL(SIGALRM, sighandler); 207} 208 209static struct tst_test test = { 210 .tid = "times03", 211 .setup = setup, 212 .forks_child = 1, 213 .test_all = do_test, 214}; 215