20467: Reintroduce rusage-based escapes for TIMEFMT.

This commit is contained in:
Peter Stephenson 2004-10-08 14:36:51 +00:00
parent cc72740775
commit 8a67a66a61
7 changed files with 189 additions and 57 deletions

View file

@ -1,3 +1,10 @@
2004-10-08 Peter Stephenson <pws@csr.com>
* 20467: configure.ac, Doc/Zsh/params.yo, Src/exec.c, Src/jobs.c,
Src/signals.c, Src/zsh.h: Finally reintroduce the
TIMEFMT escapes from struct rusage removed ages ago. Uses more
sophisticated autconf tests to make configuration seamless.
2004-10-07 Peter Stephenson <pws@csr.com>
* 20462: configure.ac, Src/exec.c, Src/init.c, Src/jobs.c,

View file

@ -1047,14 +1047,34 @@ vindex(TIMEFMT)
item(tt(TIMEFMT))(
The format of process time reports with the tt(time) keyword.
The default is `tt(%E real %U user %S system %P %J)'.
Recognizes the following escape sequences:
Recognizes the following escape sequences, although not all
may be available on all systems, and some that are available
may not be useful:
startsitem()
sitem(tt(%%))(A `tt(%)'.)
sitem(tt(%U))(CPU seconds spent in user mode.)
sitem(tt(%S))(CPU seconds spent in kernel mode.)
sitem(tt(%E))(Elapsed time in seconds.)
sitem(tt(%P))(The CPU percentage, computed as (tt(%U)PLUS()tt(%S))/tt(%E).)
sitem(tt(%P))(The CPU percentage, computed as
(100*tt(%U)PLUS()tt(%S))/tt(%E).)
sitem(tt(%W))(Number of times the process was swapped.)
sitem(tt(%X))(The average amount in (shared) text space used in Kbytes.)
sitem(tt(%D))(The average amount in (unshared) data/stack space used in
Kbytes.)
sitem(tt(%K))(The total space used (%X+%D) in Kbytes.)
sitem(tt(%M))(The maximum memory the process had in use at any time in
Kbytes.)
sitem(tt(%F))(The number of major page faults (page needed to be brought
from disk).)
sitem(tt(%R))(The number of minor page faults.)
sitem(tt(%I))(The number of input operations.)
sitem(tt(%O))(The number of output operations.)
sitem(tt(%r))(The number of socket messages received.)
sitem(tt(%s))(The number of socket messages sent.)
sitem(tt(%k))(The number of signals received.)
sitem(tt(%w))(Number of voluntary context switches (waits).)
sitem(tt(%c))(Number of involuntary context switches.)
sitem(tt(%J))(The name of this job.)
endsitem()

View file

@ -1162,18 +1162,14 @@ execpline(Estate state, wordcode slcode, int how, int last1)
(jobtab[list_pipe_job].stat & STAT_STOPPED)))) {
pid_t pid;
int synch[2];
struct timezone dummy_tz;
struct timeval bgtime;
pipe(synch);
gettimeofday(&bgtime, &dummy_tz);
/* Any reason this isn't zfork? */
if ((pid = fork()) == -1) {
if ((pid = zfork(&bgtime)) == -1) {
trashzle();
close(synch[0]);
close(synch[1]);
putc('\n', stderr);
fprintf(stderr, "zsh: job can't be suspended\n");
fflush(stderr);
makerunning(jn);
@ -1300,15 +1296,11 @@ execpline2(Estate state, wordcode pcode,
if (wc_code(code) >= WC_CURSH && (how & Z_SYNC)) {
int synch[2];
struct timeval bgtime;
struct timezone dummy_tz;
pipe(synch);
gettimeofday(&bgtime, &dummy_tz);
/* any reason this isn't zfork? */
if ((pid = fork()) == -1) {
if ((pid = zfork(&bgtime)) == -1) {
close(synch[0]);
close(synch[1]);
zerr("fork failed: %e", NULL, errno);
} else if (pid) {
char dummy, *text;

View file

@ -271,6 +271,7 @@ get_usage(void)
}
#ifndef HAVE_GETRUSAGE
/* Update status of process that we have just WAIT'ed for */
/**/
@ -278,32 +279,19 @@ void
update_process(Process pn, int status)
{
struct timezone dummy_tz;
#ifdef HAVE_GETRUSAGE
struct timeval childs, childu;
#else
long childs, childu;
#endif
#ifdef HAVE_GETRUSAGE
childs = child_usage.ru_stime;
childu = child_usage.ru_utime;
#else
childs = shtms.tms_cstime;
childu = shtms.tms_cutime;
#endif
/* get time-accounting info */
get_usage();
gettimeofday(&pn->endtime, &dummy_tz); /* record time process exited */
pn->status = status; /* save the status returned by WAIT */
#ifdef HAVE_GETRUSAGE
dtime(&pn->ti.sys, &childs, &child_usage.ru_stime);
dtime(&pn->ti.usr, &childu, &child_usage.ru_utime);
#else
pn->ti.st = shtms.tms_cstime - childs; /* compute process system space time */
pn->ti.ut = shtms.tms_cutime - childu; /* compute process user space time */
#endif
}
#endif
/* Update status of job, possibly printing it */
@ -563,6 +551,9 @@ printtime(struct timeval *real, child_times_t *ti, char *desc)
{
char *s;
double elapsed_time, user_time, system_time;
#ifdef HAVE_GETRUSAGE
double total_time;
#endif
int percent;
if (!desc)
@ -572,10 +563,11 @@ printtime(struct timeval *real, child_times_t *ti, char *desc)
elapsed_time = real->tv_sec + real->tv_usec / 1000000.0;
#ifdef HAVE_GETRUSAGE
user_time = ti->usr.tv_sec + ti->usr.tv_usec / 1000000.0;
system_time = ti->sys.tv_sec + ti->sys.tv_usec / 1000000.0;
user_time = ti->ru_utime.tv_sec + ti->ru_utime.tv_usec / 1000000.0;
system_time = ti->ru_stime.tv_sec + ti->ru_stime.tv_usec / 1000000.0;
percent = 100.0 * (user_time + system_time)
/ (real->tv_sec + real->tv_usec / 1000000.0);
total_time = user_time + system_time;
#else
set_clktck();
user_time = ti->ut / (double) clktck;
@ -620,6 +612,97 @@ printtime(struct timeval *real, child_times_t *ti, char *desc)
case 'P':
fprintf(stderr, "%d%%", percent);
break;
#ifdef HAVE_STRUCT_RUSAGE_RU_NSWAP
case 'W':
fprintf(stderr, "%ld", ti->ru_nswap);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS
case 'X':
fprintf(stderr, "%ld", (long)(ti->ru_ixrss / total_time));
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_IDRSS
case 'D':
fprintf(stderr, "%ld",
(long) ((ti->ru_idrss
#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS
+ ti->ru_isrss
#endif
) / total_time));
break;
#endif
#if defined(HAVE_STRUCT_RUSAGE_RU_IDRSS) || \
defined(HAVE_STRUCT_RUSAGE_RU_ISRSS) || \
defined(HAVE_STRUCT_RUSAGE_RU_IXRSS)
case 'K':
/* treat as D if X not available */
fprintf(stderr, "%ld",
(long) ((
#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS
ti->ru_ixrss
#else
0
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_IDRSS
+ ti->ru_idrss
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS
+ ti->ru_isrss
#endif
) / total_time));
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_MAXRSS
case 'M':
fprintf(stderr, "%ld", ti->ru_maxrss / 1024);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_MAJFLT
case 'F':
fprintf(stderr, "%ld", ti->ru_majflt);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_MINFLT
case 'R':
fprintf(stderr, "%ld", ti->ru_minflt);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_INBLOCK
case 'I':
fprintf(stderr, "%ld", ti->ru_inblock);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_OUBLOCK
case 'O':
fprintf(stderr, "%ld", ti->ru_oublock);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_MSGRCV
case 'r':
fprintf(stderr, "%ld", ti->ru_msgrcv);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_MSGSND
case 's':
fprintf(stderr, "%ld", ti->ru_msgsnd);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_NSIGNALS
case 'k':
fprintf(stderr, "%ld", ti->ru_nsignals);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_NVCSW
case 'w':
fprintf(stderr, "%ld", ti->ru_nvcsw);
break;
#endif
#ifdef HAVE_STRUCT_RUSAGE_RU_NIVCSW
case 'c':
fprintf(stderr, "%ld", ti->ru_nivcsw);
break;
#endif
case 'J':
fprintf(stderr, "%s", desc);
break;
@ -683,8 +766,9 @@ should_report_time(Job j)
return 0;
#ifdef HAVE_GETRUSAGE
reporttime -= j->procs->ti.usr.tv_sec + j->procs->ti.sys.tv_sec;
if (j->procs->ti.usr.tv_usec + j->procs->ti.sys.tv_usec >= 1000000)
reporttime -= j->procs->ti.ru_utime.tv_sec + j->procs->ti.ru_stime.tv_sec;
if (j->procs->ti.ru_utime.tv_usec +
j->procs->ti.ru_stime.tv_usec >= 1000000)
reporttime--;
return reporttime <= 0;
#else
@ -1214,20 +1298,15 @@ shelltime(void)
{
struct timezone dummy_tz;
struct timeval dtimeval, now;
#ifdef HAVE_GETRUSAGE
struct rusage ru;
child_times_t ti;
#else
struct timeinfo ti;
#ifndef HAVE_GETRUSAGE
struct tms buf;
#endif
gettimeofday(&now, &dummy_tz);
#ifdef HAVE_GETRUSAGE
getrusage(RUSAGE_SELF, &ru);
ti.sys = ru.ru_stime;
ti.usr = ru.ru_utime;
getrusage(RUSAGE_SELF, &ti);
#else
times(&buf);
@ -1237,9 +1316,7 @@ shelltime(void)
printtime(dtime(&dtimeval, &shtimer, &now), &ti, "shell");
#ifdef HAVE_GETRUSAGE
getrusage(RUSAGE_CHILDREN, &ru);
ti.sys = ru.ru_stime;
ti.usr = ru.ru_utime;
getrusage(RUSAGE_CHILDREN, &ti);
#else
ti.ut = buf.tms_cutime;
ti.st = buf.tms_cstime;

View file

@ -400,18 +400,6 @@ signal_suspend(int sig, int sig2)
return ret;
}
/* What flavor of waitpid/wait3/wait shall we use? */
#ifdef HAVE_WAITPID
# define WAIT(pid, statusp, options) waitpid(pid, statusp, options)
#else
# ifdef HAVE_WAIT3
# define WAIT(pid, statusp, options) wait3((void *) statusp, options, NULL)
# else
# define WAIT(pid, statusp, options) wait(statusp)
# endif
#endif
/* the signal handler */
/**/
@ -471,7 +459,25 @@ zhandler(int sig)
int *procsubval = &cmdoutval;
struct execstack *es = exstack;
pid = WAIT(-1, &status, WNOHANG|WUNTRACED); /* reap the child process */
/*
* Reap the child process.
* If we want usage information, we need to use wait3.
*/
#ifdef HAVE_WAIT3
# ifdef HAVE_GETRUSAGE
struct rusage ru;
pid = wait3((void *)&status, WNOHANG|WUNTRACED, &ru);
# else
pid = wait3((void *)&status, WNOHANG|WUNTRACED, NULL);
# endif
#else
# ifdef HAVE_WAITPID
pid = waitpid(-1, &status, WNOHANG|WUNTRACED);
# else
pid = wait(&status);
# endif
#endif
if (!pid) /* no more children to reap */
break;
@ -504,7 +510,14 @@ zhandler(int sig)
/* Find the process and job containing this pid and update it. */
if (findproc(pid, &jn, &pn, 0)) {
#if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE)
struct timezone dummy_tz;
gettimeofday(&pn->endtime, &dummy_tz);
pn->status = status;
pn->ti = ru;
#else
update_process(pn, status);
#endif
update_job(jn);
} else if (findproc(pid, &jn, &pn, 1)) {
pn->status = status;

View file

@ -740,10 +740,7 @@ struct timeinfo {
/* node in job process lists */
#ifdef HAVE_GETRUSAGE
typedef struct {
struct timeval sys;
struct timeval usr;
} child_times_t;
typedef struct rusage child_times_t;
#else
typedef struct timeinfo child_times_t;
#endif

View file

@ -1447,6 +1447,32 @@ if test $zsh_cv_rlimit_vmem_is_as = yes; then
fi
dnl --------------------------------------------
dnl Check for members of struct rusage
dnl --------------------------------------------
if test $ac_cv_func_getrusage = yes; then
AC_CHECK_MEMBERS([struct rusage.ru_maxrss,
struct rusage.ru_ixrss,
struct rusage.ru_idrss,
struct rusage.ru_isrss,
struct rusage.ru_minflt,
struct rusage.ru_majflt,
struct rusage.ru_nswap,
struct rusage.ru_inblock,
struct rusage.ru_oublock,
struct rusage.ru_msgsnd,
struct rusage.ru_msgrcv,
struct rusage.ru_nsignals,
struct rusage.ru_nvcsw,
struct rusage.ru_nivcsw],,,
[#include <sys/types.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/resource.h>])
fi
dnl --------------------------------------------
dnl CHECK FOR DEFAULT PATH (used for command -p)
dnl --------------------------------------------