147823Sbostic /*-
2*60765Sbostic * Copyright (c) 1980, 1991, 1993
3*60765Sbostic * The Regents of the University of California. All rights reserved.
447823Sbostic *
547823Sbostic * %sccs.include.redist.c%
621943Sdist */
721943Sdist
814476Ssam #ifndef lint
9*60765Sbostic static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 05/31/93";
1047823Sbostic #endif /* not lint */
111306Sbill
1250028Sbostic #include <sys/types.h>
1350033Schristos #if __STDC__
1450033Schristos # include <stdarg.h>
1550033Schristos #else
1650033Schristos # include <varargs.h>
1750033Schristos #endif
1850033Schristos
1950023Sbostic #include "csh.h"
2050023Sbostic #include "extern.h"
211306Sbill
221306Sbill /*
231306Sbill * C Shell - routines handling process timing and niceing
241306Sbill */
2550026Schristos static void pdeltat __P((struct timeval *, struct timeval *));
261306Sbill
2749992Sbostic void
settimes()281306Sbill settimes()
291306Sbill {
3049992Sbostic struct rusage ruch;
311306Sbill
3250028Sbostic (void) gettimeofday(&time0, NULL);
3349992Sbostic (void) getrusage(RUSAGE_SELF, &ru0);
3449992Sbostic (void) getrusage(RUSAGE_CHILDREN, &ruch);
3549992Sbostic ruadd(&ru0, &ruch);
361306Sbill }
371306Sbill
381306Sbill /*
391306Sbill * dotime is only called if it is truly a builtin function and not a
401306Sbill * prefix to another command
411306Sbill */
4249992Sbostic void
4350439Schristos /*ARGSUSED*/
dotime(v,t)4450439Schristos dotime(v, t)
4550439Schristos Char **v;
4650439Schristos struct command *t;
471306Sbill {
4849992Sbostic struct timeval timedol;
4949992Sbostic struct rusage ru1, ruch;
501306Sbill
5149992Sbostic (void) getrusage(RUSAGE_SELF, &ru1);
5249992Sbostic (void) getrusage(RUSAGE_CHILDREN, &ruch);
5349992Sbostic ruadd(&ru1, &ruch);
5450028Sbostic (void) gettimeofday(&timedol, NULL);
5549992Sbostic prusage(&ru0, &ru1, &timedol, &time0);
561306Sbill }
571306Sbill
581306Sbill /*
591306Sbill * donice is only called when it on the line by itself or with a +- value
601306Sbill */
6149992Sbostic void
6250439Schristos /*ARGSUSED*/
donice(v,t)6350439Schristos donice(v, t)
6450439Schristos Char **v;
6550439Schristos struct command *t;
661306Sbill {
6749992Sbostic register Char *cp;
6849992Sbostic int nval = 0;
691306Sbill
7049992Sbostic v++, cp = *v++;
7149992Sbostic if (cp == 0)
7249992Sbostic nval = 4;
7349992Sbostic else if (*v == 0 && any("+-", cp[0]))
7449992Sbostic nval = getn(cp);
7549992Sbostic (void) setpriority(PRIO_PROCESS, 0, nval);
761306Sbill }
771306Sbill
7849992Sbostic void
ruadd(ru,ru2)7910036Ssam ruadd(ru, ru2)
8049992Sbostic register struct rusage *ru, *ru2;
811306Sbill {
8249992Sbostic tvadd(&ru->ru_utime, &ru2->ru_utime);
8349992Sbostic tvadd(&ru->ru_stime, &ru2->ru_stime);
8449992Sbostic if (ru2->ru_maxrss > ru->ru_maxrss)
8549992Sbostic ru->ru_maxrss = ru2->ru_maxrss;
861306Sbill
8749992Sbostic ru->ru_ixrss += ru2->ru_ixrss;
8849992Sbostic ru->ru_idrss += ru2->ru_idrss;
8949992Sbostic ru->ru_isrss += ru2->ru_isrss;
9049992Sbostic ru->ru_minflt += ru2->ru_minflt;
9149992Sbostic ru->ru_majflt += ru2->ru_majflt;
9249992Sbostic ru->ru_nswap += ru2->ru_nswap;
9349992Sbostic ru->ru_inblock += ru2->ru_inblock;
9449992Sbostic ru->ru_oublock += ru2->ru_oublock;
9549992Sbostic ru->ru_msgsnd += ru2->ru_msgsnd;
9649992Sbostic ru->ru_msgrcv += ru2->ru_msgrcv;
9749992Sbostic ru->ru_nsignals += ru2->ru_nsignals;
9849992Sbostic ru->ru_nvcsw += ru2->ru_nvcsw;
9949992Sbostic ru->ru_nivcsw += ru2->ru_nivcsw;
1001306Sbill }
1011306Sbill
10249992Sbostic void
prusage(r0,r1,e,b)10310705Ssam prusage(r0, r1, e, b)
10449992Sbostic register struct rusage *r0, *r1;
10549992Sbostic struct timeval *e, *b;
1061306Sbill {
10749992Sbostic register time_t t =
10849992Sbostic (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
10949992Sbostic (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
11049992Sbostic (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
11149992Sbostic (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
11249992Sbostic register char *cp;
11349992Sbostic register long i;
11449992Sbostic register struct varent *vp = adrof(STRtime);
1151306Sbill
11649992Sbostic int ms =
11749992Sbostic (e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000;
11849992Sbostic
11949992Sbostic cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww";
12049992Sbostic
12149992Sbostic if (vp && vp->vec[0] && vp->vec[1])
12249992Sbostic cp = short2str(vp->vec[1]);
12350024Schristos
12449992Sbostic for (; *cp; cp++)
1251306Sbill if (*cp != '%')
12650439Schristos (void) fputc(*cp, cshout);
12749992Sbostic else if (cp[1])
12849992Sbostic switch (*++cp) {
1291306Sbill
13049992Sbostic case 'U': /* user CPU time used */
13110036Ssam pdeltat(&r1->ru_utime, &r0->ru_utime);
1321306Sbill break;
1331306Sbill
13449992Sbostic case 'S': /* system CPU time used */
13510036Ssam pdeltat(&r1->ru_stime, &r0->ru_stime);
1361306Sbill break;
1371306Sbill
13849992Sbostic case 'E': /* elapsed (wall-clock) time */
13949992Sbostic pcsecs((long) ms);
1401306Sbill break;
1411306Sbill
14249992Sbostic case 'P': /* percent time spent running */
14350024Schristos /* check if it did not run at all */
14450024Schristos i = (ms == 0) ? 0 : (t * 1000 / ms);
14550439Schristos /* nn.n% */
14650439Schristos (void) fprintf(cshout, "%ld.%01ld%%", i / 10, i % 10);
1471306Sbill break;
1481306Sbill
14949992Sbostic case 'W': /* number of swaps */
15010036Ssam i = r1->ru_nswap - r0->ru_nswap;
15150439Schristos (void) fprintf(cshout, "%ld", i);
1521306Sbill break;
1531306Sbill
15449992Sbostic case 'X': /* (average) shared text size */
15550439Schristos (void) fprintf(cshout, "%ld", t == 0 ? 0L :
15650439Schristos (r1->ru_ixrss - r0->ru_ixrss) / t);
1571306Sbill break;
1581306Sbill
15949992Sbostic case 'D': /* (average) unshared data size */
16050439Schristos (void) fprintf(cshout, "%ld", t == 0 ? 0L :
16149992Sbostic (r1->ru_idrss + r1->ru_isrss -
16249992Sbostic (r0->ru_idrss + r0->ru_isrss)) / t);
1631306Sbill break;
1641306Sbill
16549992Sbostic case 'K': /* (average) total data memory used */
16650439Schristos (void) fprintf(cshout, "%ld", t == 0 ? 0L :
16749992Sbostic ((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
16849992Sbostic (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
1691306Sbill break;
1701306Sbill
17149992Sbostic case 'M': /* max. Resident Set Size */
17250439Schristos (void) fprintf(cshout, "%ld", r1->ru_maxrss / 2L);
1731306Sbill break;
1741306Sbill
17549992Sbostic case 'F': /* page faults */
17650439Schristos (void) fprintf(cshout, "%ld", r1->ru_majflt - r0->ru_majflt);
1771306Sbill break;
1781306Sbill
17949992Sbostic case 'R': /* page reclaims */
18050439Schristos (void) fprintf(cshout, "%ld", r1->ru_minflt - r0->ru_minflt);
1811306Sbill break;
1821306Sbill
18349992Sbostic case 'I': /* FS blocks in */
18450439Schristos (void) fprintf(cshout, "%ld", r1->ru_inblock - r0->ru_inblock);
1851306Sbill break;
1861306Sbill
18749992Sbostic case 'O': /* FS blocks out */
18850439Schristos (void) fprintf(cshout, "%ld", r1->ru_oublock - r0->ru_oublock);
1891306Sbill break;
19049992Sbostic
19149992Sbostic case 'r': /* socket messages recieved */
19250439Schristos (void) fprintf(cshout, "%ld", r1->ru_msgrcv - r0->ru_msgrcv);
19349992Sbostic break;
19449992Sbostic
19549992Sbostic case 's': /* socket messages sent */
19650439Schristos (void) fprintf(cshout, "%ld", r1->ru_msgsnd - r0->ru_msgsnd);
19749992Sbostic break;
19849992Sbostic
19949992Sbostic case 'k': /* number of signals recieved */
20050439Schristos (void) fprintf(cshout, "%ld", r1->ru_nsignals-r0->ru_nsignals);
20149992Sbostic break;
20249992Sbostic
20349992Sbostic case 'w': /* num. voluntary context switches (waits) */
20450439Schristos (void) fprintf(cshout, "%ld", r1->ru_nvcsw - r0->ru_nvcsw);
20549992Sbostic break;
20649992Sbostic
20749992Sbostic case 'c': /* num. involuntary context switches */
20850439Schristos (void) fprintf(cshout, "%ld", r1->ru_nivcsw - r0->ru_nivcsw);
20949992Sbostic break;
21049992Sbostic }
21150439Schristos (void) fputc('\n', cshout);
2121306Sbill }
21310036Ssam
21449992Sbostic static void
pdeltat(t1,t0)21510036Ssam pdeltat(t1, t0)
21649992Sbostic struct timeval *t1, *t0;
21710036Ssam {
21849992Sbostic struct timeval td;
21910036Ssam
22049992Sbostic tvsub(&td, t1, t0);
22150439Schristos (void) fprintf(cshout, "%d.%01d", td.tv_sec, td.tv_usec / 100000);
22210036Ssam }
22310036Ssam
22449992Sbostic void
tvadd(tsum,t0)22510036Ssam tvadd(tsum, t0)
22649992Sbostic struct timeval *tsum, *t0;
22710036Ssam {
22810036Ssam
22949992Sbostic tsum->tv_sec += t0->tv_sec;
23049992Sbostic tsum->tv_usec += t0->tv_usec;
23149992Sbostic if (tsum->tv_usec > 1000000)
23249992Sbostic tsum->tv_sec++, tsum->tv_usec -= 1000000;
23310036Ssam }
23410036Ssam
23549992Sbostic void
tvsub(tdiff,t1,t0)23610036Ssam tvsub(tdiff, t1, t0)
23749992Sbostic struct timeval *tdiff, *t1, *t0;
23810036Ssam {
23910036Ssam
24049992Sbostic tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
24149992Sbostic tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
24249992Sbostic if (tdiff->tv_usec < 0)
24349992Sbostic tdiff->tv_sec--, tdiff->tv_usec += 1000000;
24410036Ssam }
24550439Schristos
24650439Schristos #define P2DIG(i) (void) fprintf(cshout, "%d%d", (i) / 10, (i) % 10)
24750439Schristos
24850439Schristos void
psecs(l)24950439Schristos psecs(l)
25050439Schristos long l;
25150439Schristos {
25250439Schristos register int i;
25350439Schristos
25450439Schristos i = l / 3600;
25550439Schristos if (i) {
25650439Schristos (void) fprintf(cshout, "%d:", i);
25750439Schristos i = l % 3600;
25850439Schristos P2DIG(i / 60);
25950439Schristos goto minsec;
26050439Schristos }
26150439Schristos i = l;
26250439Schristos (void) fprintf(cshout, "%d", i / 60);
26350439Schristos minsec:
26450439Schristos i %= 60;
26550439Schristos (void) fputc(':', cshout);
26650439Schristos P2DIG(i);
26750439Schristos }
26850439Schristos
26950439Schristos void
pcsecs(l)27050439Schristos pcsecs(l) /* PWP: print mm:ss.dd, l is in sec*100 */
27150439Schristos long l;
27250439Schristos {
27350439Schristos register int i;
27450439Schristos
27550439Schristos i = l / 360000;
27650439Schristos if (i) {
27750439Schristos (void) fprintf(cshout, "%d:", i);
27850439Schristos i = (l % 360000) / 100;
27950439Schristos P2DIG(i / 60);
28050439Schristos goto minsec;
28150439Schristos }
28250439Schristos i = l / 100;
28350439Schristos (void) fprintf(cshout, "%d", i / 60);
28450439Schristos minsec:
28550439Schristos i %= 60;
28650439Schristos (void) fputc(':', cshout);
28750439Schristos P2DIG(i);
28850439Schristos (void) fputc('.', cshout);
28950439Schristos P2DIG((int) (l % 100));
29050439Schristos }
291