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