201 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C
		
	
	
	
| // SPDX-License-Identifier: GPL-2.0-or-later
 | |
| /*
 | |
|  * Copyright (c) International Business Machines Corp., 2001
 | |
|  * Copyright (C) 2017 Cyril Hrubis <chrubis@suse.cz>
 | |
|  */
 | |
| /*
 | |
|  * DESCRIPTION
 | |
|  *	Testcase to check the basic functionality of the times() system call.
 | |
|  *
 | |
|  * ALGORITHM
 | |
|  *	This testcase checks the values that times(2) system call returns.
 | |
|  *	Start a process, and spend some CPU time by performing a spin in
 | |
|  *	a for-loop. Then use the times() system call, to determine the
 | |
|  *	cpu time/sleep time, and other statistics.
 | |
|  *
 | |
|  * History
 | |
|  *	07/2001 John George
 | |
|  */
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #include <sys/times.h>
 | |
| #include <errno.h>
 | |
| #include <sys/wait.h>
 | |
| #include <time.h>
 | |
| #include <signal.h>
 | |
| #include <stdlib.h>
 | |
| 
 | |
| #include "tst_test.h"
 | |
| 
 | |
| static volatile int timeout;
 | |
| 
 | |
| static void sighandler(int signal)
 | |
| {
 | |
| 	if (signal == SIGALRM)
 | |
| 		timeout = 1;
 | |
| }
 | |
| 
 | |
| static volatile int k;
 | |
| 
 | |
| static void work(void)
 | |
| {
 | |
| 	int i, j;
 | |
| 
 | |
| 	while (!timeout)
 | |
| 		for (i = 0; i < 10000; i++)
 | |
| 			for (j = 0; j < 100; j++)
 | |
| 				k = i * j;
 | |
| 	timeout = 0;
 | |
| }
 | |
| 
 | |
| static void generate_utime(void)
 | |
| {
 | |
| 	alarm(1);
 | |
| 	work();
 | |
| }
 | |
| 
 | |
| static void generate_stime(void)
 | |
