sh.time.c revision 59415
1266125Sjhb/* $Header: /src/pub/tcsh/sh.time.c,v 3.21 2000/01/14 22:57:29 christos Exp $ */
2281887Sjhb/*
3266125Sjhb * sh.time.c: Shell time keeping and printing.
4266125Sjhb */
5266125Sjhb/*-
6266125Sjhb * Copyright (c) 1980, 1991 The	Regents	of the University of California.
7266125Sjhb * All rights reserved.
8266125Sjhb *
9266125Sjhb * Redistribution and use in source and	binary forms, with or without
10266125Sjhb * modification, are permitted provided	that the following conditions
11266125Sjhb * are met:
12266125Sjhb * 1. Redistributions of source	code must retain the above copyright
13266125Sjhb *    notice, this list	of conditions and the following	disclaimer.
14266125Sjhb * 2. Redistributions in binary	form must reproduce the	above copyright
15266125Sjhb *    notice, this list	of conditions and the following	disclaimer in the
16266125Sjhb *    documentation and/or other materials provided with the distribution.
17266125Sjhb * 3. All advertising materials	mentioning features or use of this software
18266125Sjhb *    must display the following acknowledgement:
19266125Sjhb *	This product includes software developed by the	University of
20266125Sjhb *	California, Berkeley and its contributors.
21266125Sjhb * 4. Neither the name of the University nor the names of its contributors
22266125Sjhb *    may be used to endorse or	promote	products derived from this software
23266125Sjhb *    without specific prior written permission.
24266125Sjhb *
25266125Sjhb * THIS	SOFTWARE IS PROVIDED BY	THE REGENTS AND	CONTRIBUTORS ``AS IS'' AND
26266125Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27266125Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28266125Sjhb * ARE DISCLAIMED.  IN NO EVENT	SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29266125Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR	CONSEQUENTIAL
30266125Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31266125Sjhb * OR SERVICES;	LOSS OF	USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32266125Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33266125Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34266125Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35266125Sjhb * SUCH	DAMAGE.
36266125Sjhb */
37266125Sjhb#include "sh.h"
38266125Sjhb
39266125SjhbRCSID("$Id: sh.time.c,v 3.21 2000/01/14 22:57:29 christos Exp $")
40266125Sjhb
41266125Sjhb#ifdef SUNOS4
42266125Sjhb# include <machine/param.h>
43266125Sjhb#endif /* SUNOS4 */
44266125Sjhb
45266125Sjhb/*
46 * C Shell - routines handling process timing and niceing
47 */
48#ifdef BSDTIMES
49# ifndef RUSAGE_SELF
50#  define	RUSAGE_SELF	0
51#  define	RUSAGE_CHILDREN	-1
52# endif	/* RUSAGE_SELF */
53#else /* BSDTIMES */
54struct tms times0;
55#endif /* BSDTIMES */
56
57#if !defined(BSDTIMES) && !defined(_SEQUENT_)
58# ifdef	POSIX
59static	void	pdtimet	__P((clock_t, clock_t));
60# else /* ! POSIX */
61static	void	pdtimet	__P((time_t, time_t));
62# endif	/* ! POSIX */
63#else /* BSDTIMES || _SEQUENT_ */
64static	void	tvadd	__P((timeval_t *, timeval_t *));
65static	void	pdeltat	__P((timeval_t *, timeval_t *));
66#endif /* BSDTIMES || _SEQUENT_	*/
67
68void
69settimes()
70{
71#ifdef BSDTIMES
72    struct sysrusage ruch;
73#ifdef convex
74    memset(&ru0, 0, sizeof(ru0));
75    memset(&ruch, 0, sizeof(ruch));
76#endif /* convex */
77
78    (void) gettimeofday(&time0,	NULL);
79    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru0);
80    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
81    ruadd(&ru0,	&ruch);
82#else
83# ifdef	_SEQUENT_
84    struct process_stats ruch;
85
86    (void) get_process_stats(&time0, PS_SELF, &ru0, &ruch);
87    ruadd(&ru0,	&ruch);
88# else	/* _SEQUENT_ */
89    seconds0 = time(NULL);
90#  ifndef COHERENT
91    time0 = times(&times0);
92#  else	/* !COHERENT */
93    time0 = HZ * seconds0;
94    times(&times0);
95#  endif /* !COHERENT */
96    times0.tms_stime +=	times0.tms_cstime;
97    times0.tms_utime +=	times0.tms_cutime;
98    times0.tms_cstime =	0;
99    times0.tms_cutime =	0;
100# endif	/* _SEQUENT_ */
101#endif /* BSDTIMES */
102}
103
104/*
105 * dotime is only called if it is truly	a builtin function and not a
106 * prefix to another command
107 */
108/*ARGSUSED*/
109void
110dotime(v, c)
111    Char **v;
112    struct command *c;
113{
114#ifdef BSDTIMES
115    timeval_t timedol;
116    struct sysrusage ru1, ruch;
117#ifdef convex
118    memset(&ru1, 0, sizeof(ru1));
119    memset(&ruch, 0, sizeof(ruch));
120#endif /* convex */
121
122    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru1);
123    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
124    ruadd(&ru1,	&ruch);
125    (void) gettimeofday(&timedol, NULL);
126    prusage(&ru0, &ru1,	&timedol, &time0);
127#else
128# ifdef	_SEQUENT_
129    timeval_t timedol;
130    struct process_stats ru1, ruch;
131
132    (void) get_process_stats(&timedol, PS_SELF,	&ru1, &ruch);
133    ruadd(&ru1,	&ruch);
134    prusage(&ru0, &ru1,	&timedol, &time0);
135# else /* _SEQUENT_ */
136#  ifndef POSIX
137    time_t  timedol;
138#  else	/* POSIX */
139    clock_t timedol;
140#  endif /* POSIX */
141
142    struct tms times_dol;
143
144#ifndef	COHERENT
145    timedol = times(&times_dol);
146#else
147    timedol = HZ * time(NULL);
148    times(&times_dol);
149#endif
150    times_dol.tms_stime	+= times_dol.tms_cstime;
151    times_dol.tms_utime	+= times_dol.tms_cutime;
152    times_dol.tms_cstime = 0;
153    times_dol.tms_cutime = 0;
154    prusage(&times0, &times_dol, timedol, time0);
155# endif	/* _SEQUENT_ */
156#endif /* BSDTIMES */
157    USE(c);
158    USE(v);
159}
160
161/*
162 * donice is only called when it on the	line by	itself or with a +- value
163 */
164/*ARGSUSED*/
165void
166donice(v, c)
167    register Char **v;
168    struct command *c;
169{
170    register Char *cp;
171    int	    nval = 0;
172
173    USE(c);
174    v++, cp = *v++;
175    if (cp == 0)
176	nval = 4;
177    else if (*v	== 0 &&	any("+-", cp[0]))
178	nval = getn(cp);
179#ifdef BSDNICE
180    (void) setpriority(PRIO_PROCESS, 0,	nval);
181#else /* BSDNICE */
182    (void) nice(nval);
183#endif /* BSDNICE */
184}
185
186#ifdef BSDTIMES
187void
188ruadd(ru, ru2)
189    register struct sysrusage *ru,	*ru2;
190{
191    tvadd(&ru->ru_utime, &ru2->ru_utime);
192    tvadd(&ru->ru_stime, &ru2->ru_stime);
193    if (ru2->ru_maxrss > ru->ru_maxrss)
194	ru->ru_maxrss =	ru2->ru_maxrss;
195
196    ru->ru_ixrss += ru2->ru_ixrss;
197    ru->ru_idrss += ru2->ru_idrss;
198    ru->ru_isrss += ru2->ru_isrss;
199    ru->ru_minflt += ru2->ru_minflt;
200    ru->ru_majflt += ru2->ru_majflt;
201    ru->ru_nswap += ru2->ru_nswap;
202    ru->ru_inblock += ru2->ru_inblock;
203    ru->ru_oublock += ru2->ru_oublock;
204    ru->ru_msgsnd += ru2->ru_msgsnd;
205    ru->ru_msgrcv += ru2->ru_msgrcv;
206    ru->ru_nsignals += ru2->ru_nsignals;
207    ru->ru_nvcsw += ru2->ru_nvcsw;
208    ru->ru_nivcsw += ru2->ru_nivcsw;
209
210# ifdef	convex
211    tvadd(&ru->ru_exutime, &ru2->ru_exutime);
212    ru->ru_utotal += ru2->ru_utotal;
213    ru->ru_usamples += ru2->ru_usamples;
214    ru->ru_stotal += ru2->ru_stotal;
215    ru->ru_ssamples += ru2->ru_ssamples;
216# endif	/* convex */
217}
218
219#else /* BSDTIMES */
220# ifdef	_SEQUENT_
221void
222ruadd(ru, ru2)
223    register struct process_stats *ru, *ru2;
224{
225    tvadd(&ru->ps_utime, &ru2->ps_utime);
226    tvadd(&ru->ps_stime, &ru2->ps_stime);
227    if (ru2->ps_maxrss > ru->ps_maxrss)
228	ru->ps_maxrss =	ru2->ps_maxrss;
229
230    ru->ps_pagein += ru2->ps_pagein;
231    ru->ps_reclaim += ru2->ps_reclaim;
232    ru->ps_zerofill += ru2->ps_zerofill;
233    ru->ps_pffincr += ru2->ps_pffincr;
234    ru->ps_pffdecr += ru2->ps_pffdecr;
235    ru->ps_swap	+= ru2->ps_swap;
236    ru->ps_syscall += ru2->ps_syscall;
237    ru->ps_volcsw += ru2->ps_volcsw;
238    ru->ps_involcsw += ru2->ps_involcsw;
239    ru->ps_signal += ru2->ps_signal;
240    ru->ps_lread += ru2->ps_lread;
241    ru->ps_lwrite += ru2->ps_lwrite;
242    ru->ps_bread += ru2->ps_bread;
243    ru->ps_bwrite += ru2->ps_bwrite;
244    ru->ps_phread += ru2->ps_phread;
245    ru->ps_phwrite += ru2->ps_phwrite;
246}
247
248# endif	/* _SEQUENT_ */
249#endif /* BSDTIMES */
250
251#ifdef BSDTIMES
252
253/*
254 * PWP:	the LOG1024 and	pagetok	stuff taken from the top command,
255 * written by William LeFebvre
256 */
257/* Log base 2 of 1024 is 10 (2^10 == 1024) */
258#define	LOG1024		10
259
260/* Convert clicks (kernel pages) to kbytes ... */
261/* If there is no PGSHIFT defined, assume it is	11 */
262/* Is this needed for compatability with some old flavor of 4.2	or 4.1?	*/
263#ifdef SUNOS4
264# ifndef PGSHIFT
265#  define pagetok(size)	  ((size) << 1)
266# else
267#  if PGSHIFT>10
268#   define pagetok(size)   ((size) << (PGSHIFT - LOG1024))
269#  else
270#   define pagetok(size)   ((size) >> (LOG1024 - PGSHIFT))
271#  endif
272# endif
273#endif
274
275/*
276 * if any other	machines return	wierd values in	the ru_i* stuff, put
277 * the adjusting macro here:
278 */
279#ifdef SUNOS4
280# define IADJUST(i)	(pagetok(i)/2)
281#else /* SUNOS4	*/
282# ifdef	convex
283   /*
284    * convex has megabytes * CLK_TCK
285    * multiply by 100 since we use time	in 100ths of a second in prusage
286    */
287#  define IADJUST(i) (((i) << 10) / CLK_TCK * 100)
288# else /* convex */
289#  define IADJUST(i)	(i)
290# endif	/* convex */
291#endif /* SUNOS4 */
292
293void
294prusage(r0, r1,	e, b)
295    register struct sysrusage *r0,	*r1;
296    timeval_t *e, *b;
297
298#else /* BSDTIMES */
299# ifdef	_SEQUENT_
300void
301prusage(r0, r1,	e, b)
302    register struct process_stats *r0, *r1;
303    timeval_t *e, *b;
304
305# else /* _SEQUENT_ */
306void
307prusage(bs, es,	e, b)
308    struct tms *bs, *es;
309
310#  ifndef POSIX
311    time_t  e, b;
312
313#  else	/* POSIX */
314    clock_t e, b;
315
316#  endif /* POSIX */
317# endif	/* _SEQUENT_ */
318#endif /* BSDTIMES */
319{
320#ifdef BSDTIMES
321    register time_t t =
322    (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec)	* 100 +
323    (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
324    (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec)	* 100 +
325    (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
326
327#else
328# ifdef	_SEQUENT_
329    register time_t t =
330    (r1->ps_utime.tv_sec - r0->ps_utime.tv_sec)	* 100 +
331    (r1->ps_utime.tv_usec - r0->ps_utime.tv_usec) / 10000 +
332    (r1->ps_stime.tv_sec - r0->ps_stime.tv_sec)	* 100 +
333    (r1->ps_stime.tv_usec - r0->ps_stime.tv_usec) / 10000;
334
335# else /* _SEQUENT_ */
336#  ifndef POSIX
337    register time_t t =	(es->tms_utime - bs->tms_utime +
338			 es->tms_stime - bs->tms_stime)	* 100 /	HZ;
339
340#  else	/* POSIX */
341    register clock_t t = (es->tms_utime	- bs->tms_utime	+
342			  es->tms_stime	- bs->tms_stime) * 100 / clk_tck;
343
344#  endif /* POSIX */
345# endif	/* _SEQUENT_ */
346#endif /* BSDTIMES */
347
348    register char *cp;
349    register long i;
350    register struct varent *vp = adrof(STRtime);
351
352#ifdef BSDTIMES
353# ifdef	convex
354    static struct system_information sysinfo;
355    long long memtmp;	/* let memory calculations exceede 2Gb */
356# endif	/* convex */
357    int	    ms = (int)
358    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
359
360    cp = "%Uu %Ss %E %P	%X+%Dk %I+%Oio %Fpf+%Ww";
361#else /* !BSDTIMES */
362# ifdef	_SEQUENT_
363    int	    ms = (int)
364    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
365
366    cp = "%Uu %Ss %E %P	%I+%Oio	%Fpf+%Ww";
367# else /* !_SEQUENT_ */
368#  ifndef POSIX
369    time_t ms = ((time_t)((e - b) / HZ) * 100) +
370		 (time_t)(((e - b) % HZ) * 100) / HZ;
371#  else	/* POSIX */
372    clock_t ms = ((clock_t)((e - b) / clk_tck) * 100) +
373		  (clock_t)(((e - b) % clk_tck) * 100) / clk_tck;
374#  endif /* POSIX */
375
376    cp = "%Uu %Ss %E %P";
377
378    /*
379     * the tms stuff is	not very precise, so we	fudge it.
380     * granularity fix:	can't be more than 100%
381     * this breaks in multi-processor systems...
382     * maybe I should take it out and let people see more then 100%
383     * utilizations.
384     */
385#  if 0
386    if (ms < t && ms !=	0)
387	ms = t;
388#  endif
389# endif	/*! _SEQUENT_ */
390#endif /* !BSDTIMES */
391#ifdef TDEBUG
392    xprintf("es->tms_utime %lu bs->tms_utime %lu\n",
393	    es->tms_utime, bs->tms_utime);
394    xprintf("es->tms_stime %lu bs->tms_stime %lu\n",
395	    es->tms_stime, bs->tms_stime);
396    xprintf("ms	%lu e %lu b %lu\n", ms,	e, b);
397    xprintf("t %lu\n", t);
398#endif /* TDEBUG */
399
400    if (vp && vp->vec[0] && vp->vec[1])
401	cp = short2str(vp->vec[1]);
402    for	(; *cp;	cp++)
403	if (*cp	!= '%')
404	    xputchar(*cp);
405	else if	(cp[1])
406	    switch (*++cp) {
407
408	    case 'U':		/* user	CPU time used */
409#ifdef BSDTIMES
410		pdeltat(&r1->ru_utime, &r0->ru_utime);
411#else
412# ifdef	_SEQUENT_
413		pdeltat(&r1->ps_utime, &r0->ps_utime);
414# else /* _SEQUENT_ */
415#  ifndef POSIX
416		pdtimet(es->tms_utime, bs->tms_utime);
417#  else	/* POSIX */
418		pdtimet(es->tms_utime, bs->tms_utime);
419#  endif /* POSIX */
420# endif	/* _SEQUENT_ */
421#endif /* BSDTIMES */
422		break;
423
424	    case 'S':		/* system CPU time used	*/
425#ifdef BSDTIMES
426		pdeltat(&r1->ru_stime, &r0->ru_stime);
427#else
428# ifdef	_SEQUENT_
429		pdeltat(&r1->ps_stime, &r0->ps_stime);
430# else /* _SEQUENT_ */
431#  ifndef POSIX
432		pdtimet(es->tms_stime, bs->tms_stime);
433#  else	/* POSIX */
434		pdtimet(es->tms_stime, bs->tms_stime);
435#  endif /* POSIX */
436# endif	/* _SEQUENT_ */
437#endif /* BSDTIMES */
438		break;
439
440	    case 'E':		/* elapsed (wall-clock)	time */
441#ifdef BSDTIMES
442		pcsecs((long) ms);
443#else /* BSDTIMES */
444		pcsecs(ms);
445#endif /* BSDTIMES */
446		break;
447
448	    case 'P':		/* percent time	spent running */
449		/* check if the	process	did not	run */
450#ifdef convex
451		/*
452		 * scale the cpu %- ages by the	number of processors
453		 * available on	this machine
454		 */
455		if ((sysinfo.cpu_count == 0) &&
456		    (getsysinfo(SYSINFO_SIZE, &sysinfo)	< 0))
457		    sysinfo.cpu_count =	1;
458		    i =	(ms == 0) ? 0 :	(t * 1000.0 / (ms * sysinfo.cpu_count));
459#else /* convex	*/
460		i = (ms	== 0) ?	0 : (t * 1000.0 / ms);
461#endif /* convex */
462		xprintf("%ld.%01ld%%", i / 10, i % 10);	/* nn.n% */
463		break;
464
465#ifdef BSDTIMES
466	    case 'W':		/* number of swaps */
467		i = r1->ru_nswap - r0->ru_nswap;
468		xprintf("%ld", i);
469		break;
470
471#ifdef convex
472	    case 'X':		/* (average) shared text size */
473		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_ixrss -
474				 (long long)r0->ru_ixrss) /
475			 (long long)t);
476		xprintf("%lu", (unsigned long)memtmp);
477
478		break;
479
480	    case 'D':		/* (average) unshared data size	*/
481		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_idrss +
482				 (long long)r1->ru_isrss -
483				 ((long	long)r0->ru_idrss +
484				  (long	long)r0->ru_isrss)) /
485			 (long long)t);
486		xprintf("%lu", (unsigned long)memtmp);
487		break;
488
489	    case 'K':		/* (average) total data	memory used  */
490		memtmp = (t == 0 ? 0LL : IADJUST(((long	long)r1->ru_ixrss +
491				  (long	long)r1->ru_isrss +
492				  (long	long)r1->ru_idrss) -
493				  ((long long)r0->ru_ixrss +
494				   (long long)r0->ru_idrss +
495				   (long long)r0->ru_isrss)) /
496			 (long long)t);
497		xprintf("%lu", (unsigned long)memtmp);
498		break;
499#else /* !convex */
500	    case 'X':		/* (average) shared text size */
501		xprintf("%ld", t == 0 ?	0L :
502			IADJUST(r1->ru_ixrss - r0->ru_ixrss) / t);
503		break;
504
505	    case 'D':		/* (average) unshared data size	*/
506		xprintf("%ld", t == 0 ?	0L :
507			IADJUST(r1->ru_idrss + r1->ru_isrss -
508				(r0->ru_idrss +	r0->ru_isrss)) / t);
509		break;
510
511	    case 'K':		/* (average) total data	memory used  */
512		xprintf("%ld", t == 0 ?	0L :
513			IADJUST((r1->ru_ixrss +	r1->ru_isrss + r1->ru_idrss) -
514			   (r0->ru_ixrss + r0->ru_idrss	+ r0->ru_isrss)) / t);
515		break;
516#endif /* convex */
517	    case 'M':		/* max.	Resident Set Size */
518#ifdef SUNOS4
519		xprintf("%ld", pagetok(r1->ru_maxrss));
520#else
521# ifdef	convex
522		xprintf("%ld", r1->ru_maxrss * 4L);
523# else /* !convex */
524		xprintf("%ld", r1->ru_maxrss / 2L);
525# endif	/* convex */
526#endif /* SUNOS4 */
527		break;
528
529	    case 'F':		/* page	faults */
530		xprintf("%ld", r1->ru_majflt - r0->ru_majflt);
531		break;
532
533	    case 'R':		/* page	reclaims */
534		xprintf("%ld", r1->ru_minflt - r0->ru_minflt);
535		break;
536
537	    case 'I':		/* FS blocks in	*/
538		xprintf("%ld", r1->ru_inblock -	r0->ru_inblock);
539		break;
540
541	    case 'O':		/* FS blocks out */
542		xprintf("%ld", r1->ru_oublock -	r0->ru_oublock);
543		break;
544
545# ifdef	convex
546	    case 'C':			/*  CPU	parallelization	factor */
547		if (r1->ru_usamples	!= 0LL)	{
548		    long long parr = ((r1->ru_utotal * 100LL) /
549				      r1->ru_usamples);
550		    xprintf("%d.%02d", (int)(parr/100), (int)(parr%100));
551		} else
552		    xprintf("?");
553		break;
554# endif	/* convex */
555	    case 'r':		/* PWP:	socket messages	recieved */
556		xprintf("%ld", r1->ru_msgrcv - r0->ru_msgrcv);
557		break;
558
559	    case 's':		/* PWP:	socket messages	sent */
560		xprintf("%ld", r1->ru_msgsnd - r0->ru_msgsnd);
561		break;
562
563	    case 'k':		/* PWP:	signals	received */
564		xprintf("%ld", r1->ru_nsignals - r0->ru_nsignals);
565		break;
566
567	    case 'w':		/* PWP:	voluntary context switches (waits) */
568		xprintf("%ld", r1->ru_nvcsw - r0->ru_nvcsw);
569		break;
570
571	    case 'c':		/* PWP:	involuntary context switches */
572		xprintf("%ld", r1->ru_nivcsw - r0->ru_nivcsw);
573		break;
574#else /* BSDTIMES */
575# ifdef	_SEQUENT_
576	    case 'W':		/* number of swaps */
577		i = r1->ps_swap	- r0->ps_swap;
578		xprintf("%ld", i);
579		break;
580
581	    case 'M':
582		xprintf("%ld", r1->ps_maxrss / 2);
583		break;
584
585	    case 'F':
586		xprintf("%ld", r1->ps_pagein - r0->ps_pagein);
587		break;
588
589	    case 'R':
590		xprintf("%ld", r1->ps_reclaim -	r0->ps_reclaim);
591		break;
592
593	    case 'I':
594		xprintf("%ld", r1->ps_bread - r0->ps_bread);
595		break;
596
597	    case 'O':
598		xprintf("%ld", r1->ps_bwrite - r0->ps_bwrite);
599		break;
600
601	    case 'k':
602		xprintf("%ld", r1->ps_signal - r0->ps_signal);
603		break;
604
605	    case 'w':
606		xprintf("%ld", r1->ps_volcsw - r0->ps_volcsw);
607		break;
608
609	    case 'c':
610		xprintf("%ld", r1->ps_involcsw - r0->ps_involcsw);
611		break;
612
613	    case 'Z':
614		xprintf("%ld", r1->ps_zerofill - r0->ps_zerofill);
615		break;
616
617	    case 'i':
618		xprintf("%ld", r1->ps_pffincr -	r0->ps_pffincr);
619		break;
620
621	    case 'd':
622		xprintf("%ld", r1->ps_pffdecr -	r0->ps_pffdecr);
623		break;
624
625	    case 'Y':
626		xprintf("%ld", r1->ps_syscall -	r0->ps_syscall);
627		break;
628
629	    case 'l':
630		xprintf("%ld", r1->ps_lread - r0->ps_lread);
631		break;
632
633	    case 'm':
634		xprintf("%ld", r1->ps_lwrite - r0->ps_lwrite);
635		break;
636
637	    case 'p':
638		xprintf("%ld", r1->ps_phread - r0->ps_phread);
639		break;
640
641	    case 'q':
642		xprintf("%ld", r1->ps_phwrite -	r0->ps_phwrite);
643		break;
644# endif	/* _SEQUENT_ */
645#endif /* BSDTIMES */
646	    default:
647		break;
648	    }
649    xputchar('\n');
650}
651
652#if defined(BSDTIMES) || defined(_SEQUENT_)
653static void
654pdeltat(t1, t0)
655    timeval_t *t1, *t0;
656{
657    timeval_t td;
658
659    tvsub(&td, t1, t0);
660    xprintf("%ld.%03ld", td.tv_sec, td.tv_usec / 1000L);
661}
662
663static void
664tvadd(tsum, t0)
665    timeval_t *tsum, *t0;
666{
667
668    tsum->tv_sec += t0->tv_sec;
669    tsum->tv_usec += t0->tv_usec;
670    if (tsum->tv_usec >= 1000000)
671	tsum->tv_sec++,	tsum->tv_usec -= 1000000;
672}
673
674void
675tvsub(tdiff, t1, t0)
676    timeval_t *tdiff, *t1, *t0;
677{
678
679    tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
680    tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
681    if (tdiff->tv_usec < 0)
682	tdiff->tv_sec--, tdiff->tv_usec	+= 1000000;
683}
684
685#else /* !BSDTIMES && !_SEQUENT_ */
686static void
687pdtimet(eval, bval)
688#ifndef	POSIX
689    time_t  eval, bval;
690
691#else /* POSIX */
692    clock_t eval, bval;
693
694#endif /* POSIX	*/
695{
696#ifndef	POSIX
697    time_t  val;
698
699#else /* POSIX */
700    clock_t val;
701
702#endif /* POSIX	*/
703
704#ifndef	POSIX
705    val	= (eval	- bval)	* 100 /	HZ;
706#else /* POSIX */
707    val	= (eval	- bval)	* 100 /	clk_tck;
708#endif /* POSIX	*/
709
710    xprintf("%ld.%02ld", val / 100, val	- (val / 100 * 100));
711}
712#endif /* BSDTIMES || _SEQUENT_	*/
713