time.c revision 38520
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1987, 1988, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3528203Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1987, 1988, 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4128203Scharnier#if 0 421590Srgrimesstatic char sccsid[] = "@(#)time.c 8.1 (Berkeley) 6/6/93"; 4328203Scharnier#endif 4428203Scharnierstatic const char rcsid[] = 4538520Scracauer "$Id: time.c,v 1.10 1998/07/28 10:08:16 des Exp $"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 481590Srgrimes#include <sys/types.h> 491590Srgrimes#include <sys/time.h> 501590Srgrimes#include <sys/resource.h> 511590Srgrimes#include <sys/signal.h> 5217351Sjdp#include <sys/sysctl.h> 5318889Sjkh#include <stdlib.h> 5418889Sjkh#include <sys/wait.h> 5517351Sjdp 5617351Sjdp#include <err.h> 571590Srgrimes#include <stdio.h> 5837888Sdes#include <string.h> 5928203Scharnier#include <unistd.h> 6038520Scracauer#include <signal.h> 611590Srgrimes 6217351Sjdpstatic int getstathz __P((void)); 6328203Scharnierstatic void usage __P((void)); 6417351Sjdp 6528203Scharnierint 661590Srgrimesmain(argc, argv) 671590Srgrimes int argc; 681590Srgrimes char **argv; 691590Srgrimes{ 7037855Sphk extern char *optarg; 7137855Sphk extern int optind; 7237855Sphk 731590Srgrimes register int pid; 7437913Sdes int aflag, ch, lflag, status; 751590Srgrimes struct timeval before, after; 761590Srgrimes struct rusage ru; 7737888Sdes FILE *out = stderr; 7837888Sdes char *ofn = NULL; 7938520Scracauer int exitonsig = 0; /* Die with same signal as child */ 801590Srgrimes 8137913Sdes aflag = lflag = 0; 8237913Sdes while ((ch = getopt(argc, argv, "alo:")) != -1) 831590Srgrimes switch((char)ch) { 8437855Sphk case 'a': 8537888Sdes aflag = 1; 8637855Sphk break; 8737913Sdes case 'l': 8837913Sdes lflag = 1; 8937913Sdes break; 9037888Sdes case 'o': 9137888Sdes ofn = optarg; 9237855Sphk break; 931590Srgrimes case '?': 941590Srgrimes default: 9528203Scharnier usage(); 961590Srgrimes } 971590Srgrimes 981590Srgrimes if (!(argc -= optind)) 991590Srgrimes exit(0); 1001590Srgrimes argv += optind; 1011590Srgrimes 10237888Sdes if (ofn) { 10337913Sdes if ((out = fopen(ofn, aflag ? "a" : "w")) == NULL) 10437913Sdes err(1, "%s", ofn); 10537913Sdes setvbuf(out, (char *)NULL, _IONBF, (size_t)0); 10637888Sdes } 10737855Sphk 1081590Srgrimes gettimeofday(&before, (struct timezone *)NULL); 1091590Srgrimes switch(pid = vfork()) { 1101590Srgrimes case -1: /* error */ 11128203Scharnier err(1, "time"); 1121590Srgrimes /* NOTREACHED */ 1131590Srgrimes case 0: /* child */ 1141590Srgrimes execvp(*argv, argv); 11528203Scharnier warn("%s", *argv); 1161590Srgrimes _exit(1); 1171590Srgrimes /* NOTREACHED */ 1181590Srgrimes } 1191590Srgrimes /* parent */ 1201590Srgrimes (void)signal(SIGINT, SIG_IGN); 1211590Srgrimes (void)signal(SIGQUIT, SIG_IGN); 1221590Srgrimes while (wait3(&status, 0, &ru) != pid); /* XXX use waitpid */ 1231590Srgrimes gettimeofday(&after, (struct timezone *)NULL); 12438520Scracauer if ( ! WIFEXITED(status)) 12528203Scharnier warnx("command terminated abnormally"); 12638520Scracauer if (WIFSIGNALED(status)) 12738520Scracauer exitonsig = WTERMSIG(status); 1281590Srgrimes after.tv_sec -= before.tv_sec; 1291590Srgrimes after.tv_usec -= before.tv_usec; 1301590Srgrimes if (after.tv_usec < 0) 1311590Srgrimes after.tv_sec--, after.tv_usec += 1000000; 13237855Sphk fprintf(out, "%9ld.%02ld real ", after.tv_sec, after.tv_usec/10000); 13337855Sphk fprintf(out, "%9ld.%02ld user ", 1341590Srgrimes ru.ru_utime.tv_sec, ru.ru_utime.tv_usec/10000); 13537855Sphk fprintf(out, "%9ld.%02ld sys\n", 1361590Srgrimes ru.ru_stime.tv_sec, ru.ru_stime.tv_usec/10000); 1371590Srgrimes if (lflag) { 13817351Sjdp int hz = getstathz(); 13911873Spst u_long ticks; 1401590Srgrimes 1411590Srgrimes ticks = hz * (ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) + 1421590Srgrimes hz * (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) / 1000000; 14311873Spst 14411873Spst /* 14511873Spst * If our round-off on the tick calculation still puts us at 0, 14611873Spst * then always assume at least one tick. 14711873Spst */ 14811873Spst if (ticks == 0) 14911873Spst ticks = 1; 15011873Spst 15137855Sphk fprintf(out, "%10ld %s\n", 1521590Srgrimes ru.ru_maxrss, "maximum resident set size"); 15337855Sphk fprintf(out, "%10ld %s\n", 1541590Srgrimes ru.ru_ixrss / ticks, "average shared memory size"); 15537855Sphk fprintf(out, "%10ld %s\n", 1561590Srgrimes ru.ru_idrss / ticks, "average unshared data size"); 15737855Sphk fprintf(out, "%10ld %s\n", 1581590Srgrimes ru.ru_isrss / ticks, "average unshared stack size"); 15937855Sphk fprintf(out, "%10ld %s\n", 1601590Srgrimes ru.ru_minflt, "page reclaims"); 16137855Sphk fprintf(out, "%10ld %s\n", 1621590Srgrimes ru.ru_majflt, "page faults"); 16337855Sphk fprintf(out, "%10ld %s\n", 1641590Srgrimes ru.ru_nswap, "swaps"); 16537855Sphk fprintf(out, "%10ld %s\n", 1661590Srgrimes ru.ru_inblock, "block input operations"); 16737855Sphk fprintf(out, "%10ld %s\n", 1681590Srgrimes ru.ru_oublock, "block output operations"); 16937855Sphk fprintf(out, "%10ld %s\n", 1701590Srgrimes ru.ru_msgsnd, "messages sent"); 17137855Sphk fprintf(out, "%10ld %s\n", 1721590Srgrimes ru.ru_msgrcv, "messages received"); 17337855Sphk fprintf(out, "%10ld %s\n", 1741590Srgrimes ru.ru_nsignals, "signals received"); 17537855Sphk fprintf(out, "%10ld %s\n", 1761590Srgrimes ru.ru_nvcsw, "voluntary context switches"); 17737855Sphk fprintf(out, "%10ld %s\n", 1781590Srgrimes ru.ru_nivcsw, "involuntary context switches"); 1791590Srgrimes } 18038520Scracauer if (exitonsig) { 18138520Scracauer if (signal(exitonsig, SIG_DFL) < 0) 18238520Scracauer perror("signal"); 18338520Scracauer else 18438520Scracauer kill(getpid(), exitonsig); 18538520Scracauer } 18618889Sjkh exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE); 1871590Srgrimes} 18817351Sjdp 18928203Scharnierstatic void 19028203Scharnierusage() 19128203Scharnier{ 19237913Sdes fprintf(stderr, "usage: time [-al] [-o file] command\n"); 19337913Sdes exit(1); 19428203Scharnier} 19528203Scharnier 19617351Sjdp/* 19717351Sjdp * Return the frequency of the kernel's statistics clock. 19817351Sjdp */ 19917351Sjdpstatic int 20017351Sjdpgetstathz() 20117351Sjdp{ 20217351Sjdp struct clockinfo clockrate; 20317351Sjdp int mib[2]; 20417351Sjdp size_t size; 20517351Sjdp 20617351Sjdp mib[0] = CTL_KERN; 20717351Sjdp mib[1] = KERN_CLOCKRATE; 20817351Sjdp size = sizeof clockrate; 20917351Sjdp if (sysctl(mib, 2, &clockrate, &size, NULL, 0) == -1) 21017351Sjdp err(1, "sysctl kern.clockrate"); 21117351Sjdp return clockrate.stathz; 21217351Sjdp} 213