Home | History | Annotate | Download | only in times
      1 /*
      2  * Copyright (c) International Business Machines  Corp., 2001
      3  * Copyright (C) 2017 Cyril Hrubis <chrubis (at) 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 
     45 static void sighandler(int signal)
     46 {
     47 	if (signal == SIGALRM)
     48 		timeout = 1;
     49 }
     50 
     51 static volatile int k;
     52 
     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 
     64 static void generate_utime(void)
     65 {
     66 	alarm(1);
     67 	work();
     68 }
     69 
     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 
     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 != 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  */
    196 static void do_test(void)
    197 {
    198 	int pid = SAFE_FORK();
    199 
    200 	if (!pid)
    201 		verify_times();
    202 }
    203 
    204 static void setup(void)
    205 {
    206 	SAFE_SIGNAL(SIGALRM, sighandler);
    207 }
    208 
    209 static struct tst_test test = {
    210 	.tid = "times03",
    211 	.setup = setup,
    212 	.forks_child = 1,
    213 	.test_all = do_test,
    214 };
    215