sh.time.c revision 59243
1210389Sgabor/* $Header: /src/pub/tcsh/sh.time.c,v 3.20 1998/11/24 18:17:38 christos Exp $ */
2210389Sgabor/*
3210389Sgabor * sh.time.c: Shell time keeping and printing.
4210389Sgabor */
5210389Sgabor/*-
6210389Sgabor * Copyright (c) 1980, 1991 The	Regents	of the University of California.
7210389Sgabor * All rights reserved.
8210389Sgabor *
9210389Sgabor * Redistribution and use in source and	binary forms, with or without
10210389Sgabor * modification, are permitted provided	that the following conditions
11210389Sgabor * are met:
12210389Sgabor * 1. Redistributions of source	code must retain the above copyright
13210389Sgabor *    notice, this list	of conditions and the following	disclaimer.
14210389Sgabor * 2. Redistributions in binary	form must reproduce the	above copyright
15210389Sgabor *    notice, this list	of conditions and the following	disclaimer in the
16210389Sgabor *    documentation and/or other materials provided with the distribution.
17210389Sgabor * 3. All advertising materials	mentioning features or use of this software
18210389Sgabor *    must display the following acknowledgement:
19210389Sgabor *	This product includes software developed by the	University of
20210389Sgabor *	California, Berkeley and its contributors.
21210389Sgabor * 4. Neither the name of the University nor the names of its contributors
22210389Sgabor *    may be used to endorse or	promote	products derived from this software
23210389Sgabor *    without specific prior written permission.
24210389Sgabor *
25210389Sgabor * THIS	SOFTWARE IS PROVIDED BY	THE REGENTS AND	CONTRIBUTORS ``AS IS'' AND
26210389Sgabor * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27210389Sgabor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28210389Sgabor * ARE DISCLAIMED.  IN NO EVENT	SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29210389Sgabor * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR	CONSEQUENTIAL
30210389Sgabor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31210389Sgabor * OR SERVICES;	LOSS OF	USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32210389Sgabor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33210389Sgabor * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34210389Sgabor * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35210389Sgabor * SUCH	DAMAGE.
36210389Sgabor */
37210389Sgabor#include "sh.h"
38210389Sgabor
39210389SgaborRCSID("$Id: sh.time.c,v 3.20 1998/11/24 18:17:38 christos Exp $")
40210389Sgabor
41210389Sgabor#ifdef SUNOS4
42210389Sgabor# include <machine/param.h>
43210389Sgabor#endif /* SUNOS4 */
44210389Sgabor
45210389Sgabor/*
46210389Sgabor * C Shell - routines handling process timing and niceing
47210389Sgabor */
48210389Sgabor#ifdef BSDTIMES
49210389Sgabor# ifndef RUSAGE_SELF
50210389Sgabor#  define	RUSAGE_SELF	0
51210389Sgabor#  define	RUSAGE_CHILDREN	-1
52210389Sgabor# endif	/* RUSAGE_SELF */
53210389Sgabor#else /* BSDTIMES */
54210389Sgaborstruct tms times0;
55210389Sgabor#endif /* BSDTIMES */
56210389Sgabor
57210389Sgabor#if !defined(BSDTIMES) && !defined(_SEQUENT_)
58210389Sgabor# ifdef	POSIX
59210389Sgaborstatic	void	pdtimet	__P((clock_t, clock_t));
60210389Sgabor# else /* ! POSIX */
61210389Sgaborstatic	void	pdtimet	__P((time_t, time_t));
62210389Sgabor# endif	/* ! POSIX */
63210389Sgabor#else /* BSDTIMES || _SEQUENT_ */
64210389Sgaborstatic	void	tvadd	__P((timeval_t *, timeval_t *));
65210389Sgaborstatic	void	pdeltat	__P((timeval_t *, timeval_t *));
66210389Sgabor#endif /* BSDTIMES || _SEQUENT_	*/
67210389Sgabor
68210389Sgaborvoid
69210389Sgaborsettimes()
70210389Sgabor{
71210389Sgabor#ifdef BSDTIMES
72210389Sgabor    struct sysrusage ruch;
73210389Sgabor#ifdef convex
74210389Sgabor    memset(&ru0, 0, sizeof(ru0));
75210389Sgabor    memset(&ruch, 0, sizeof(ruch));
76210389Sgabor#endif /* convex */
77210389Sgabor
78210389Sgabor    (void) gettimeofday(&time0,	NULL);
79210389Sgabor    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru0);
80210389Sgabor    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
81210389Sgabor    ruadd(&ru0,	&ruch);
82210389Sgabor#else
83210389Sgabor# ifdef	_SEQUENT_
84210389Sgabor    struct process_stats ruch;
85210389Sgabor
86210389Sgabor    (void) get_process_stats(&time0, PS_SELF, &ru0, &ruch);
87210389Sgabor    ruadd(&ru0,	&ruch);
88210389Sgabor# else	/* _SEQUENT_ */
89210389Sgabor#  ifndef COHERENT
90210389Sgabor    time0 = times(&times0);
91210389Sgabor#  else	/* !COHERENT */
92210389Sgabor    time0 = HZ * time(NULL);
93210389Sgabor    times(&times0);
94210389Sgabor#  endif /* !COHERENT */
95210389Sgabor    times0.tms_stime +=	times0.tms_cstime;
96210389Sgabor    times0.tms_utime +=	times0.tms_cutime;
97210389Sgabor    times0.tms_cstime =	0;
98210389Sgabor    times0.tms_cutime =	0;
99210389Sgabor# endif	/* _SEQUENT_ */
100210389Sgabor#endif /* BSDTIMES */
101210389Sgabor}
102210389Sgabor
103210389Sgabor/*
104210389Sgabor * dotime is only called if it is truly	a builtin function and not a
105210389Sgabor * prefix to another command
106210389Sgabor */
107210389Sgabor/*ARGSUSED*/
108210389Sgaborvoid
109210389Sgabordotime(v, c)
110210389Sgabor    Char **v;
111210389Sgabor    struct command *c;
112210389Sgabor{
113210389Sgabor#ifdef BSDTIMES
114210389Sgabor    timeval_t timedol;
115210389Sgabor    struct sysrusage ru1, ruch;
116210389Sgabor#ifdef convex
117210389Sgabor    memset(&ru1, 0, sizeof(ru1));
118210389Sgabor    memset(&ruch, 0, sizeof(ruch));
119210389Sgabor#endif /* convex */
120210389Sgabor
121210389Sgabor    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru1);
122210389Sgabor    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
123210389Sgabor    ruadd(&ru1,	&ruch);
124210389Sgabor    (void) gettimeofday(&timedol, NULL);
125210389Sgabor    prusage(&ru0, &ru1,	&timedol, &time0);
126210389Sgabor#else
127210389Sgabor# ifdef	_SEQUENT_
128210389Sgabor    timeval_t timedol;
129210389Sgabor    struct process_stats ru1, ruch;
130210389Sgabor
131210389Sgabor    (void) get_process_stats(&timedol, PS_SELF,	&ru1, &ruch);
132210389Sgabor    ruadd(&ru1,	&ruch);
133210389Sgabor    prusage(&ru0, &ru1,	&timedol, &time0);
134210389Sgabor# else /* _SEQUENT_ */
135210389Sgabor#  ifndef POSIX
136210389Sgabor    time_t  timedol;
137210389Sgabor#  else	/* POSIX */
138210389Sgabor    clock_t timedol;
139210389Sgabor#  endif /* POSIX */
140210389Sgabor
141210389Sgabor    struct tms times_dol;
142210389Sgabor
143210389Sgabor#ifndef	COHERENT
144210389Sgabor    timedol = times(&times_dol);
145210389Sgabor#else
146210389Sgabor    timedol = HZ * time(NULL);
147210389Sgabor    times(&times_dol);
148210389Sgabor#endif
149210389Sgabor    times_dol.tms_stime	+= times_dol.tms_cstime;
150210389Sgabor    times_dol.tms_utime	+= times_dol.tms_cutime;
151210389Sgabor    times_dol.tms_cstime = 0;
152210389Sgabor    times_dol.tms_cutime = 0;
153210389Sgabor    prusage(&times0, &times_dol, timedol, time0);
154210389Sgabor# endif	/* _SEQUENT_ */
155210389Sgabor#endif /* BSDTIMES */
156210389Sgabor    USE(c);
157210389Sgabor    USE(v);
158210389Sgabor}
159210389Sgabor
160210389Sgabor/*
161210389Sgabor * donice is only called when it on the	line by	itself or with a +- value
162210389Sgabor */
163/*ARGSUSED*/
164void
165donice(v, c)
166    register Char **v;
167    struct command *c;
168{
169    register Char *cp;
170    int	    nval = 0;
171
172    USE(c);
173    v++, cp = *v++;
174    if (cp == 0)
175	nval = 4;
176    else if (*v	== 0 &&	any("+-", cp[0]))
177	nval = getn(cp);
178#ifdef BSDNICE
179    (void) setpriority(PRIO_PROCESS, 0,	nval);
180#else /* BSDNICE */
181    (void) nice(nval);
182#endif /* BSDNICE */
183}
184
185#ifdef BSDTIMES
186void
187ruadd(ru, ru2)
188    register struct sysrusage *ru,	*ru2;
189{
190    tvadd(&ru->ru_utime, &ru2->ru_utime);
191    tvadd(&ru->ru_stime, &ru2->ru_stime);
192    if (ru2->ru_maxrss > ru->ru_maxrss)
193	ru->ru_maxrss =	ru2->ru_maxrss;
194
195    ru->ru_ixrss += ru2->ru_ixrss;
196    ru->ru_idrss += ru2->ru_idrss;
197    ru->ru_isrss += ru2->ru_isrss;
198    ru->ru_minflt += ru2->ru_minflt;
199    ru->ru_majflt += ru2->ru_majflt;
200    ru->ru_nswap += ru2->ru_nswap;
201    ru->ru_inblock += ru2->ru_inblock;
202    ru->ru_oublock += ru2->ru_oublock;
203    ru->ru_msgsnd += ru2->ru_msgsnd;
204    ru->ru_msgrcv += ru2->ru_msgrcv;
205    ru->ru_nsignals += ru2->ru_nsignals;
206    ru->ru_nvcsw += ru2->ru_nvcsw;
207    ru->ru_nivcsw += ru2->ru_nivcsw;
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_
220void
221ruadd(ru, ru2)
222    register 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
292void
293prusage(r0, r1,	e, b)
294    register struct sysrusage *r0,	*r1;
295    timeval_t *e, *b;
296
297#else /* BSDTIMES */
298# ifdef	_SEQUENT_
299void
300prusage(r0, r1,	e, b)
301    register struct process_stats *r0, *r1;
302    timeval_t *e, *b;
303
304# else /* _SEQUENT_ */
305void
306prusage(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    register 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    register 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    register time_t t =	(es->tms_utime - bs->tms_utime +
337			 es->tms_stime - bs->tms_stime)	* 100 /	HZ;
338
339#  else	/* POSIX */
340    register 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    register char *cp;
348    register long i;
349    register 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[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 / (ms	* sysinfo.cpu_count));
458#else /* convex	*/
459		i = (ms	== 0) ?	0 : (t * 1000 /	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		i = r1->ru_nswap - r0->ru_nswap;
467		xprintf("%ld", i);
468		break;
469
470#ifdef convex
471	    case 'X':		/* (average) shared text size */
472		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_ixrss -
473				 (long long)r0->ru_ixrss) /
474			 (long long)t);
475		xprintf("%lu", (unsigned long)memtmp);
476
477		break;
478
479	    case 'D':		/* (average) unshared data size	*/
480		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_idrss +
481				 (long long)r1->ru_isrss -
482				 ((long	long)r0->ru_idrss +
483				  (long	long)r0->ru_isrss)) /
484			 (long long)t);
485		xprintf("%lu", (unsigned long)memtmp);
486		break;
487
488	    case 'K':		/* (average) total data	memory used  */
489		memtmp = (t == 0 ? 0LL : IADJUST(((long	long)r1->ru_ixrss +
490				  (long	long)r1->ru_isrss +
491				  (long	long)r1->ru_idrss) -
492				  ((long long)r0->ru_ixrss +
493				   (long long)r0->ru_idrss +
494				   (long long)r0->ru_isrss)) /
495			 (long long)t);
496		xprintf("%lu", (unsigned long)memtmp);
497		break;
498#else /* !convex */
499	    case 'X':		/* (average) shared text size */
500		xprintf("%ld", t == 0 ?	0L :
501			IADJUST(r1->ru_ixrss - r0->ru_ixrss) / t);
502		break;
503
504	    case 'D':		/* (average) unshared data size	*/
505		xprintf("%ld", t == 0 ?	0L :
506			IADJUST(r1->ru_idrss + r1->ru_isrss -
507				(r0->ru_idrss +	r0->ru_isrss)) / t);
508		break;
509
510	    case 'K':		/* (average) total data	memory used  */
511		xprintf("%ld", t == 0 ?	0L :
512			IADJUST((r1->ru_ixrss +	r1->ru_isrss + r1->ru_idrss) -
513			   (r0->ru_ixrss + r0->ru_idrss	+ r0->ru_isrss)) / t);
514		break;
515#endif /* convex */
516	    case 'M':		/* max.	Resident Set Size */
517#ifdef SUNOS4
518		xprintf("%ld", pagetok(r1->ru_maxrss));
519#else
520# ifdef	convex
521		xprintf("%ld", r1->ru_maxrss * 4L);
522# else /* !convex */
523		xprintf("%ld", r1->ru_maxrss / 2L);
524# endif	/* convex */
525#endif /* SUNOS4 */
526		break;
527
528	    case 'F':		/* page	faults */
529		xprintf("%ld", r1->ru_majflt - r0->ru_majflt);
530		break;
531
532	    case 'R':		/* page	reclaims */
533		xprintf("%ld", r1->ru_minflt - r0->ru_minflt);
534		break;
535
536	    case 'I':		/* FS blocks in	*/
537		xprintf("%ld", r1->ru_inblock -	r0->ru_inblock);
538		break;
539
540	    case 'O':		/* FS blocks out */
541		xprintf("%ld", r1->ru_oublock -	r0->ru_oublock);
542		break;
543
544# ifdef	convex
545	    case 'C':			/*  CPU	parallelization	factor */
546		if (r1->ru_usamples	!= 0LL)	{
547		    long long parr = ((r1->ru_utotal * 100LL) /
548				      r1->ru_usamples);
549		    xprintf("%d.%02d", (int)(parr/100), (int)(parr%100));
550		} else
551		    xprintf("?");
552		break;
553# endif	/* convex */
554	    case 'r':		/* PWP:	socket messages	recieved */
555		xprintf("%ld", r1->ru_msgrcv - r0->ru_msgrcv);
556		break;
557
558	    case 's':		/* PWP:	socket messages	sent */
559		xprintf("%ld", r1->ru_msgsnd - r0->ru_msgsnd);
560		break;
561
562	    case 'k':		/* PWP:	signals	received */
563		xprintf("%ld", r1->ru_nsignals - r0->ru_nsignals);
564		break;
565
566	    case 'w':		/* PWP:	voluntary context switches (waits) */
567		xprintf("%ld", r1->ru_nvcsw - r0->ru_nvcsw);
568		break;
569
570	    case 'c':		/* PWP:	involuntary context switches */
571		xprintf("%ld", r1->ru_nivcsw - r0->ru_nivcsw);
572		break;
573#else /* BSDTIMES */
574# ifdef	_SEQUENT_
575	    case 'W':		/* number of swaps */
576		i = r1->ps_swap	- r0->ps_swap;
577		xprintf("%ld", i);
578		break;
579
580	    case 'M':
581		xprintf("%ld", r1->ps_maxrss / 2);
582		break;
583
584	    case 'F':
585		xprintf("%ld", r1->ps_pagein - r0->ps_pagein);
586		break;
587
588	    case 'R':
589		xprintf("%ld", r1->ps_reclaim -	r0->ps_reclaim);
590		break;
591
592	    case 'I':
593		xprintf("%ld", r1->ps_bread - r0->ps_bread);
594		break;
595
596	    case 'O':
597		xprintf("%ld", r1->ps_bwrite - r0->ps_bwrite);
598		break;
599
600	    case 'k':
601		xprintf("%ld", r1->ps_signal - r0->ps_signal);
602		break;
603
604	    case 'w':
605		xprintf("%ld", r1->ps_volcsw - r0->ps_volcsw);
606		break;
607
608	    case 'c':
609		xprintf("%ld", r1->ps_involcsw - r0->ps_involcsw);
610		break;
611
612	    case 'Z':
613		xprintf("%ld", r1->ps_zerofill - r0->ps_zerofill);
614		break;
615
616	    case 'i':
617		xprintf("%ld", r1->ps_pffincr -	r0->ps_pffincr);
618		break;
619
620	    case 'd':
621		xprintf("%ld", r1->ps_pffdecr -	r0->ps_pffdecr);
622		break;
623
624	    case 'Y':
625		xprintf("%ld", r1->ps_syscall -	r0->ps_syscall);
626		break;
627
628	    case 'l':
629		xprintf("%ld", r1->ps_lread - r0->ps_lread);
630		break;
631
632	    case 'm':
633		xprintf("%ld", r1->ps_lwrite - r0->ps_lwrite);
634		break;
635
636	    case 'p':
637		xprintf("%ld", r1->ps_phread - r0->ps_phread);
638		break;
639
640	    case 'q':
641		xprintf("%ld", r1->ps_phwrite -	r0->ps_phwrite);
642		break;
643# endif	/* _SEQUENT_ */
644#endif /* BSDTIMES */
645	    default:
646		break;
647	    }
648    xputchar('\n');
649}
650
651#if defined(BSDTIMES) || defined(_SEQUENT_)
652static void
653pdeltat(t1, t0)
654    timeval_t *t1, *t0;
655{
656    timeval_t td;
657
658    tvsub(&td, t1, t0);
659    xprintf("%ld.%03ld", td.tv_sec, td.tv_usec / 1000L);
660}
661
662static void
663tvadd(tsum, t0)
664    timeval_t *tsum, *t0;
665{
666
667    tsum->tv_sec += t0->tv_sec;
668    tsum->tv_usec += t0->tv_usec;
669    if (tsum->tv_usec >= 1000000)
670	tsum->tv_sec++,	tsum->tv_usec -= 1000000;
671}
672
673void
674tvsub(tdiff, t1, t0)
675    timeval_t *tdiff, *t1, *t0;
676{
677
678    tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
679    tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
680    if (tdiff->tv_usec < 0)
681	tdiff->tv_sec--, tdiff->tv_usec	+= 1000000;
682}
683
684#else /* !BSDTIMES && !_SEQUENT_ */
685static void
686pdtimet(eval, bval)
687#ifndef	POSIX
688    time_t  eval, bval;
689
690#else /* POSIX */
691    clock_t eval, bval;
692
693#endif /* POSIX	*/
694{
695#ifndef	POSIX
696    time_t  val;
697
698#else /* POSIX */
699    clock_t val;
700
701#endif /* POSIX	*/
702
703#ifndef	POSIX
704    val	= (eval	- bval)	* 100 /	HZ;
705#else /* POSIX */
706    val	= (eval	- bval)	* 100 /	clk_tck;
707#endif /* POSIX	*/
708
709    xprintf("%ld.%02ld", val / 100, val	- (val / 100 * 100));
710}
711#endif /* BSDTIMES || _SEQUENT_	*/
712