summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Doc/Zsh/params.yo24
-rw-r--r--Src/exec.c12
-rw-r--r--Src/jobs.c133
-rw-r--r--Src/signals.c39
-rw-r--r--Src/zsh.h5
-rw-r--r--configure.ac26
7 files changed, 189 insertions, 57 deletions
diff --git a/ChangeLog b/ChangeLog
index 453ec96da..76c06cdaa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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,
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index fd12b4f20..d9ab5c1f3 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -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()
 
diff --git a/Src/exec.c b/Src/exec.c
index 47d20bb93..437233bad 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -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;
 
diff --git a/Src/jobs.c b/Src/jobs.c
index 0c3960e87..9bb8bbbd7 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -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;
diff --git a/Src/signals.c b/Src/signals.c
index df9120d2d..fd5d47e71 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -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;
diff --git a/Src/zsh.h b/Src/zsh.h
index bde274d9b..8d27e2014 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -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
diff --git a/configure.ac b/configure.ac
index 11b97b9da..3bb6e3b35 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1448,6 +1448,32 @@ 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 --------------------------------------------
 AC_CACHE_VAL(zsh_cv_cs_path,