/* * 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 <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 != 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 = { .setup = setup, .forks_child = 1, .test_all = do_test, };