xref: /freebsd/contrib/tcsh/sh.time.c (revision 3a31b7eb32ad60e1e05b2b2e184ff47e4afbb874)
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 
39 RCSID("$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 */
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     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
188 void
189 ruadd(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_
222 void
223 ruadd(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 
294 void
295 prusage(r0, r1,	e, b)
296     register struct sysrusage *r0,	*r1;
297     timeval_t *e, *b;
298 
299 #else /* BSDTIMES */
300 # ifdef	_SEQUENT_
301 void
302 prusage(r0, r1,	e, b)
303     register struct process_stats *r0, *r1;
304     timeval_t *e, *b;
305 
306 # else /* _SEQUENT_ */
307 void
308 prusage(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_)
654 static void
655 pdeltat(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 
664 static void
665 tvadd(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 
675 void
676 tvsub(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_ */
687 static void
688 pdtimet(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