Our times(3) just calls getrusage(2) and gettimeofday(2), converting seconds

to ticks.  Since ksh needs things in seconds it then converted them back.
Avoid the silliness and use the getrusage(2) and gettimeofday(2) directly.
With man page help from jmc@
From: Todd C. Miller <millert@cvs.openbsd.org>
This commit is contained in:
tg 2004-12-31 18:41:47 +00:00
parent 3cba14dc9d
commit f6e24ec417
8 changed files with 107 additions and 215 deletions

41
aclocal.m4 vendored
View File

@ -1,4 +1,4 @@
dnl $MirBSD: src/bin/ksh/aclocal.m4,v 2.4 2004/12/31 17:29:28 tg Exp $
dnl $MirBSD: src/bin/ksh/aclocal.m4,v 2.5 2004/12/31 18:41:46 tg Exp $
dnl-
dnl Copyright (c) 2004
dnl Thorsten "mirabile" Glaser <tg@66h.42h.de>
@ -281,45 +281,6 @@ AC_DEFUN(KSH_TIME_DECLARED,
])dnl
dnl
dnl
dnl Check for working times (ie, it exists and doesn't always return 0).
dnl Defines TIMES_BROKEN if it doesn't exist or if it always returns 0
dnl (also checks for existance of getrusage if times doesn't work).
dnl XXX: requires clock_t to be typedefed/defined...
AC_DEFUN(KSH_TIMES_CHECK,
[AC_CACHE_CHECK(if times() is present/working, ksh_cv_func_times_ok,
[AC_TRY_RUN([
#include <sys/types.h>
#include <sys/times.h>
/* if missing, clock_t is defined to be INT32 */
#if SIZEOF_INT == 4
# define INT32 int
#else /* SIZEOF_INT */
# if SIZEOF_LONG == 4
# define INT32 long
# else /* SIZEOF_LONG */
#error cannot find 32 bit type...
# endif /* SIZEOF_LONG */
#endif /* SIZEOF_INT */
main()
{
extern clock_t times();
struct tms tms;
times(&tms);
sleep(1);
if (times(&tms) == 0)
exit(1);
exit(0);
}
], ksh_cv_func_times_ok=yes, ksh_cv_func_times_ok=no,
AC_MSG_ERROR(cannot determine if times works when cross compiling)
)])
if test $ksh_cv_func_times_ok = no; then
AC_DEFINE(TIMES_BROKEN)
AC_CHECK_FUNCS(getrusage)
fi
])dnl
dnl
dnl
AC_DEFUN(KSH_C_VOID,
[AC_CACHE_CHECK(if compiler understands void, ksh_cv_c_void,
[AC_TRY_COMPILE(

116
c_sh.c
View File

@ -1,19 +1,18 @@
/** $MirBSD: src/bin/ksh/c_sh.c,v 2.10 2004/12/31 17:42:44 tg Exp $ */
/* $OpenBSD: c_sh.c,v 1.21 2004/12/18 22:35:41 millert Exp $ */
/** $MirBSD: src/bin/ksh/c_sh.c,v 2.11 2004/12/31 18:41:46 tg Exp $ */
/* $OpenBSD: c_sh.c,v 1.25 2004/12/22 18:48:56 millert Exp $ */
/*
* built-in Bourne commands
*/
#include "sh.h"
#include "ksh_stat.h" /* umask() */
#include "ksh_time.h"
#include "ksh_times.h"
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
__RCSID("$MirBSD: src/bin/ksh/c_sh.c,v 2.10 2004/12/31 17:42:44 tg Exp $");
static char *clocktos(clock_t t);
__RCSID("$MirBSD: src/bin/ksh/c_sh.c,v 2.11 2004/12/31 18:41:46 tg Exp $");
static void p_time(struct shf *, int, struct timeval *, int, char *, char *);
/* :, false and true */
int
@ -661,16 +660,31 @@ c_unset(char **wp)
return ret;
}
static void
p_time(struct shf *shf, int posix, struct timeval *tv, int width,
char *prefix, char *suffix)
{
if (posix)
shf_fprintf(shf, "%s%*ld.%02ld%s", prefix ? prefix : "",
width, (long)tv->tv_sec, tv->tv_usec / 10000, suffix);
else
shf_fprintf(shf, "%s%*ldm%ld.%02lds%s", prefix ? prefix : "",
width, (long)(tv->tv_sec / 60), (long)(tv->tv_sec % 60),
tv->tv_usec / 10000, suffix);
}
int
c_times(char **wp GCC_FUNC_ATTR(unused))
{
struct tms all;
struct rusage usage;
(void) ksh_times(&all);
shprintf("Shell: %8ss user ", clocktos(all.tms_utime));
shprintf("%8ss system\n", clocktos(all.tms_stime));
shprintf("Kids: %8ss user ", clocktos(all.tms_cutime));
shprintf("%8ss system\n", clocktos(all.tms_cstime));
(void) getrusage(RUSAGE_SELF, &usage);
p_time(shl_stdout, 0, &usage.ru_utime, 0, NULL, " ");
p_time(shl_stdout, 0, &usage.ru_stime, 0, NULL, "\n");
(void) getrusage(RUSAGE_CHILDREN, &usage);
p_time(shl_stdout, 0, &usage.ru_utime, 0, NULL, " ");
p_time(shl_stdout, 0, &usage.ru_stime, 0, NULL, "\n");
return 0;
}
@ -685,13 +699,15 @@ timex(struct op *t, int f)
#define TF_NOREAL BIT(1) /* don't report real time */
#define TF_POSIX BIT(2) /* report in posix format */
int rv = 0;
struct tms t0, t1, tms;
clock_t t0t, t1t = 0;
struct rusage ru0, ru1, cru0, cru1;
struct timeval usrtime, systime, tv0, tv1;
int tf = 0;
extern clock_t j_usrtime, j_systime; /* computed by j_wait */
extern struct timeval j_usrtime, j_systime; /* computed by j_wait */
char opts[1];
t0t = ksh_times(&t0);
gettimeofday(&tv0, NULL);
getrusage(RUSAGE_SELF, &ru0);
getrusage(RUSAGE_CHILDREN, &cru0);
if (t->left) {
/*
* Two ways of getting cpu usage of a command: just use t0
@ -701,33 +717,45 @@ timex(struct op *t, int f)
* pdksh tries to do the later (the j_usrtime hack doesn't
* really work as it only counts the last job).
*/
j_usrtime = j_systime = 0;
timerclear(&j_usrtime);
timerclear(&j_systime);
if (t->left->type == TCOM)
t->left->str = opts;
opts[0] = 0;
rv = execute(t->left, f | XTIME);
tf |= opts[0];
t1t = ksh_times(&t1);
gettimeofday(&tv1, NULL);
getrusage(RUSAGE_SELF, &ru1);
getrusage(RUSAGE_CHILDREN, &cru1);
} else
tf = TF_NOARGS;
if (tf & TF_NOARGS) { /* ksh93 - report shell times (shell+kids) */
tf |= TF_NOREAL;
tms.tms_utime = t0.tms_utime + t0.tms_cutime;
tms.tms_stime = t0.tms_stime + t0.tms_cstime;
timeradd(&ru0.ru_utime, &cru0.ru_utime, &usrtime);
timeradd(&ru0.ru_stime, &cru0.ru_stime, &systime);
} else {
tms.tms_utime = t1.tms_utime - t0.tms_utime + j_usrtime;
tms.tms_stime = t1.tms_stime - t0.tms_stime + j_systime;
timersub(&ru1.ru_utime, &ru0.ru_utime, &usrtime);
timeradd(&usrtime, &j_usrtime, &usrtime);
timersub(&ru1.ru_stime, &ru0.ru_stime, &systime);
timeradd(&systime, &j_systime, &systime);
}
if (!(tf & TF_NOREAL))
shf_fprintf(shl_out,
tf & TF_POSIX ? "real %8s\n" : "%8ss real ",
clocktos(t1t - t0t));
shf_fprintf(shl_out, tf & TF_POSIX ? "user %8s\n" : "%8ss user ",
clocktos(tms.tms_utime));
shf_fprintf(shl_out, tf & TF_POSIX ? "sys %8s\n" : "%8ss system\n",
clocktos(tms.tms_stime));
if (!(tf & TF_NOREAL)) {
timersub(&tv1, &tv0, &tv1);
if (tf & TF_POSIX)
p_time(shl_out, 1, &tv1, 5, "real ", "\n");
else
p_time(shl_out, 0, &tv1, 5, NULL, " real ");
}
if (tf & TF_POSIX)
p_time(shl_out, 1, &usrtime, 5, "user ", "\n");
else
p_time(shl_out, 0, &usrtime, 5, NULL, " user ");
if (tf & TF_POSIX)
p_time(shl_out, 1, &systime, 5, "sys ", "\n");
else
p_time(shl_out, 0, &systime, 5, NULL, " system\n");
shf_flush(shl_out);
return rv;
@ -766,30 +794,6 @@ timex_hook(struct op *t, char **volatile *app)
*app = wp;
}
static char *
clocktos(clock_t t)
{
static char temp[22]; /* enough for 64 bit clock_t */
int i;
char *cp = temp + sizeof(temp);
/* note: posix says must use max precision, ie, if clk_tck is
* 1000, must print 3 places after decimal (if non-zero, else 1).
*/
if (CLK_TCK != 100) /* convert to 1/100'ths */
t = (t < 1000000000/CLK_TCK) ?
(t * 100) / CLK_TCK : (t / CLK_TCK) * 100;
*--cp = '\0';
for (i = -2; i <= 0 || t > 0; i++) {
if (i == 0)
*--cp = '.';
*--cp = '0' + (char)(t%10);
t /= 10;
}
return cp;
}
/* exec with no args - args case is taken care of in comexec() */
int
c_exec(char **wp GCC_FUNC_ATTR(unused))

View File

@ -1,4 +1,4 @@
/** $MirBSD: src/bin/ksh/config.h,v 2.4 2004/12/31 17:29:28 tg Exp $ */
/** $MirBSD: src/bin/ksh/config.h,v 2.5 2004/12/31 18:41:46 tg Exp $ */
/* $OpenBSD: config.h,v 1.9 2003/10/22 07:40:38 jmc Exp $ */
/*
@ -142,9 +142,6 @@
/* Define if you have a sane <termio.h> header file */
/* #undef HAVE_TERMIO_H */
/* Define if you don't have times() or if it always returns 0 */
/* #undef TIMES_BROKEN */
/* Define if opendir() will open non-directory files */
/* #undef OPENDIR_DOES_NONDIR */

View File

@ -1,4 +1,4 @@
dnl $MirBSD: src/bin/ksh/configure.in,v 2.2 2004/12/28 22:44:39 tg Exp $
dnl $MirBSD: src/bin/ksh/configure.in,v 2.3 2004/12/31 18:41:47 tg Exp $
dnl
dnl Process this file with autoconf to produce a configure script
dnl
@ -79,7 +79,6 @@ KSH_FUNC_LSTAT
KSH_SYS_ERRLIST
KSH_SYS_SIGLIST
KSH_TIME_DECLARED
KSH_TIMES_CHECK
dnl
dnl Structures
dnl

36
jobs.c
View File

@ -1,5 +1,5 @@
/** $MirBSD: src/bin/ksh/jobs.c,v 2.7 2004/12/31 17:39:12 tg Exp $ */
/* $OpenBSD: jobs.c,v 1.26 2004/12/18 22:12:23 millert Exp $ */
/** $MirBSD: src/bin/ksh/jobs.c,v 2.8 2004/12/31 18:41:47 tg Exp $ */
/* $OpenBSD: jobs.c,v 1.30 2004/12/22 18:48:56 millert Exp $ */
/*
* Process and job control
@ -26,12 +26,13 @@
*/
#include "sh.h"
#include "ksh_stat.h"
#include <sys/stat.h>
#include "ksh_wait.h"
#include "ksh_times.h"
#include <sys/time.h>
#include <sys/resource.h>
#include "tty.h"
__RCSID("$MirBSD: src/bin/ksh/jobs.c,v 2.7 2004/12/31 17:39:12 tg Exp $");
__RCSID("$MirBSD: src/bin/ksh/jobs.c,v 2.8 2004/12/31 18:41:47 tg Exp $");
/* Start of system configuration stuff */
@ -137,8 +138,8 @@ struct job {
pid_t pgrp; /* process group of job */
pid_t ppid; /* pid of process that forked job */
INT32 age; /* number of jobs started */
clock_t systime; /* system time used by job */
clock_t usrtime; /* user time used by job */
struct timeval systime; /* system time used by job */
struct timeval usrtime; /* user time used by job */
Proc *proc_list; /* process list */
Proc *last_proc; /* last process in list */
Coproc_id coproc_id; /* 0 or id of coprocess output pipe */
@ -167,7 +168,7 @@ static const char *const lookup_msgs[] = {
"argument must be %job or process id",
NULL
};
clock_t j_systime, j_usrtime; /* user and system time of last j_waitjed job */
struct timeval j_systime, j_usrtime; /* user and system time of last j_waitjed job */
static Job *job_list; /* job list */
static Job *last_job;
@ -488,7 +489,8 @@ exchild(struct op *t, int flags, int close_fd)
*/
j->flags = (flags & XXCOM) ? JF_XXCOM
: ((flags & XBGND) ? 0 : (JF_FG|JF_USETTYMODE));
j->usrtime = j->systime = 0;
timerclear(&j->usrtime);
timerclear(&j->systime);
j->state = PRUNNING;
j->pgrp = 0;
j->ppid = procpid;
@ -1290,7 +1292,7 @@ j_sigchld(int sig GCC_FUNC_ATTR(unused))
Proc UNINITIALIZED(*p);
int pid;
WAIT_T status;
struct tms t0, t1;
struct rusage ru0, ru1;
#ifdef JOB_SIGS
/* Don't wait for any processes if a job is partially started.
@ -1305,7 +1307,7 @@ j_sigchld(int sig GCC_FUNC_ATTR(unused))
}
#endif /* JOB_SIGS */
ksh_times(&t0);
getrusage(RUSAGE_CHILDREN, &ru0);
do {
#ifdef JOB_SIGS
pid = ksh_waitpid(-1, &status, (WNOHANG|WUNTRACED));
@ -1316,7 +1318,7 @@ j_sigchld(int sig GCC_FUNC_ATTR(unused))
if (pid <= 0) /* return if would block (0) ... */
break; /* ... or no children or interrupted (-1) */
ksh_times(&t1);
getrusage(RUSAGE_CHILDREN, &ru1);
/* find job and process structures for this pid */
for (j = job_list; j != NULL; j = j->next)
@ -1329,13 +1331,15 @@ found:
warningf(true, "bad process waited for (pid = %d)",
pid);
*/
t0 = t1;
ru0 = ru1;
continue;
}
j->usrtime += t1.tms_cutime - t0.tms_cutime;
j->systime += t1.tms_cstime - t0.tms_cstime;
t0 = t1;
timeradd(&j->usrtime, &ru1.ru_utime, &j->usrtime);
timersub(&j->usrtime, &ru0.ru_utime, &j->usrtime);
timeradd(&j->systime, &ru1.ru_stime, &j->systime);
timersub(&j->systime, &ru0.ru_stime, &j->systime);
ru0 = ru1;
p->status = status;
#ifdef JOBS
if (WIFSTOPPED(status))

View File

@ -1,4 +1,4 @@
.\" $MirBSD: src/bin/ksh/ksh.1tbl,v 2.8 2004/12/31 18:22:54 tg Exp $
.\" $MirBSD: src/bin/ksh/ksh.1tbl,v 2.9 2004/12/31 18:41:47 tg Exp $
.\" $OpenBSD: ksh.1tbl,v 1.84 2004/12/22 18:58:44 millert Exp $
.\" $OpenBSD: sh.1tbl,v 1.53 2004/12/10 01:56:56 jaredy Exp $
.\"
@ -3864,21 +3864,24 @@ the user CPU time (time spent running in user mode) and the system CPU time
(time spent running in kernel mode).
Times are reported to standard error; the format of the output is:
.Pp
.Dl 0.00s real 0.00s user 0.00s system
.Dl "0m0.00s real 0m0.00s user 0m0.00s system"
.Pp
unless the
If the
.Fl p
option is given (only possible if
option is given the output is slightly longer:
.Bd -literal -offset indent
real 0.00
user 0.00
sys 0.00
.Ed
.Pp
It is an error to specify the
.Fl p
option unless
.Ar pipeline
is a simple command), in which case the output is slightly longer:
is a simple command.
.Pp
.Dl real 0.00
.Dl user 0.00
.Dl sys 0.00
.Pp
(the number of digits after the decimal may vary from system to system).
Note
that simple redirections of standard error do not effect the output of the
Simple redirections of standard error do not effect the output of the
.Ic time
command:
.Pp
@ -3889,8 +3892,13 @@ Times for the first command do not go to
.Dq afile ,
but those of the second command do.
.It Ic times
Print the accumulated user and system times used by the shell and by processes
which have exited that the shell started.
Print the accumulated user and system times used both by the shell
and by processes that the shell started which have exited.
The format of the output is:
.Bd -literal -offset indent
0m0.00s 0m0.00s
0m0.00s 0m0.00s
.Ed
.It Ic trap Op Ar handler signal ...
Sets a trap handler that is to be executed when any of the
specified signals are received.

View File

@ -1,22 +0,0 @@
/** $MirBSD: src/bin/ksh/ksh_times.h,v 2.1 2004/12/10 18:09:41 tg Exp $ */
/* $OpenBSD: ksh_times.h,v 1.2 1996/10/01 02:05:41 downsj Exp $ */
#ifndef KSH_TIMES_H
#define KSH_TIMES_H
/* Needed for clock_t on some systems (ie, NeXT in non-posix mode) */
#include "ksh_time.h"
#include <sys/times.h>
#ifdef TIMES_BROKEN
extern clock_t ksh_times(struct tms *);
#else /* TIMES_BROKEN */
# define ksh_times times
#endif /* TIMES_BROKEN */
#ifdef HAVE_TIMES
extern clock_t times(struct tms *);
#endif /* HAVE_TIMES */
#endif /* KSH_TIMES_H */

View File

@ -1,4 +1,4 @@
/** $MirBSD: src/bin/ksh/missing.c,v 2.4 2004/12/18 19:22:30 tg Exp $ */
/** $MirBSD: src/bin/ksh/missing.c,v 2.5 2004/12/31 18:41:47 tg Exp $ */
/* $OpenBSD: missing.c,v 1.5 2003/05/16 18:49:46 jsyn Exp $ */
/*
@ -9,7 +9,7 @@
#include "ksh_stat.h"
#include "ksh_dir.h"
__RCSID("$MirBSD: src/bin/ksh/missing.c,v 2.4 2004/12/18 19:22:30 tg Exp $");
__RCSID("$MirBSD: src/bin/ksh/missing.c,v 2.5 2004/12/31 18:41:47 tg Exp $");
#ifndef HAVE_MEMSET
void *
@ -189,65 +189,6 @@ strerror(err)
}
#endif /* !HAVE_STRERROR */
#ifdef TIMES_BROKEN
# include "ksh_time.h"
# include "ksh_times.h"
# ifdef HAVE_GETRUSAGE
# include <sys/resource.h>
# else /* HAVE_GETRUSAGE */
# include <sys/timeb.h>
# endif /* HAVE_GETRUSAGE */
clock_t
ksh_times(tms)
struct tms *tms;
{
static clock_t base_sec;
clock_t rv;
# ifdef HAVE_GETRUSAGE
{
struct timeval tv;
struct rusage ru;
getrusage(RUSAGE_SELF, &ru);
tms->tms_utime = ru.ru_utime.tv_sec * CLK_TCK
+ ru.ru_utime.tv_usec * CLK_TCK / 1000000;
tms->tms_stime = ru.ru_stime.tv_sec * CLK_TCK
+ ru.ru_stime.tv_usec * CLK_TCK / 1000000;
getrusage(RUSAGE_CHILDREN, &ru);
tms->tms_cutime = ru.ru_utime.tv_sec * CLK_TCK
+ ru.ru_utime.tv_usec * CLK_TCK / 1000000;
tms->tms_cstime = ru.ru_stime.tv_sec * CLK_TCK
+ ru.ru_stime.tv_usec * CLK_TCK / 1000000;
gettimeofday(&tv, NULL);
if (base_sec == 0)
base_sec = tv.tv_sec;
rv = (tv.tv_sec - base_sec) * CLK_TCK;
rv += tv.tv_usec * CLK_TCK / 1000000;
}
# else /* HAVE_GETRUSAGE */
/* Assume times() available, but always returns 0
* (also assumes ftime() available)
*/
{
struct timeb tb;
if (times(tms) == (clock_t) -1)
return (clock_t) -1;
ftime(&tb);
if (base_sec == 0)
base_sec = tb.time;
rv = (tb.time - base_sec) * CLK_TCK;
rv += tb.millitm * CLK_TCK / 1000;
}
# endif /* HAVE_GETRUSAGE */
return rv;
}
#endif /* TIMES_BROKEN */
#ifdef OPENDIR_DOES_NONDIR
/* Prevent opendir() from attempting to open non-directories. Such
* behavior can cause problems if it attempts to open special devices...