sh.time.c revision 83098
1/* $Header: /src/pub/tcsh/sh.time.c,v 3.23 2001/03/18 19:06:31 christos Exp $ */
2/*
3 * sh.time.c: Shell time keeping and printing.
4 */
5/*-
6 * Copyright (c) 1980, 1991 The	Regents	of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and	binary forms, with or without
10 * modification, are permitted provided	that the following conditions
11 * are met:
12 * 1. Redistributions of source	code must retain the above copyright
13 *    notice, this list	of conditions and the following	disclaimer.
14 * 2. Redistributions in binary	form must reproduce the	above copyright
15 *    notice, this list	of conditions and the following	disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials	mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *	This product includes software developed by the	University of
20 *	California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or	promote	products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS	SOFTWARE IS PROVIDED BY	THE REGENTS AND	CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT	SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR	CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES;	LOSS OF	USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH	DAMAGE.
36 */
37#include "sh.h"
38
39RCSID("$Id: sh.time.c,v 3.23 2001/03/18 19:06:31 christos Exp $")
40
41#ifdef SUNOS4
42# include <machine/param.h>
43#endif /* SUNOS4 */
44
45/*
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    if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno)
181	stderror(ERR_SYSTEM, "setpriority", strerror(errno));
182#else /* BSDNICE */
183    (void) nice(nval);
184#endif /* BSDNICE */
185}
186
187#ifdef BSDTIMES
188void
189ruadd(ru, ru2)
190    register struct sysrusage *ru,	*ru2;
191{
192    tvadd(&ru->ru_utime, &ru2->ru_utime);
193    tvadd(&ru->ru_stime, &ru2->ru_stime);
194    if (ru2->ru_maxrss > ru->ru_maxrss)
195	ru->ru_maxrss =	ru2->ru_maxrss;
196
197    ru->ru_ixrss += ru2->ru_ixrss;
198    ru->ru_idrss += ru2->ru_idrss;
199    ru->ru_isrss += ru2->ru_isrss;
200    ru->ru_minflt += ru2->ru_minflt;
201    ru->ru_majflt += ru2->ru_majflt;
202    ru->ru_nswap += ru2->ru_nswap;
203    ru->ru_inblock += ru2->ru_inblock;
204    ru->ru_oublock += ru2->ru_oublock;
205    ru->ru_msgsnd += ru2->ru_msgsnd;
206    ru->ru_msgrcv += ru2->ru_msgrcv;
207    ru->ru_nsignals += ru2->ru_nsignals;
208    ru->ru_nvcsw += ru2->ru_nvcsw;
209    ru->ru_nivcsw += ru2->ru_nivcsw;
210
211# ifdef	convex
212    tvadd(&ru->ru_exutime, &ru2->ru_exutime);
213    ru->ru_utotal += ru2->ru_utotal;
214    ru->ru_usamples += ru2->ru_usamples;
215    ru->ru_stotal += ru2->ru_stotal;
216    ru->ru_ssamples += ru2->ru_ssamples;
217# endif	/* convex */
218}
219
220#else /* BSDTIMES */
221# ifdef	_SEQUENT_
222void
223ruadd(ru, ru2)
224    register struct process_stats *ru, *ru2;
225{
226    tvadd(&ru->ps_utime, &ru2->ps_utime);
227    tvadd(&ru->ps_stime, &ru2->ps_stime);
228    if (ru2->ps_maxrss > ru->ps_maxrss)
229	ru->ps_maxrss =	ru2->ps_maxrss;
230
231    ru->ps_pagein += ru2->ps_pagein;
232    ru->ps_reclaim += ru2->ps_reclaim;
233    ru->ps_zerofill += ru2->ps_zerofill;
234    ru->ps_pffincr += ru2->ps_pffincr;
235    ru->ps_pffdecr += ru2->ps_pffdecr;
236    ru->ps_swap	+= ru2->ps_swap;
237    ru->ps_syscall += ru2->ps_syscall;
238    ru->ps_volcsw += ru2->ps_volcsw;
239    ru->ps_involcsw += ru2->ps_involcsw;
240    ru->ps_signal += ru2->ps_signal;
241    ru->ps_lread += ru2->ps_lread;
242    ru->ps_lwrite += ru2->ps_lwrite;
243    ru->ps_bread += ru2->ps_bread;
244    ru->ps_bwrite += ru2->ps_bwrite;
245    ru->ps_phread += ru2->ps_phread;
246    ru->ps_phwrite += ru2->ps_phwrite;
247}
248
249# endif	/* _SEQUENT_ */
250#endif /* BSDTIMES */
251
252#ifdef BSDTIMES
253
254/*
255 * PWP:	the LOG1024 and	pagetok	stuff taken from the top command,
256 * written by William LeFebvre
257 */
258/* Log base 2 of 1024 is 10 (2^10 == 1024) */
259#define	LOG1024		10
260
261/* Convert clicks (kernel pages) to kbytes ... */
262/* If there is no PGSHIFT defined, assume it is	11 */
263/* Is this needed for compatability with some old flavor of 4.2	or 4.1?	*/
264#ifdef SUNOS4
265# ifndef PGSHIFT
266#  define pagetok(size)	  ((size) << 1)
267# else
268#  if PGSHIFT>10
269#   define pagetok(size)   ((size) << (PGSHIFT - LOG1024))
270#  else
271#   define pagetok(size)   ((size) >> (LOG1024 - PGSHIFT))
272#  endif
273# endif
274#endif
275
276/*
277 * if any other	machines return	wierd values in	the ru_i* stuff, put
278 * the adjusting macro here:
279 */
280#ifdef SUNOS4
281# define IADJUST(i)	(pagetok(i)/2)
282#else /* SUNOS4	*/
283# ifdef	convex
284   /*
285    * convex has megabytes * CLK_TCK
286    * multiply by 100 since we use time	in 100ths of a second in prusage
287    */
288#  define IADJUST(i) (((i) << 10) / CLK_TCK * 100)
289# else /* convex */
290#  define IADJUST(i)	(i)
291# endif	/* convex */
292#endif /* SUNOS4 */
293
294void
295prusage(r0, r1,	e, b)
296    register struct sysrusage *r0,	*r1;
297    timeval_t *e, *b;
298
299#else /* BSDTIMES */
300# ifdef	_SEQUENT_
301void
302prusage(r0, r1,	e, b)
303    register struct process_stats *r0, *r1;
304    timeval_t *e, *b;
305
306# else /* _SEQUENT_ */
307void
308prusage(bs, es,	e, b)
309    struct tms *bs, *es;
310
311#  ifndef POSIX
312    time_t  e, b;
313
314#  else	/* POSIX */
315    clock_t e, b;
316
317#  endif /* POSIX */
318# endif	/* _SEQUENT_ */
319#endif /* BSDTIMES */
320{
321#ifdef BSDTIMES
322    register time_t t =
323    (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec)	* 100 +
324    (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
325    (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec)	* 100 +
326    (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
327
328#else
329# ifdef	_SEQUENT_
330    register time_t t =
331    (r1->ps_utime.tv_sec - r0->ps_utime.tv_sec)	* 100 +
332    (r1->ps_utime.tv_usec - r0->ps_utime.tv_usec) / 10000 +
333    (r1->ps_stime.tv_sec - r0->ps_stime.tv_sec)	* 100 +
334    (r1->ps_stime.tv_usec - r0->ps_stime.tv_usec) / 10000;
335
336# else /* _SEQUENT_ */
337#  ifndef POSIX
338    register time_t t =	(es->tms_utime - bs->tms_utime +
339			 es->tms_stime - bs->tms_stime)	* 100 /	HZ;
340
341#  else	/* POSIX */
342    register clock_t t = (es->tms_utime	- bs->tms_utime	+
343			  es->tms_stime	- bs->tms_stime) * 100 / clk_tck;
344
345#  endif /* POSIX */
346# endif	/* _SEQUENT_ */
347#endif /* BSDTIMES */
348
349    register char *cp;
350    register long i;
351    register struct varent *vp = adrof(STRtime);
352
353#ifdef BSDTIMES
354# ifdef	convex
355    static struct system_information sysinfo;
356    long long memtmp;	/* let memory calculations exceede 2Gb */
357# endif	/* convex */
358    int	    ms = (int)
359    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
360
361    cp = "%Uu %Ss %E %P	%X+%Dk %I+%Oio %Fpf+%Ww";
362#else /* !BSDTIMES */
363# ifdef	_SEQUENT_
364    int	    ms = (int)
365    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
366
367    cp = "%Uu %Ss %E %P	%I+%Oio	%Fpf+%Ww";
368# else /* !_SEQUENT_ */
369#  ifndef POSIX
370    time_t ms = ((time_t)((e - b) / HZ) * 100) +
371		 (time_t)(((e - b) % HZ) * 100) / HZ;
372#  else	/* POSIX */
373    clock_t ms = ((clock_t)((e - b) / clk_tck) * 100) +
374		  (clock_t)(((e - b) % clk_tck) * 100) / clk_tck;
375#  endif /* POSIX */
376
377    cp = "%Uu %Ss %E %P";
378
379    /*
380     * the tms stuff is	not very precise, so we	fudge it.
381     * granularity fix:	can't be more than 100%
382     * this breaks in multi-processor systems...
383     * maybe I should take it out and let people see more then 100%
384     * utilizations.
385     */
386#  if 0
387    if (ms < t && ms !=	0)
388	ms = t;
389#  endif
390# endif	/*! _SEQUENT_ */
391#endif /* !BSDTIMES */
392#ifdef TDEBUG
393    xprintf("es->tms_utime %lu bs->tms_utime %lu\n",
394	    es->tms_utime, bs->tms_utime);
395    xprintf("es->tms_stime %lu bs->tms_stime %lu\n",
396	    es->tms_stime, bs->tms_stime);
397    xprintf("ms	%lu e %lu b %lu\n", ms,	e, b);
398    xprintf("t %lu\n", t);
399#endif /* TDEBUG */
400
401    if (vp && vp->vec[0] && vp->vec[1])
402	cp = short2str(vp->vec[1]);
403    for	(; *cp;	cp++)
404	if (*cp	!= '%')
405	    xputchar(*cp);
406	else if	(cp[1])
407	    switch (*++cp) {
408
409	    case 'U':		/* user	CPU time used */
410#ifdef BSDTIMES
411		pdeltat(&r1->ru_utime, &r0->ru_utime);
412#else
413# ifdef	_SEQUENT_
414		pdeltat(&r1->ps_utime, &r0->ps_utime);
415# else /* _SEQUENT_ */
416#  ifndef POSIX
417		pdtimet(es->tms_utime, bs->tms_utime);
418#  else	/* POSIX */
419		pdtimet(es->tms_utime, bs->tms_utime);
420#  endif /* POSIX */
421# endif	/* _SEQUENT_ */
422#endif /* BSDTIMES */
423		break;
424
425	    case 'S':		/* system CPU time used	*/
426#ifdef BSDTIMES
427		pdeltat(&r1->ru_stime, &r0->ru_stime);
428#else
429# ifdef	_SEQUENT_
430		pdeltat(&r1->ps_stime, &r0->ps_stime);
431# else /* _SEQUENT_ */
432#  ifndef POSIX
433		pdtimet(es->tms_stime, bs->tms_stime);
434#  else	/* POSIX */
435		pdtimet(es->tms_stime, bs->tms_stime);
436#  endif /* POSIX */
437# endif	/* _SEQUENT_ */
438#endif /* BSDTIMES */
439		break;
440
441	    case 'E':		/* elapsed (wall-clock)	time */
442#ifdef BSDTIMES
443		pcsecs((long) ms);
444#else /* BSDTIMES */
445		pcsecs(ms);
446#endif /* BSDTIMES */
447		break;
448
449	    case 'P':		/* percent time	spent running */
450		/* check if the	process	did not	run */
451#ifdef convex
452		/*
453		 * scale the cpu %- ages by the	number of processors
454		 * available on	this machine
455		 */
456		if ((sysinfo.cpu_count == 0) &&
457		    (getsysinfo(SYSINFO_SIZE, &sysinfo)	< 0))
458		    sysinfo.cpu_count =	1;
459		    i =	(ms == 0) ? 0 :	(t * 1000.0 / (ms * sysinfo.cpu_count));
460#else /* convex	*/
461		i = (ms	== 0) ?	0 : (long)(t * 1000.0 / ms);
462#endif /* convex */
463		xprintf("%ld.%01ld%%", i / 10, i % 10);	/* nn.n% */
464		break;
465
466#ifdef BSDTIMES
467	    case 'W':		/* number of swaps */
468		i = r1->ru_nswap - r0->ru_nswap;
469		xprintf("%ld", i);
470		break;
471
472#ifdef convex
473	    case 'X':		/* (average) shared text size */
474		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_ixrss -
475				 (long long)r0->ru_ixrss) /
476			 (long long)t);
477		xprintf("%lu", (unsigned long)memtmp);
478
479		break;
480
481	    case 'D':		/* (average) unshared data size	*/
482		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_idrss +
483				 (long long)r1->ru_isrss -
484				 ((long	long)r0->ru_idrss +
485				  (long	long)r0->ru_isrss)) /
486			 (long long)t);
487		xprintf("%lu", (unsigned long)memtmp);
488		break;
489
490	    case 'K':		/* (average) total data	memory used  */
491		memtmp = (t == 0 ? 0LL : IADJUST(((long	long)r1->ru_ixrss +
492				  (long	long)r1->ru_isrss +
493				  (long	long)r1->ru_idrss) -
494				  ((long long)r0->ru_ixrss +
495				   (long long)r0->ru_idrss +
496				   (long long)r0->ru_isrss)) /
497			 (long long)t);
498		xprintf("%lu", (unsigned long)memtmp);
499		break;
500#else /* !convex */
501	    case 'X':		/* (average) shared text size */
502		xprintf("%ld", t == 0 ?	0L :
503			IADJUST(r1->ru_ixrss - r0->ru_ixrss) / t);
504		break;
505
506	    case 'D':		/* (average) unshared data size	*/
507		xprintf("%ld", t == 0 ?	0L :
508			IADJUST(r1->ru_idrss + r1->ru_isrss -
509				(r0->ru_idrss +	r0->ru_isrss)) / t);
510		break;
511
512	    case 'K':		/* (average) total data	memory used  */
513		xprintf("%ld", t == 0 ?	0L :
514			IADJUST((r1->ru_ixrss +	r1->ru_isrss + r1->ru_idrss) -
515			   (r0->ru_ixrss + r0->ru_idrss	+ r0->ru_isrss)) / t);
516		break;
517#endif /* convex */
518	    case 'M':		/* max.	Resident Set Size */
519#ifdef SUNOS4
520		xprintf("%ld", pagetok(r1->ru_maxrss));
521#else
522# ifdef	convex
523		xprintf("%ld", r1->ru_maxrss * 4L);
524# else /* !convex */
525		xprintf("%ld", r1->ru_maxrss / 2L);
526# endif	/* convex */
527#endif /* SUNOS4 */
528		break;
529
530	    case 'F':		/* page	faults */
531		xprintf("%ld", r1->ru_majflt - r0->ru_majflt);
532		break;
533
534	    case 'R':		/* page	reclaims */
535		xprintf("%ld", r1->ru_minflt - r0->ru_minflt);
536		break;
537
538	    case 'I':		/* FS blocks in	*/
539		xprintf("%ld", r1->ru_inblock -	r0->ru_inblock);
540		break;
541
542	    case 'O':		/* FS blocks out */
543		xprintf("%ld", r1->ru_oublock -	r0->ru_oublock);
544		break;
545
546# ifdef	convex
547	    case 'C':			/*  CPU	parallelization	factor */
548		if (r1->ru_usamples	!= 0LL)	{
549		    long long parr = ((r1->ru_utotal * 100LL) /
550				      r1->ru_usamples);
551		    xprintf("%d.%02d", (int)(parr/100), (int)(parr%100));
552		} else
553		    xprintf("?");
554		break;
555# endif	/* convex */
556	    case 'r':		/* PWP:	socket messages	recieved */
557		xprintf("%ld", r1->ru_msgrcv - r0->ru_msgrcv);
558		break;
559
560	    case 's':		/* PWP:	socket messages	sent */
561		xprintf("%ld", r1->ru_msgsnd - r0->ru_msgsnd);
562		break;
563
564	    case 'k':		/* PWP:	signals	received */
565		xprintf("%ld", r1->ru_nsignals - r0->ru_nsignals);
566		break;
567
568	    case 'w':		/* PWP:	voluntary context switches (waits) */
569		xprintf("%ld", r1->ru_nvcsw - r0->ru_nvcsw);
570		break;
571
572	    case 'c':		/* PWP:	involuntary context switches */
573		xprintf("%ld", r1->ru_nivcsw - r0->ru_nivcsw);
574		break;
575#else /* BSDTIMES */
576# ifdef	_SEQUENT_
577	    case 'W':		/* number of swaps */
578		i = r1->ps_swap	- r0->ps_swap;
579		xprintf("%ld", i);
580		break;
581
582	    case 'M':
583		xprintf("%ld", r1->ps_maxrss / 2);
584		break;
585
586	    case 'F':
587		xprintf("%ld", r1->ps_pagein - r0->ps_pagein);
588		break;
589
590	    case 'R':
591		xprintf("%ld", r1->ps_reclaim -	r0->ps_reclaim);
592		break;
593
594	    case 'I':
595		xprintf("%ld", r1->ps_bread - r0->ps_bread);
596		break;
597
598	    case 'O':
599		xprintf("%ld", r1->ps_bwrite - r0->ps_bwrite);
600		break;
601
602	    case 'k':
603		xprintf("%ld", r1->ps_signal - r0->ps_signal);
604		break;
605
606	    case 'w':
607		xprintf("%ld", r1->ps_volcsw - r0->ps_volcsw);
608		break;
609
610	    case 'c':
611		xprintf("%ld", r1->ps_involcsw - r0->ps_involcsw);
612		break;
613
614	    case 'Z':
615		xprintf("%ld", r1->ps_zerofill - r0->ps_zerofill);
616		break;
617
618	    case 'i':
619		xprintf("%ld", r1->ps_pffincr -	r0->ps_pffincr);
620		break;
621
622	    case 'd':
623		xprintf("%ld", r1->ps_pffdecr -	r0->ps_pffdecr);
624		break;
625
626	    case 'Y':
627		xprintf("%ld", r1->ps_syscall -	r0->ps_syscall);
628		break;
629
630	    case 'l':
631		xprintf("%ld", r1->ps_lread - r0->ps_lread);
632		break;
633
634	    case 'm':
635		xprintf("%ld", r1->ps_lwrite - r0->ps_lwrite);
636		break;
637
638	    case 'p':
639		xprintf("%ld", r1->ps_phread - r0->ps_phread);
640		break;
641
642	    case 'q':
643		xprintf("%ld", r1->ps_phwrite -	r0->ps_phwrite);
644		break;
645# endif	/* _SEQUENT_ */
646#endif /* BSDTIMES */
647	    default:
648		break;
649	    }
650    xputchar('\n');
651}
652
653#if defined(BSDTIMES) || defined(_SEQUENT_)
654static void
655pdeltat(t1, t0)
656    timeval_t *t1, *t0;
657{
658    timeval_t td;
659
660    tvsub(&td, t1, t0);
661    xprintf("%ld.%03ld", td.tv_sec, td.tv_usec / 1000L);
662}
663
664static void
665tvadd(tsum, t0)
666    timeval_t *tsum, *t0;
667{
668
669    tsum->tv_sec += t0->tv_sec;
670    tsum->tv_usec += t0->tv_usec;
671    if (tsum->tv_usec >= 1000000)
672	tsum->tv_sec++,	tsum->tv_usec -= 1000000;
673}
674
675void
676tvsub(tdiff, t1, t0)
677    timeval_t *tdiff, *t1, *t0;
678{
679
680    tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
681    tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
682    if (tdiff->tv_usec < 0)
683	tdiff->tv_sec--, tdiff->tv_usec	+= 1000000;
684}
685
686#else /* !BSDTIMES && !_SEQUENT_ */
687static void
688pdtimet(eval, bval)
689#ifndef	POSIX
690    time_t  eval, bval;
691
692#else /* POSIX */
693    clock_t eval, bval;
694
695#endif /* POSIX	*/
696{
697#ifndef	POSIX
698    time_t  val;
699
700#else /* POSIX */
701    clock_t val;
702
703#endif /* POSIX	*/
704
705#ifndef	POSIX
706    val	= (eval	- bval)	* 100 /	HZ;
707#else /* POSIX */
708    val	= (eval	- bval)	* 100 /	clk_tck;
709#endif /* POSIX	*/
710
711    xprintf("%ld.%02ld", val / 100, val	- (val / 100 * 100));
712}
713#endif /* BSDTIMES || _SEQUENT_	*/
714