| {
 | |
| 	time_t start_time, end_time;
 | |
| 	struct tms buf;
 | |
| 
 | |
| 	/*
 | |
| 	 * At least some CPU time must be used in system space. This is
 | |
| 	 * achieved by executing the times(2) call for
 | |
| 	 * atleast 2 secs. This logic makes it independant
 | |
| 	 * of the processor speed.
 | |
| 	 */
 | |
| 	start_time = time(NULL);
 | |
| 	for (;;) {
 | |
| 		if (times(&buf) == -1)
 | |
| 			tst_res(TFAIL | TERRNO, "times failed");
 | |
| 		end_time = time(NULL);
 | |
| 		if ((end_time - start_time) > 2)
 | |
| 			return;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void verify_times(void)
 | |
| {
 | |
| 	int pid;
 | |
| 	struct tms buf1, buf2, buf3;
 | |
| 
 | |
| 	if (times(&buf1) == -1)
 | |
| 		tst_brk(TBROK | TERRNO, "times()");
 | |
| 
 | |
| 	if (buf1.tms_utime > 5)
 | |
| 		tst_res(TFAIL, "buf1.tms_utime = %li", buf1.tms_utime);
 | |
| 	else
 | |
| 		tst_res(TPASS, "buf1.tms_utime <= 5");
 | |
| 
 | |
| 	if (buf1.tms_stime > 5)
 | |
| 		tst_res(TFAIL, "buf1.tms_stime = %li", buf1.tms_stime);
 | |
| 	else
 | |
| 		tst_res(TPASS, "buf1.tms_stime <= 5");
 | |
| 
 | |
| 	generate_utime();
 | |
| 	generate_stime();
 | |
| 
 | |
| 	if (times(&buf2) == -1)
 | |
| 		tst_brk(TBROK | TERRNO, "times()");
 | |
| 
 | |
| 	if (buf2.tms_utime == 0)
 | |
| 		tst_res(TFAIL, "buf2.tms_utime = 0");
 | |
| 	else
 | |
| 		tst_res(TPASS, "buf2.tms_utime = %li", buf2.tms_utime);
 | |
| 
 | |
| 	if (buf1.tms_utime >= buf2.tms_utime) {
 | |
| 		tst_res(TFAIL, "buf1.tms_utime (%li) >= buf2.tms_utime (%li)",
 | |
| 			buf1.tms_utime, buf2.tms_utime);
 | |
| 	} else {
 | |
| 		tst_res(TPASS, "buf1.tms_utime (%li) < buf2.tms_utime (%li)",
 | |
| 			buf1.tms_utime, buf2.tms_utime);
 | |
| 	}
 | |
| 
 | |
| 	if (buf2.tms_stime == 0)
 | |
| 		tst_res(TFAIL, "buf2.tms_stime = 0");
 | |
| 	else
 | |
| 		tst_res(TPASS, "buf2.tms_stime = %li", buf2.tms_stime);
 | |
| 
 | |
| 	if (buf1.tms_stime >= buf2.tms_stime) {
 | |
| 		tst_res(TFAIL, "buf1.tms_stime (%li) >= buf2.tms_stime (%li)",
 | |
| 			buf1.tms_stime, buf2.tms_stime);
 | |
| 	} else {
 | |
| 		tst_res(TPASS, "buf1.tms_stime (%li) < buf2.tms_stime (%li)",
 | |
| 			buf1.tms_stime, buf2.tms_stime);
 | |
| 	}
 | |
| 
 | |
| 	if (buf2.tms_cutime != 0)
 | |
| 		tst_res(TFAIL, "buf2.tms_cutime = %li", buf2.tms_cutime);
 | |
| 	else
 | |
| 		tst_res(TPASS, "buf2.tms_cutime = 0");
 | |
| 
 | |
| 	if (buf2.tms_cstime != 0)
 | |
| 		tst_res(TFAIL, "buf2.tms_cstime = %li", buf2.tms_cstime);
 | |
| 	else
 | |
| 		tst_res(TPASS, "buf2.tms_cstime = 0");
 | |
| 
 | |
| 	pid = SAFE_FORK();
 | |
| 
 | |
| 	if (!pid) {
 | |
| 		generate_utime();
 | |
| 		generate_stime();
 | |
| 		exit(0);
 | |
| 	}
 | |
| 
 | |
| 	SAFE_WAITPID(pid, NULL, 0);
 | |
| 
 | |
| 	if (times(&buf3) == -1)
 | |
| 		tst_brk(TBROK | TERRNO, "times()");
 | |
| 
 | |
| 	if (buf2.tms_utime > buf3.tms_utime) {
 | |
| 		tst_res(TFAIL, "buf2.tms_utime (%li) > buf3.tms_utime (%li)",
 | |
| 			buf2.tms_utime, buf3.tms_utime);
 | |
| 	} else {
 | |
| 		tst_res(TPASS, "buf2.tms_utime (%li) <= buf3.tms_utime (%li)",
 | |
| 			buf2.tms_utime, buf3.tms_utime);
 | |
| 	}
 | |
| 
 | |
| 	if (buf2.tms_stime > buf3.tms_stime) {
 | |
| 		tst_res(TFAIL, "buf2.tms_stime (%li) > buf3.tms_stime (%li)",
 | |
| 			buf2.tms_stime, buf3.tms_stime);
 | |
| 	} else {
 | |
| 		tst_res(TPASS, "buf2.tms_stime (%li) <= buf3.tms_stime (%li)",
 | |
| 			buf2.tms_stime, buf3.tms_stime);
 | |
| 	}
 | |
| 
 | |
| 	if (buf3.tms_cutime == 0)
 | |
| 		tst_res(TFAIL, "buf3.tms_cutime = 0");
 | |
| 	else
 | |
| 		tst_res(TPASS, "buf3.tms_cutime = %ld", buf3.tms_cutime);
 | |
| 
 | |
| 	if (buf3.tms_cstime == 0)
 | |
| 		tst_res(TFAIL, "buf3.tms_cstime = 0");
 | |
| 	else
 | |
| 		tst_res(TPASS, "buf3.tms_cstime = %ld", buf3.tms_cstime);
 | |
| 
 | |
| 	exit(0);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Run the test in a child to reset times in case of -i option.
 | |
|  */
 | |
| static void do_test(void)
 | |
| {
 | |
| 	int pid = SAFE_FORK();
 | |
| 
 | |
| 	if (!pid)
 | |
| 		verify_times();
 | |
| }
 | |
| 
 | |
| static void setup(void)
 | |
| {
 | |
| 	SAFE_SIGNAL(SIGALRM, sighandler);
 | |
| }
 | |
| 
 | |
| static struct tst_test test = {
 | |
| 	.setup = setup,
 | |
| 	.forks_child = 1,
 | |
| 	.test_all = do_test,
 | |
| };
 |