blob: 661b2d4db190bb198a840a43d4c512b60b8d4c8b [file] [log] [blame]
/*
* Copyright (c) International Business Machines Corp., 2001
* Copyright (C) 2017 Cyril Hrubis <chrubis@suse.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* 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 <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 != 0)
tst_res(TFAIL, "buf1.tms_utime = %li", buf1.tms_utime);
else
tst_res(TPASS, "buf1.tms_utime = 0");
if (buf1.tms_stime != 0)
tst_res(TFAIL, "buf1.tms_stime = %li", buf1.tms_stime);
else
tst_res(TPASS, "buf1.tms_stime = 0");
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 = {
.tid = "times03",
.setup = setup,
.forks_child = 1,
.test_all = do_test,
};