xref: /freebsd/contrib/tcsh/sh.time.c (revision 7dfd9569a2f0637fb9a48157b1c1bfe5709faee3)
1 /* $Header: /src/pub/tcsh/sh.time.c,v 3.28 2005/03/03 16:49:16 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. 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.28 2005/03/03 16:49:16 kim 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     Char **v;
164     struct command *c;
165 {
166     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 HAVE_SETPRIORITY
176     if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno)
177 	stderror(ERR_SYSTEM, "setpriority", strerror(errno));
178 #else /* !HAVE_SETPRIORITY */
179     (void) nice(nval);
180 #endif /* HAVE_SETPRIORITY */
181 }
182 
183 #ifdef BSDTIMES
184 void
185 ruadd(ru, ru2)
186     struct sysrusage *ru,	*ru2;
187 {
188     tvadd(&ru->ru_utime, &ru2->ru_utime);
189     tvadd(&ru->ru_stime, &ru2->ru_stime);
190 #ifndef _OSD_POSIX
191     if (ru2->ru_maxrss > ru->ru_maxrss)
192 	ru->ru_maxrss =	ru2->ru_maxrss;
193 
194     ru->ru_ixrss += ru2->ru_ixrss;
195     ru->ru_idrss += ru2->ru_idrss;
196     ru->ru_isrss += ru2->ru_isrss;
197     ru->ru_minflt += ru2->ru_minflt;
198     ru->ru_majflt += ru2->ru_majflt;
199     ru->ru_nswap += ru2->ru_nswap;
200     ru->ru_inblock += ru2->ru_inblock;
201     ru->ru_oublock += ru2->ru_oublock;
202     ru->ru_msgsnd += ru2->ru_msgsnd;
203     ru->ru_msgrcv += ru2->ru_msgrcv;
204     ru->ru_nsignals += ru2->ru_nsignals;
205     ru->ru_nvcsw += ru2->ru_nvcsw;
206     ru->ru_nivcsw += ru2->ru_nivcsw;
207 #endif /*bs2000*/
208 
209 # ifdef	convex
210     tvadd(&ru->ru_exutime, &ru2->ru_exutime);
211     ru->ru_utotal += ru2->ru_utotal;
212     ru->ru_usamples += ru2->ru_usamples;
213     ru->ru_stotal += ru2->ru_stotal;
214     ru->ru_ssamples += ru2->ru_ssamples;
215 # endif	/* convex */
216 }
217 
218 #else /* BSDTIMES */
219 # ifdef	_SEQUENT_
220 void
221 ruadd(ru, ru2)
222     struct process_stats *ru, *ru2;
223 {
224     tvadd(&ru->ps_utime, &ru2->ps_utime);
225     tvadd(&ru->ps_stime, &ru2->ps_stime);
226     if (ru2->ps_maxrss > ru->ps_maxrss)
227 	ru->ps_maxrss =	ru2->ps_maxrss;
228 
229     ru->ps_pagein += ru2->ps_pagein;
230     ru->ps_reclaim += ru2->ps_reclaim;
231     ru->ps_zerofill += ru2->ps_zerofill;
232     ru->ps_pffincr += ru2->ps_pffincr;
233     ru->ps_pffdecr += ru2->ps_pffdecr;
234     ru->ps_swap	+= ru2->ps_swap;
235     ru->ps_syscall += ru2->ps_syscall;
236     ru->ps_volcsw += ru2->ps_volcsw;
237     ru->ps_involcsw += ru2->ps_involcsw;
238     ru->ps_signal += ru2->ps_signal;
239     ru->ps_lread += ru2->ps_lread;
240     ru->ps_lwrite += ru2->ps_lwrite;
241     ru->ps_bread += ru2->ps_bread;
242     ru->ps_bwrite += ru2->ps_bwrite;
243     ru->ps_phread += ru2->ps_phread;
244     ru->ps_phwrite += ru2->ps_phwrite;
245 }
246 
247 # endif	/* _SEQUENT_ */
248 #endif /* BSDTIMES */
249 
250 #ifdef BSDTIMES
251 
252 /*
253  * PWP:	the LOG1024 and	pagetok	stuff taken from the top command,
254  * written by William LeFebvre
255  */
256 /* Log base 2 of 1024 is 10 (2^10 == 1024) */
257 #define	LOG1024		10
258 
259 /* Convert clicks (kernel pages) to kbytes ... */
260 /* If there is no PGSHIFT defined, assume it is	11 */
261 /* Is this needed for compatability with some old flavor of 4.2	or 4.1?	*/
262 #ifdef SUNOS4
263 # ifndef PGSHIFT
264 #  define pagetok(size)	  ((size) << 1)
265 # else
266 #  if PGSHIFT>10
267 #   define pagetok(size)   ((size) << (PGSHIFT - LOG1024))
268 #  else
269 #   define pagetok(size)   ((size) >> (LOG1024 - PGSHIFT))
270 #  endif
271 # endif
272 #endif
273 
274 /*
275  * if any other	machines return	wierd values in	the ru_i* stuff, put
276  * the adjusting macro here:
277  */
278 #ifdef SUNOS4
279 # define IADJUST(i)	(pagetok(i)/2)
280 #else /* SUNOS4	*/
281 # ifdef	convex
282    /*
283     * convex has megabytes * CLK_TCK
284     * multiply by 100 since we use time	in 100ths of a second in prusage
285     */
286 #  define IADJUST(i) (((i) << 10) / CLK_TCK * 100)
287 # else /* convex */
288 #  define IADJUST(i)	(i)
289 # endif	/* convex */
290 #endif /* SUNOS4 */
291 
292 void
293 prusage(r0, r1,	e, b)
294     struct sysrusage *r0,	*r1;
295     timeval_t *e, *b;
296 
297 #else /* BSDTIMES */
298 # ifdef	_SEQUENT_
299 void
300 prusage(r0, r1,	e, b)
301     struct process_stats *r0, *r1;
302     timeval_t *e, *b;
303 
304 # else /* _SEQUENT_ */
305 void
306 prusage(bs, es,	e, b)
307     struct tms *bs, *es;
308 
309 #  ifndef POSIX
310     time_t  e, b;
311 
312 #  else	/* POSIX */
313     clock_t e, b;
314 
315 #  endif /* POSIX */
316 # endif	/* _SEQUENT_ */
317 #endif /* BSDTIMES */
318 {
319 #ifdef BSDTIMES
320     time_t t =
321     (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec)	* 100 +
322     (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
323     (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec)	* 100 +
324     (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
325 
326 #else
327 # ifdef	_SEQUENT_
328     time_t t =
329     (r1->ps_utime.tv_sec - r0->ps_utime.tv_sec)	* 100 +
330     (r1->ps_utime.tv_usec - r0->ps_utime.tv_usec) / 10000 +
331     (r1->ps_stime.tv_sec - r0->ps_stime.tv_sec)	* 100 +
332     (r1->ps_stime.tv_usec - r0->ps_stime.tv_usec) / 10000;
333 
334 # else /* _SEQUENT_ */
335 #  ifndef POSIX
336     time_t t =	(es->tms_utime - bs->tms_utime +
337 			 es->tms_stime - bs->tms_stime)	* 100 /	HZ;
338 
339 #  else	/* POSIX */
340     clock_t t = (es->tms_utime	- bs->tms_utime	+
341 			  es->tms_stime	- bs->tms_stime) * 100 / clk_tck;
342 
343 #  endif /* POSIX */
344 # endif	/* _SEQUENT_ */
345 #endif /* BSDTIMES */
346 
347     const char *cp;
348     long i;
349     struct varent *vp = adrof(STRtime);
350 
351 #ifdef BSDTIMES
352 # ifdef	convex
353     static struct system_information sysinfo;
354     long long memtmp;	/* let memory calculations exceede 2Gb */
355 # endif	/* convex */
356     int	    ms = (int)
357     ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
358 
359     cp = "%Uu %Ss %E %P	%X+%Dk %I+%Oio %Fpf+%Ww";
360 #else /* !BSDTIMES */
361 # ifdef	_SEQUENT_
362     int	    ms = (int)
363     ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
364 
365     cp = "%Uu %Ss %E %P	%I+%Oio	%Fpf+%Ww";
366 # else /* !_SEQUENT_ */
367 #  ifndef POSIX
368     time_t ms = ((time_t)((e - b) / HZ) * 100) +
369 		 (time_t)(((e - b) % HZ) * 100) / HZ;
370 #  else	/* POSIX */
371     clock_t ms = ((clock_t)((e - b) / clk_tck) * 100) +
372 		  (clock_t)(((e - b) % clk_tck) * 100) / clk_tck;
373 #  endif /* POSIX */
374 
375     cp = "%Uu %Ss %E %P";
376 
377     /*
378      * the tms stuff is	not very precise, so we	fudge it.
379      * granularity fix:	can't be more than 100%
380      * this breaks in multi-processor systems...
381      * maybe I should take it out and let people see more then 100%
382      * utilizations.
383      */
384 #  if 0
385     if (ms < t && ms !=	0)
386 	ms = t;
387 #  endif
388 # endif	/*! _SEQUENT_ */
389 #endif /* !BSDTIMES */
390 #ifdef TDEBUG
391     xprintf("es->tms_utime %lu bs->tms_utime %lu\n",
392 	    es->tms_utime, bs->tms_utime);
393     xprintf("es->tms_stime %lu bs->tms_stime %lu\n",
394 	    es->tms_stime, bs->tms_stime);
395     xprintf("ms	%lu e %lu b %lu\n", ms,	e, b);
396     xprintf("t %lu\n", t);
397 #endif /* TDEBUG */
398 
399     if (vp && vp->vec && vp->vec[0] && vp->vec[1])
400 	cp = short2str(vp->vec[1]);
401     for	(; *cp;	cp++)
402 	if (*cp	!= '%')
403 	    xputchar(*cp);
404 	else if	(cp[1])
405 	    switch (*++cp) {
406 
407 	    case 'U':		/* user	CPU time used */
408 #ifdef BSDTIMES
409 		pdeltat(&r1->ru_utime, &r0->ru_utime);
410 #else
411 # ifdef	_SEQUENT_
412 		pdeltat(&r1->ps_utime, &r0->ps_utime);
413 # else /* _SEQUENT_ */
414 #  ifndef POSIX
415 		pdtimet(es->tms_utime, bs->tms_utime);
416 #  else	/* POSIX */
417 		pdtimet(es->tms_utime, bs->tms_utime);
418 #  endif /* POSIX */
419 # endif	/* _SEQUENT_ */
420 #endif /* BSDTIMES */
421 		break;
422 
423 	    case 'S':		/* system CPU time used	*/
424 #ifdef BSDTIMES
425 		pdeltat(&r1->ru_stime, &r0->ru_stime);
426 #else
427 # ifdef	_SEQUENT_
428 		pdeltat(&r1->ps_stime, &r0->ps_stime);
429 # else /* _SEQUENT_ */
430 #  ifndef POSIX
431 		pdtimet(es->tms_stime, bs->tms_stime);
432 #  else	/* POSIX */
433 		pdtimet(es->tms_stime, bs->tms_stime);
434 #  endif /* POSIX */
435 # endif	/* _SEQUENT_ */
436 #endif /* BSDTIMES */
437 		break;
438 
439 	    case 'E':		/* elapsed (wall-clock)	time */
440 #ifdef BSDTIMES
441 		pcsecs((long) ms);
442 #else /* BSDTIMES */
443 		pcsecs(ms);
444 #endif /* BSDTIMES */
445 		break;
446 
447 	    case 'P':		/* percent time	spent running */
448 		/* check if the	process	did not	run */
449 #ifdef convex
450 		/*
451 		 * scale the cpu %- ages by the	number of processors
452 		 * available on	this machine
453 		 */
454 		if ((sysinfo.cpu_count == 0) &&
455 		    (getsysinfo(SYSINFO_SIZE, &sysinfo)	< 0))
456 		    sysinfo.cpu_count =	1;
457 		    i =	(ms == 0) ? 0 :	(t * 1000.0 / (ms * sysinfo.cpu_count));
458 #else /* convex	*/
459 		i = (ms	== 0) ?	0 : (long)(t * 1000.0 / ms);
460 #endif /* convex */
461 		xprintf("%ld.%01ld%%", i / 10, i % 10);	/* nn.n% */
462 		break;
463 
464 #ifdef BSDTIMES
465 	    case 'W':		/* number of swaps */
466 #ifdef _OSD_POSIX
467 		i = 0;
468 #else
469 		i = r1->ru_nswap - r0->ru_nswap;
470 #endif
471 		xprintf("%ld", i);
472 		break;
473 
474 #ifdef convex
475 	    case 'X':		/* (average) shared text size */
476 		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_ixrss -
477 				 (long long)r0->ru_ixrss) /
478 			 (long long)t);
479 		xprintf("%lu", (unsigned long)memtmp);
480 
481 		break;
482 
483 	    case 'D':		/* (average) unshared data size	*/
484 		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_idrss +
485 				 (long long)r1->ru_isrss -
486 				 ((long	long)r0->ru_idrss +
487 				  (long	long)r0->ru_isrss)) /
488 			 (long long)t);
489 		xprintf("%lu", (unsigned long)memtmp);
490 		break;
491 
492 	    case 'K':		/* (average) total data	memory used  */
493 		memtmp = (t == 0 ? 0LL : IADJUST(((long	long)r1->ru_ixrss +
494 				  (long	long)r1->ru_isrss +
495 				  (long	long)r1->ru_idrss) -
496 				  ((long long)r0->ru_ixrss +
497 				   (long long)r0->ru_idrss +
498 				   (long long)r0->ru_isrss)) /
499 			 (long long)t);
500 		xprintf("%lu", (unsigned long)memtmp);
501 		break;
502 #else /* !convex */
503 	    case 'X':		/* (average) shared text size */
504 #ifdef _OSD_POSIX
505 		xprintf("0",0);
506 #else
507 		xprintf("%ld", t == 0 ?	0L :
508 			IADJUST(r1->ru_ixrss - r0->ru_ixrss) / t);
509 #endif
510 		break;
511 
512 	    case 'D':		/* (average) unshared data size	*/
513 #ifdef _OSD_POSIX
514 		xprintf("0",0);
515 #else
516 		xprintf("%ld", t == 0 ?	0L :
517 			IADJUST(r1->ru_idrss + r1->ru_isrss -
518 				(r0->ru_idrss +	r0->ru_isrss)) / t);
519 #endif
520 		break;
521 
522 	    case 'K':		/* (average) total data	memory used  */
523 #ifdef _OSD_POSIX
524 		xprintf("0",0);
525 #else
526 		xprintf("%ld", t == 0 ?	0L :
527 			IADJUST((r1->ru_ixrss +	r1->ru_isrss + r1->ru_idrss) -
528 			   (r0->ru_ixrss + r0->ru_idrss	+ r0->ru_isrss)) / t);
529 #endif
530 		break;
531 #endif /* convex */
532 	    case 'M':		/* max.	Resident Set Size */
533 #ifdef SUNOS4
534 		xprintf("%ld", pagetok(r1->ru_maxrss));
535 #else
536 # ifdef	convex
537 		xprintf("%ld", r1->ru_maxrss * 4L);
538 # else /* !convex */
539 #  ifdef _OSD_POSIX
540 		xprintf("0",0);
541 #  else
542 		xprintf("%ld", r1->ru_maxrss / 2L);
543 #  endif
544 # endif	/* convex */
545 #endif /* SUNOS4 */
546 		break;
547 
548 	    case 'F':		/* page	faults */
549 #ifdef _OSD_POSIX
550 		xprintf("0",0);
551 #else
552 		xprintf("%ld", r1->ru_majflt - r0->ru_majflt);
553 #endif
554 		break;
555 
556 	    case 'R':		/* page	reclaims */
557 #ifdef _OSD_POSIX
558 		xprintf("0",0);
559 #else
560 		xprintf("%ld", r1->ru_minflt - r0->ru_minflt);
561 #endif
562 		break;
563 
564 	    case 'I':		/* FS blocks in	*/
565 #ifdef _OSD_POSIX
566 		xprintf("0",0);
567 #else
568 		xprintf("%ld", r1->ru_inblock -	r0->ru_inblock);
569 #endif
570 		break;
571 
572 	    case 'O':		/* FS blocks out */
573 #ifdef _OSD_POSIX
574 		xprintf("0",0);
575 #else
576 		xprintf("%ld", r1->ru_oublock -	r0->ru_oublock);
577 #endif
578 		break;
579 
580 # ifdef	convex
581 	    case 'C':			/*  CPU	parallelization	factor */
582 		if (r1->ru_usamples	!= 0LL)	{
583 		    long long parr = ((r1->ru_utotal * 100LL) /
584 				      r1->ru_usamples);
585 		    xprintf("%d.%02d", (int)(parr/100), (int)(parr%100));
586 		} else
587 		    xprintf("?");
588 		break;
589 # endif	/* convex */
590 	    case 'r':		/* PWP:	socket messages	recieved */
591 #ifdef _OSD_POSIX
592 		xprintf("0",0);
593 #else
594 		xprintf("%ld", r1->ru_msgrcv - r0->ru_msgrcv);
595 #endif
596 		break;
597 
598 	    case 's':		/* PWP:	socket messages	sent */
599 #ifdef _OSD_POSIX
600 		xprintf("0",0);
601 #else
602 		xprintf("%ld", r1->ru_msgsnd - r0->ru_msgsnd);
603 #endif
604 		break;
605 
606 	    case 'k':		/* PWP:	signals	received */
607 #ifdef _OSD_POSIX
608 		xprintf("0",0);
609 #else
610 		xprintf("%ld", r1->ru_nsignals - r0->ru_nsignals);
611 #endif
612 		break;
613 
614 	    case 'w':		/* PWP:	voluntary context switches (waits) */
615 #ifdef _OSD_POSIX
616 		xprintf("0",0);
617 #else
618 		xprintf("%ld", r1->ru_nvcsw - r0->ru_nvcsw);
619 #endif
620 		break;
621 
622 	    case 'c':		/* PWP:	involuntary context switches */
623 #ifdef _OSD_POSIX
624 		xprintf("0",0);
625 #else
626 		xprintf("%ld", r1->ru_nivcsw - r0->ru_nivcsw);
627 #endif
628 		break;
629 #else /* BSDTIMES */
630 # ifdef	_SEQUENT_
631 	    case 'W':		/* number of swaps */
632 		i = r1->ps_swap	- r0->ps_swap;
633 		xprintf("%ld", i);
634 		break;
635 
636 	    case 'M':
637 		xprintf("%ld", r1->ps_maxrss / 2);
638 		break;
639 
640 	    case 'F':
641 		xprintf("%ld", r1->ps_pagein - r0->ps_pagein);
642 		break;
643 
644 	    case 'R':
645 		xprintf("%ld", r1->ps_reclaim -	r0->ps_reclaim);
646 		break;
647 
648 	    case 'I':
649 		xprintf("%ld", r1->ps_bread - r0->ps_bread);
650 		break;
651 
652 	    case 'O':
653 		xprintf("%ld", r1->ps_bwrite - r0->ps_bwrite);
654 		break;
655 
656 	    case 'k':
657 		xprintf("%ld", r1->ps_signal - r0->ps_signal);
658 		break;
659 
660 	    case 'w':
661 		xprintf("%ld", r1->ps_volcsw - r0->ps_volcsw);
662 		break;
663 
664 	    case 'c':
665 		xprintf("%ld", r1->ps_involcsw - r0->ps_involcsw);
666 		break;
667 
668 	    case 'Z':
669 		xprintf("%ld", r1->ps_zerofill - r0->ps_zerofill);
670 		break;
671 
672 	    case 'i':
673 		xprintf("%ld", r1->ps_pffincr -	r0->ps_pffincr);
674 		break;
675 
676 	    case 'd':
677 		xprintf("%ld", r1->ps_pffdecr -	r0->ps_pffdecr);
678 		break;
679 
680 	    case 'Y':
681 		xprintf("%ld", r1->ps_syscall -	r0->ps_syscall);
682 		break;
683 
684 	    case 'l':
685 		xprintf("%ld", r1->ps_lread - r0->ps_lread);
686 		break;
687 
688 	    case 'm':
689 		xprintf("%ld", r1->ps_lwrite - r0->ps_lwrite);
690 		break;
691 
692 	    case 'p':
693 		xprintf("%ld", r1->ps_phread - r0->ps_phread);
694 		break;
695 
696 	    case 'q':
697 		xprintf("%ld", r1->ps_phwrite -	r0->ps_phwrite);
698 		break;
699 # endif	/* _SEQUENT_ */
700 #endif /* BSDTIMES */
701 	    default:
702 		break;
703 	    }
704     xputchar('\n');
705 }
706 
707 #if defined(BSDTIMES) || defined(_SEQUENT_)
708 static void
709 pdeltat(t1, t0)
710     timeval_t *t1, *t0;
711 {
712     timeval_t td;
713 
714     tvsub(&td, t1, t0);
715     xprintf("%ld.%03ld", td.tv_sec, td.tv_usec / 1000L);
716 }
717 
718 static void
719 tvadd(tsum, t0)
720     timeval_t *tsum, *t0;
721 {
722 
723     tsum->tv_sec += t0->tv_sec;
724     tsum->tv_usec += t0->tv_usec;
725     if (tsum->tv_usec >= 1000000)
726 	tsum->tv_sec++,	tsum->tv_usec -= 1000000;
727 }
728 
729 void
730 tvsub(tdiff, t1, t0)
731     timeval_t *tdiff, *t1, *t0;
732 {
733 
734     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
735     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
736     if (tdiff->tv_usec < 0)
737 	tdiff->tv_sec--, tdiff->tv_usec	+= 1000000;
738 }
739 
740 #else /* !BSDTIMES && !_SEQUENT_ */
741 static void
742 pdtimet(eval, bval)
743 #ifndef	POSIX
744     time_t  eval, bval;
745 
746 #else /* POSIX */
747     clock_t eval, bval;
748 
749 #endif /* POSIX	*/
750 {
751 #ifndef	POSIX
752     time_t  val;
753 
754 #else /* POSIX */
755     clock_t val;
756 
757 #endif /* POSIX	*/
758 
759 #ifndef	POSIX
760     val	= (eval	- bval)	* 100 /	HZ;
761 #else /* POSIX */
762     val	= (eval	- bval)	* 100 /	clk_tck;
763 #endif /* POSIX	*/
764 
765     xprintf("%ld.%02ld", val / 100, val	- (val / 100 * 100));
766 }
767 #endif /* BSDTIMES || _SEQUENT_	*/
768