xref: /freebsd/contrib/tcsh/sh.time.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /* $Header: /src/pub/tcsh/sh.time.c,v 3.22 2000/06/10 21:35:41 kim 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 
39 RCSID("$Id: sh.time.c,v 3.22 2000/06/10 21:35:41 kim 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 */
54 struct tms times0;
55 #endif /* BSDTIMES */
56 
57 #if !defined(BSDTIMES) && !defined(_SEQUENT_)
58 # ifdef	POSIX
59 static	void	pdtimet	__P((clock_t, clock_t));
60 # else /* ! POSIX */
61 static	void	pdtimet	__P((time_t, time_t));
62 # endif	/* ! POSIX */
63 #else /* BSDTIMES || _SEQUENT_ */
64 static	void	tvadd	__P((timeval_t *, timeval_t *));
65 static	void	pdeltat	__P((timeval_t *, timeval_t *));
66 #endif /* BSDTIMES || _SEQUENT_	*/
67 
68 void
69 settimes()
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*/
109 void
110 dotime(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*/
165 void
166 donice(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
187 void
188 ruadd(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_
221 void
222 ruadd(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 
293 void
294 prusage(r0, r1,	e, b)
295     register struct sysrusage *r0,	*r1;
296     timeval_t *e, *b;
297 
298 #else /* BSDTIMES */
299 # ifdef	_SEQUENT_
300 void
301 prusage(r0, r1,	e, b)
302     register struct process_stats *r0, *r1;
303     timeval_t *e, *b;
304 
305 # else /* _SEQUENT_ */
306 void
307 prusage(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 : (long)(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_)
653 static void
654 pdeltat(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 
663 static void
664 tvadd(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 
674 void
675 tvsub(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_ */
686 static void
687 pdtimet(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