sh.time.c revision 167466
1204076Spjd/* $Header: /p/tcsh/cvsroot/tcsh/sh.time.c,v 3.33 2006/03/02 18:46:44 christos Exp $ */
2204076Spjd/*
3210886Spjd * sh.time.c: Shell time keeping and printing.
4204076Spjd */
5204076Spjd/*-
6204076Spjd * Copyright (c) 1980, 1991 The	Regents	of the University of California.
7204076Spjd * All rights reserved.
8204076Spjd *
9204076Spjd * Redistribution and use in source and	binary forms, with or without
10204076Spjd * modification, are permitted provided	that the following conditions
11204076Spjd * are met:
12204076Spjd * 1. Redistributions of source	code must retain the above copyright
13204076Spjd *    notice, this list	of conditions and the following	disclaimer.
14204076Spjd * 2. Redistributions in binary	form must reproduce the	above copyright
15204076Spjd *    notice, this list	of conditions and the following	disclaimer in the
16204076Spjd *    documentation and/or other materials provided with the distribution.
17204076Spjd * 3. Neither the name of the University nor the names of its contributors
18204076Spjd *    may be used to endorse or	promote	products derived from this software
19204076Spjd *    without specific prior written permission.
20204076Spjd *
21204076Spjd * THIS	SOFTWARE IS PROVIDED BY	THE REGENTS AND	CONTRIBUTORS ``AS IS'' AND
22204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24204076Spjd * ARE DISCLAIMED.  IN NO EVENT	SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR	CONSEQUENTIAL
26204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27204076Spjd * OR SERVICES;	LOSS OF	USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31204076Spjd * SUCH	DAMAGE.
32204076Spjd */
33204076Spjd#include "sh.h"
34204076Spjd
35204076SpjdRCSID("$tcsh: sh.time.c,v 3.33 2006/03/02 18:46:44 christos Exp $")
36204076Spjd
37204076Spjd#ifdef SUNOS4
38204076Spjd# include <machine/param.h>
39204076Spjd#endif /* SUNOS4 */
40204076Spjd
41204076Spjd/*
42204076Spjd * C Shell - routines handling process timing and niceing
43204076Spjd */
44204076Spjd#ifdef BSDTIMES
45204076Spjd# ifndef RUSAGE_SELF
46204076Spjd#  define	RUSAGE_SELF	0
47204076Spjd#  define	RUSAGE_CHILDREN	-1
48204076Spjd# endif	/* RUSAGE_SELF */
49211982Spjd#else /* BSDTIMES */
50204076Spjdstruct tms times0;
51204076Spjd#endif /* BSDTIMES */
52204076Spjd
53204076Spjd#if !defined(BSDTIMES) && !defined(_SEQUENT_)
54204076Spjd# ifdef	POSIX
55204076Spjdstatic	void	pdtimet	(clock_t, clock_t);
56204076Spjd# else /* ! POSIX */
57204076Spjdstatic	void	pdtimet	(time_t, time_t);
58204076Spjd# endif	/* ! POSIX */
59204076Spjd#else /* BSDTIMES || _SEQUENT_ */
60204076Spjdstatic	void	tvadd	(timeval_t *, timeval_t *);
61212038Spjdstatic	void	pdeltat	(timeval_t *, timeval_t *);
62204076Spjd#endif /* BSDTIMES || _SEQUENT_	*/
63204076Spjd
64204076Spjdvoid
65211886Spjdsettimes(void)
66204076Spjd{
67204076Spjd#ifdef BSDTIMES
68204076Spjd    struct sysrusage ruch;
69204076Spjd#ifdef convex
70204076Spjd    memset(&ru0, 0, sizeof(ru0));
71204076Spjd    memset(&ruch, 0, sizeof(ruch));
72210886Spjd#endif /* convex */
73210886Spjd
74210886Spjd    (void) gettimeofday(&time0,	NULL);
75204076Spjd    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru0);
76204076Spjd    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
77204076Spjd    ruadd(&ru0,	&ruch);
78204076Spjd#else
79204076Spjd# ifdef	_SEQUENT_
80204076Spjd    struct process_stats ruch;
81204076Spjd
82204076Spjd    (void) get_process_stats(&time0, PS_SELF, &ru0, &ruch);
83204076Spjd    ruadd(&ru0,	&ruch);
84204076Spjd# else	/* _SEQUENT_ */
85204076Spjd    seconds0 = time(NULL);
86204076Spjd    time0 = times(&times0);
87204076Spjd    times0.tms_stime +=	times0.tms_cstime;
88204076Spjd    times0.tms_utime +=	times0.tms_cutime;
89204076Spjd    times0.tms_cstime =	0;
90204076Spjd    times0.tms_cutime =	0;
91204076Spjd# endif	/* _SEQUENT_ */
92204076Spjd#endif /* BSDTIMES */
93204076Spjd}
94204076Spjd
95204076Spjd/*
96204076Spjd * dotime is only called if it is truly	a builtin function and not a
97204076Spjd * prefix to another command
98204076Spjd */
99204076Spjd/*ARGSUSED*/
100204076Spjdvoid
101204076Spjddotime(Char **v, struct command *c)
102204076Spjd{
103204076Spjd#ifdef BSDTIMES
104204076Spjd    timeval_t timedol;
105204076Spjd    struct sysrusage ru1, ruch;
106204076Spjd#ifdef convex
107204076Spjd    memset(&ru1, 0, sizeof(ru1));
108204076Spjd    memset(&ruch, 0, sizeof(ruch));
109204076Spjd#endif /* convex */
110204076Spjd
111204076Spjd    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru1);
112204076Spjd    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
113204076Spjd    ruadd(&ru1,	&ruch);
114204076Spjd    (void) gettimeofday(&timedol, NULL);
115204076Spjd    prusage(&ru0, &ru1,	&timedol, &time0);
116204076Spjd#else
117204076Spjd# ifdef	_SEQUENT_
118204076Spjd    timeval_t timedol;
119204076Spjd    struct process_stats ru1, ruch;
120204076Spjd
121204076Spjd    (void) get_process_stats(&timedol, PS_SELF,	&ru1, &ruch);
122204076Spjd    ruadd(&ru1,	&ruch);
123204076Spjd    prusage(&ru0, &ru1,	&timedol, &time0);
124204076Spjd# else /* _SEQUENT_ */
125204076Spjd#  ifndef POSIX
126204076Spjd    time_t  timedol;
127204076Spjd#  else	/* POSIX */
128204076Spjd    clock_t timedol;
129204076Spjd#  endif /* POSIX */
130204076Spjd
131204076Spjd    struct tms times_dol;
132204076Spjd
133204076Spjd    timedol = times(&times_dol);
134204076Spjd    times_dol.tms_stime	+= times_dol.tms_cstime;
135204076Spjd    times_dol.tms_utime	+= times_dol.tms_cutime;
136204076Spjd    times_dol.tms_cstime = 0;
137204076Spjd    times_dol.tms_cutime = 0;
138204076Spjd    prusage(&times0, &times_dol, timedol, time0);
139204076Spjd# endif	/* _SEQUENT_ */
140204076Spjd#endif /* BSDTIMES */
141204076Spjd    USE(c);
142204076Spjd    USE(v);
143204076Spjd}
144204076Spjd
145204076Spjd/*
146204076Spjd * donice is only called when it on the	line by	itself or with a +- value
147204076Spjd */
148204076Spjd/*ARGSUSED*/
149204076Spjdvoid
150204076Spjddonice(Char **v, struct command *c)
151204076Spjd{
152204076Spjd    Char *cp;
153204076Spjd    int	    nval = 0;
154204076Spjd
155211982Spjd    USE(c);
156204076Spjd    v++, cp = *v++;
157211982Spjd    if (cp == 0)
158204076Spjd	nval = 4;
159204076Spjd    else if (*v	== 0 &&	any("+-", cp[0]))
160204076Spjd	nval = getn(cp);
161204076Spjd#ifdef HAVE_SETPRIORITY
162204076Spjd    if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno)
163204076Spjd	stderror(ERR_SYSTEM, "setpriority", strerror(errno));
164204076Spjd#else /* !HAVE_SETPRIORITY */
165204076Spjd    (void) nice(nval);
166204076Spjd#endif /* HAVE_SETPRIORITY */
167204076Spjd}
168204076Spjd
169204076Spjd#ifdef BSDTIMES
170204076Spjdvoid
171204076Spjdruadd(struct sysrusage *ru, struct sysrusage *ru2)
172204076Spjd{
173204076Spjd    tvadd(&ru->ru_utime, &ru2->ru_utime);
174204076Spjd    tvadd(&ru->ru_stime, &ru2->ru_stime);
175204076Spjd#ifndef _OSD_POSIX
176204076Spjd    if (ru2->ru_maxrss > ru->ru_maxrss)
177204076Spjd	ru->ru_maxrss =	ru2->ru_maxrss;
178204076Spjd
179204076Spjd    ru->ru_ixrss += ru2->ru_ixrss;
180204076Spjd    ru->ru_idrss += ru2->ru_idrss;
181204076Spjd    ru->ru_isrss += ru2->ru_isrss;
182204076Spjd    ru->ru_minflt += ru2->ru_minflt;
183214692Spjd    ru->ru_majflt += ru2->ru_majflt;
184214692Spjd    ru->ru_nswap += ru2->ru_nswap;
185214692Spjd    ru->ru_inblock += ru2->ru_inblock;
186204076Spjd    ru->ru_oublock += ru2->ru_oublock;
187214692Spjd    ru->ru_msgsnd += ru2->ru_msgsnd;
188214692Spjd    ru->ru_msgrcv += ru2->ru_msgrcv;
189214692Spjd    ru->ru_nsignals += ru2->ru_nsignals;
190214692Spjd    ru->ru_nvcsw += ru2->ru_nvcsw;
191214692Spjd    ru->ru_nivcsw += ru2->ru_nivcsw;
192214692Spjd#endif /*bs2000*/
193204076Spjd
194214692Spjd# ifdef	convex
195214692Spjd    tvadd(&ru->ru_exutime, &ru2->ru_exutime);
196214692Spjd    ru->ru_utotal += ru2->ru_utotal;
197214692Spjd    ru->ru_usamples += ru2->ru_usamples;
198204076Spjd    ru->ru_stotal += ru2->ru_stotal;
199204076Spjd    ru->ru_ssamples += ru2->ru_ssamples;
200204076Spjd# endif	/* convex */
201204076Spjd}
202204076Spjd
203204076Spjd#else /* BSDTIMES */
204204076Spjd# ifdef	_SEQUENT_
205204076Spjdvoid
206204076Spjdruadd(struct process_stats *ru, struct process_stats *ru2)
207204076Spjd{
208204076Spjd    tvadd(&ru->ps_utime, &ru2->ps_utime);
209204076Spjd    tvadd(&ru->ps_stime, &ru2->ps_stime);
210209183Spjd    if (ru2->ps_maxrss > ru->ps_maxrss)
211209183Spjd	ru->ps_maxrss =	ru2->ps_maxrss;
212209183Spjd
213209183Spjd    ru->ps_pagein += ru2->ps_pagein;
214204076Spjd    ru->ps_reclaim += ru2->ps_reclaim;
215204076Spjd    ru->ps_zerofill += ru2->ps_zerofill;
216204076Spjd    ru->ps_pffincr += ru2->ps_pffincr;
217204076Spjd    ru->ps_pffdecr += ru2->ps_pffdecr;
218204076Spjd    ru->ps_swap	+= ru2->ps_swap;
219204076Spjd    ru->ps_syscall += ru2->ps_syscall;
220204076Spjd    ru->ps_volcsw += ru2->ps_volcsw;
221204076Spjd    ru->ps_involcsw += ru2->ps_involcsw;
222204076Spjd    ru->ps_signal += ru2->ps_signal;
223204076Spjd    ru->ps_lread += ru2->ps_lread;
224204076Spjd    ru->ps_lwrite += ru2->ps_lwrite;
225204076Spjd    ru->ps_bread += ru2->ps_bread;
226204076Spjd    ru->ps_bwrite += ru2->ps_bwrite;
227204076Spjd    ru->ps_phread += ru2->ps_phread;
228204076Spjd    ru->ps_phwrite += ru2->ps_phwrite;
229204076Spjd}
230204076Spjd
231204076Spjd# endif	/* _SEQUENT_ */
232204076Spjd#endif /* BSDTIMES */
233204076Spjd
234204076Spjd#ifdef BSDTIMES
235204076Spjd
236211982Spjd/*
237204076Spjd * PWP:	the LOG1024 and	pagetok	stuff taken from the top command,
238204076Spjd * written by William LeFebvre
239204076Spjd */
240204076Spjd/* Log base 2 of 1024 is 10 (2^10 == 1024) */
241204076Spjd#define	LOG1024		10
242204076Spjd
243204076Spjd/* Convert clicks (kernel pages) to kbytes ... */
244204076Spjd/* If there is no PGSHIFT defined, assume it is	11 */
245204076Spjd/* Is this needed for compatability with some old flavor of 4.2	or 4.1?	*/
246204076Spjd#ifdef SUNOS4
247204076Spjd# ifndef PGSHIFT
248213533Spjd#  define pagetok(size)	  ((size) << 1)
249204076Spjd# else
250204076Spjd#  if PGSHIFT>10
251204076Spjd#   define pagetok(size)   ((size) << (PGSHIFT - LOG1024))
252204076Spjd#  else
253213531Spjd#   define pagetok(size)   ((size) >> (LOG1024 - PGSHIFT))
254213531Spjd#  endif
255204076Spjd# endif
256204076Spjd#endif
257204076Spjd
258204076Spjd/*
259204076Spjd * if any other	machines return	wierd values in	the ru_i* stuff, put
260204076Spjd * the adjusting macro here:
261204076Spjd */
262204076Spjd#ifdef SUNOS4
263204076Spjd# define IADJUST(i)	(pagetok(i)/2)
264212899Spjd#else /* SUNOS4	*/
265204076Spjd# ifdef	convex
266204076Spjd   /*
267204076Spjd    * convex has megabytes * CLK_TCK
268204076Spjd    * multiply by 100 since we use time	in 100ths of a second in prusage
269204076Spjd    */
270204076Spjd#  define IADJUST(i) (((i) << 10) / CLK_TCK * 100)
271204076Spjd# else /* convex */
272204076Spjd#  define IADJUST(i)	(i)
273204076Spjd# endif	/* convex */
274204076Spjd#endif /* SUNOS4 */
275204076Spjd
276204076Spjdvoid
277212899Spjdprusage(struct sysrusage *r0, struct sysrusage *r1, timeval_t *e, timeval_t *b)
278204076Spjd
279204076Spjd#else /* BSDTIMES */
280204076Spjd# ifdef	_SEQUENT_
281204076Spjdvoid
282204076Spjdprusage(struct process_stats *r0, struct process_stats *r1, timeval_t e,
283204076Spjd	timeval_t b)
284204076Spjd
285204076Spjd# else /* _SEQUENT_ */
286204076Spjd#  ifndef POSIX
287204076Spjdvoid
288204076Spjdprusage(struct tms *bs, struct tms *es, time_t e, time_t b)
289204076Spjd#  else	/* POSIX */
290204076Spjdvoid
291204076Spjdprusage(struct tms *bs, struct tms *es, clock_t e, clock_t b)
292204076Spjd#  endif /* POSIX */
293204076Spjd# endif	/* _SEQUENT_ */
294204076Spjd#endif /* BSDTIMES */
295204076Spjd{
296204076Spjd#ifdef BSDTIMES
297204076Spjd    time_t t =
298204076Spjd    (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec)	* 100 +
299204076Spjd    (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
300204076Spjd    (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec)	* 100 +
301204076Spjd    (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
302204076Spjd
303204076Spjd#else
304204076Spjd# ifdef	_SEQUENT_
305204076Spjd    time_t t =
306204076Spjd    (r1->ps_utime.tv_sec - r0->ps_utime.tv_sec)	* 100 +
307210881Spjd    (r1->ps_utime.tv_usec - r0->ps_utime.tv_usec) / 10000 +
308210881Spjd    (r1->ps_stime.tv_sec - r0->ps_stime.tv_sec)	* 100 +
309210881Spjd    (r1->ps_stime.tv_usec - r0->ps_stime.tv_usec) / 10000;
310210881Spjd
311210881Spjd# else /* _SEQUENT_ */
312210881Spjd#  ifndef POSIX
313210881Spjd    time_t t =	(es->tms_utime - bs->tms_utime +
314204076Spjd			 es->tms_stime - bs->tms_stime)	* 100 /	HZ;
315204076Spjd
316204076Spjd#  else	/* POSIX */
317204076Spjd    clock_t t = (es->tms_utime	- bs->tms_utime	+
318204076Spjd			  es->tms_stime	- bs->tms_stime) * 100 / clk_tck;
319204076Spjd
320204076Spjd#  endif /* POSIX */
321204076Spjd# endif	/* _SEQUENT_ */
322204076Spjd#endif /* BSDTIMES */
323204076Spjd
324204076Spjd    const char *cp;
325204076Spjd    long i;
326204076Spjd    struct varent *vp = adrof(STRtime);
327204076Spjd
328204076Spjd#ifdef BSDTIMES
329204076Spjd# ifdef	convex
330204076Spjd    static struct system_information sysinfo;
331204076Spjd    long long memtmp;	/* let memory calculations exceede 2Gb */
332204076Spjd# endif	/* convex */
333204076Spjd    int	    ms = (int)
334204076Spjd    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
335204076Spjd
336204076Spjd    cp = "%Uu %Ss %E %P	%X+%Dk %I+%Oio %Fpf+%Ww";
337204076Spjd#else /* !BSDTIMES */
338204076Spjd# ifdef	_SEQUENT_
339204076Spjd    int	    ms = (int)
340204076Spjd    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
341204076Spjd
342204076Spjd    cp = "%Uu %Ss %E %P	%I+%Oio	%Fpf+%Ww";
343204076Spjd# else /* !_SEQUENT_ */
344204076Spjd#  ifndef POSIX
345204076Spjd    time_t ms = ((time_t)((e - b) / HZ) * 100) +
346204076Spjd		 (time_t)(((e - b) % HZ) * 100) / HZ;
347204076Spjd#  else	/* POSIX */
348204076Spjd    clock_t ms = ((clock_t)((e - b) / clk_tck) * 100) +
349204076Spjd		  (clock_t)(((e - b) % clk_tck) * 100) / clk_tck;
350204076Spjd#  endif /* POSIX */
351204076Spjd
352204076Spjd    cp = "%Uu %Ss %E %P";
353204076Spjd
354204076Spjd    /*
355204076Spjd     * the tms stuff is	not very precise, so we	fudge it.
356204076Spjd     * granularity fix:	can't be more than 100%
357204076Spjd     * this breaks in multi-processor systems...
358204076Spjd     * maybe I should take it out and let people see more then 100%
359204076Spjd     * utilizations.
360204076Spjd     */
361204076Spjd#  if 0
362204076Spjd    if (ms < t && ms !=	0)
363204076Spjd	ms = t;
364204076Spjd#  endif
365204076Spjd# endif	/*! _SEQUENT_ */
366204076Spjd#endif /* !BSDTIMES */
367204076Spjd#ifdef TDEBUG
368204076Spjd    xprintf("es->tms_utime %lu bs->tms_utime %lu\n",
369204076Spjd	    es->tms_utime, bs->tms_utime);
370204076Spjd    xprintf("es->tms_stime %lu bs->tms_stime %lu\n",
371204076Spjd	    es->tms_stime, bs->tms_stime);
372204076Spjd    xprintf("ms	%lu e %lu b %lu\n", ms,	e, b);
373204076Spjd    xprintf("t %lu\n", t);
374204076Spjd#endif /* TDEBUG */
375204076Spjd
376204076Spjd    if (vp && vp->vec && vp->vec[0] && vp->vec[1])
377204076Spjd	cp = short2str(vp->vec[1]);
378204076Spjd    for	(; *cp;	cp++)
379204076Spjd	if (*cp	!= '%')
380204076Spjd	    xputchar(*cp);
381204076Spjd	else if	(cp[1])
382204076Spjd	    switch (*++cp) {
383204076Spjd
384204076Spjd	    case 'U':		/* user	CPU time used */
385204076Spjd#ifdef BSDTIMES
386204076Spjd		pdeltat(&r1->ru_utime, &r0->ru_utime);
387204076Spjd#else
388204076Spjd# ifdef	_SEQUENT_
389204076Spjd		pdeltat(&r1->ps_utime, &r0->ps_utime);
390204076Spjd# else /* _SEQUENT_ */
391204076Spjd#  ifndef POSIX
392204076Spjd		pdtimet(es->tms_utime, bs->tms_utime);
393204076Spjd#  else	/* POSIX */
394204076Spjd		pdtimet(es->tms_utime, bs->tms_utime);
395204076Spjd#  endif /* POSIX */
396204076Spjd# endif	/* _SEQUENT_ */
397204076Spjd#endif /* BSDTIMES */
398204076Spjd		break;
399204076Spjd
400204076Spjd	    case 'S':		/* system CPU time used	*/
401204076Spjd#ifdef BSDTIMES
402204076Spjd		pdeltat(&r1->ru_stime, &r0->ru_stime);
403204076Spjd#else
404204076Spjd# ifdef	_SEQUENT_
405204076Spjd		pdeltat(&r1->ps_stime, &r0->ps_stime);
406204076Spjd# else /* _SEQUENT_ */
407204076Spjd#  ifndef POSIX
408204076Spjd		pdtimet(es->tms_stime, bs->tms_stime);
409204076Spjd#  else	/* POSIX */
410204076Spjd		pdtimet(es->tms_stime, bs->tms_stime);
411204076Spjd#  endif /* POSIX */
412204076Spjd# endif	/* _SEQUENT_ */
413204076Spjd#endif /* BSDTIMES */
414204076Spjd		break;
415204076Spjd
416204076Spjd	    case 'E':		/* elapsed (wall-clock)	time */
417204076Spjd#ifdef BSDTIMES
418204076Spjd		pcsecs((long) ms);
419204076Spjd#else /* BSDTIMES */
420204076Spjd		pcsecs(ms);
421204076Spjd#endif /* BSDTIMES */
422204076Spjd		break;
423204076Spjd
424204076Spjd	    case 'P':		/* percent time	spent running */
425204076Spjd		/* check if the	process	did not	run */
426204076Spjd#ifdef convex
427214284Spjd		/*
428214284Spjd		 * scale the cpu %- ages by the	number of processors
429214284Spjd		 * available on	this machine
430214284Spjd		 */
431214284Spjd		if ((sysinfo.cpu_count == 0) &&
432214284Spjd		    (getsysinfo(SYSINFO_SIZE, &sysinfo)	< 0))
433214284Spjd		    sysinfo.cpu_count =	1;
434214284Spjd		    i =	(ms == 0) ? 0 :	(t * 1000.0 / (ms * sysinfo.cpu_count));
435214284Spjd#else /* convex	*/
436214284Spjd		i = (ms	== 0) ?	0 : (long)(t * 1000.0 / ms);
437214284Spjd#endif /* convex */
438214284Spjd		xprintf("%ld.%01ld%%", i / 10, i % 10);	/* nn.n% */
439214284Spjd		break;
440214284Spjd
441214284Spjd#ifdef BSDTIMES
442214284Spjd	    case 'W':		/* number of swaps */
443214284Spjd#ifdef _OSD_POSIX
444214284Spjd		i = 0;
445204076Spjd#else
446204076Spjd		i = r1->ru_nswap - r0->ru_nswap;
447204076Spjd#endif
448204076Spjd		xprintf("%ld", i);
449204076Spjd		break;
450204076Spjd
451204076Spjd#ifdef convex
452204076Spjd	    case 'X':		/* (average) shared text size */
453204076Spjd		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_ixrss -
454204076Spjd				 (long long)r0->ru_ixrss) /
455204076Spjd			 (long long)t);
456204076Spjd		xprintf("%lu", (unsigned long)memtmp);
457204076Spjd		break;
458204076Spjd
459204076Spjd	    case 'D':		/* (average) unshared data size	*/
460204076Spjd		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_idrss +
461204076Spjd				 (long long)r1->ru_isrss -
462204076Spjd				 ((long	long)r0->ru_idrss +
463204076Spjd				  (long	long)r0->ru_isrss)) /
464204076Spjd			 (long long)t);
465204076Spjd		xprintf("%lu", (unsigned long)memtmp);
466204076Spjd		break;
467204076Spjd
468204076Spjd	    case 'K':		/* (average) total data	memory used  */
469204076Spjd		memtmp = (t == 0 ? 0LL : IADJUST(((long	long)r1->ru_ixrss +
470204076Spjd				  (long	long)r1->ru_isrss +
471204076Spjd				  (long	long)r1->ru_idrss) -
472204076Spjd				  ((long long)r0->ru_ixrss +
473204076Spjd				   (long long)r0->ru_idrss +
474204076Spjd				   (long long)r0->ru_isrss)) /
475204076Spjd			 (long long)t);
476209181Spjd		xprintf("%lu", (unsigned long)memtmp);
477204076Spjd		break;
478204076Spjd#else /* !convex */
479204076Spjd	    case 'X':		/* (average) shared text size */
480214284Spjd#ifdef _OSD_POSIX
481214284Spjd		xprintf("0",0);
482214284Spjd#else
483214284Spjd		xprintf("%ld", t == 0 ?	0L :
484214284Spjd			IADJUST(r1->ru_ixrss - r0->ru_ixrss) / t);
485204076Spjd#endif
486204076Spjd		break;
487204076Spjd
488204076Spjd	    case 'D':		/* (average) unshared data size	*/
489204076Spjd#ifdef _OSD_POSIX
490204076Spjd		xprintf("0",0);
491204076Spjd#else
492205738Spjd		xprintf("%ld", t == 0 ?	0L :
493205738Spjd			IADJUST(r1->ru_idrss + r1->ru_isrss -
494205738Spjd				(r0->ru_idrss +	r0->ru_isrss)) / t);
495204076Spjd#endif
496205738Spjd		break;
497204076Spjd
498204076Spjd	    case 'K':		/* (average) total data	memory used  */
499204076Spjd#ifdef _OSD_POSIX
500204076Spjd		xprintf("0",0);
501204076Spjd#else
502204076Spjd		xprintf("%ld", t == 0 ?	0L :
503204076Spjd			IADJUST((r1->ru_ixrss +	r1->ru_isrss + r1->ru_idrss) -
504204076Spjd			   (r0->ru_ixrss + r0->ru_idrss	+ r0->ru_isrss)) / t);
505204076Spjd#endif
506205738Spjd		break;
507210881Spjd#endif /* convex */
508205738Spjd	    case 'M':		/* max.	Resident Set Size */
509205738Spjd#ifdef SUNOS4
510211983Spjd		xprintf("%ld", pagetok(r1->ru_maxrss));
511205738Spjd#else
512204076Spjd# ifdef	convex
513205738Spjd		xprintf("%ld", r1->ru_maxrss * 4L);
514215331Spjd# else /* !convex */
515215331Spjd#  ifdef _OSD_POSIX
516204076Spjd		xprintf("0",0);
517204076Spjd#  else
518204076Spjd		xprintf("%ld", r1->ru_maxrss / 2L);
519205738Spjd#  endif
520204076Spjd# endif	/* convex */
521204076Spjd#endif /* SUNOS4 */
522204076Spjd		break;
523204076Spjd
524207371Spjd	    case 'F':		/* page	faults */
525207371Spjd#ifdef _OSD_POSIX
526207371Spjd		xprintf("0",0);
527204076Spjd#else
528204076Spjd		xprintf("%ld", r1->ru_majflt - r0->ru_majflt);
529204076Spjd#endif
530204076Spjd		break;
531204076Spjd
532204076Spjd	    case 'R':		/* page	reclaims */
533204076Spjd#ifdef _OSD_POSIX
534204076Spjd		xprintf("0",0);
535204076Spjd#else
536204076Spjd		xprintf("%ld", r1->ru_minflt - r0->ru_minflt);
537204076Spjd#endif
538204076Spjd		break;
539204076Spjd
540205738Spjd	    case 'I':		/* FS blocks in	*/
541204076Spjd#ifdef _OSD_POSIX
542204076Spjd		xprintf("0",0);
543204076Spjd#else
544204076Spjd		xprintf("%ld", r1->ru_inblock -	r0->ru_inblock);
545204076Spjd#endif
546204076Spjd		break;
547204076Spjd
548205738Spjd	    case 'O':		/* FS blocks out */
549204076Spjd#ifdef _OSD_POSIX
550204076Spjd		xprintf("0",0);
551204076Spjd#else
552204076Spjd		xprintf("%ld", r1->ru_oublock -	r0->ru_oublock);
553204076Spjd#endif
554204076Spjd		break;
555204076Spjd
556204076Spjd# ifdef	convex
557204076Spjd	    case 'C':			/*  CPU	parallelization	factor */
558204076Spjd		if (r1->ru_usamples	!= 0LL)	{
559204076Spjd		    long long parr = ((r1->ru_utotal * 100LL) /
560204076Spjd				      r1->ru_usamples);
561204076Spjd		    xprintf("%d.%02d", (int)(parr/100), (int)(parr%100));
562204076Spjd		} else
563204076Spjd		    xprintf("?");
564204076Spjd		break;
565204076Spjd# endif	/* convex */
566204076Spjd	    case 'r':		/* PWP:	socket messages	recieved */
567204076Spjd#ifdef _OSD_POSIX
568204076Spjd		xprintf("0",0);
569204076Spjd#else
570204076Spjd		xprintf("%ld", r1->ru_msgrcv - r0->ru_msgrcv);
571204076Spjd#endif
572204076Spjd		break;
573204076Spjd
574204076Spjd	    case 's':		/* PWP:	socket messages	sent */
575204076Spjd#ifdef _OSD_POSIX
576204076Spjd		xprintf("0",0);
577204076Spjd#else
578204076Spjd		xprintf("%ld", r1->ru_msgsnd - r0->ru_msgsnd);
579204076Spjd#endif
580205738Spjd		break;
581215331Spjd
582215331Spjd	    case 'k':		/* PWP:	signals	received */
583204076Spjd#ifdef _OSD_POSIX
584204076Spjd		xprintf("0",0);
585204076Spjd#else
586205738Spjd		xprintf("%ld", r1->ru_nsignals - r0->ru_nsignals);
587204076Spjd#endif
588204076Spjd		break;
589204076Spjd
590204076Spjd	    case 'w':		/* PWP:	voluntary context switches (waits) */
591207371Spjd#ifdef _OSD_POSIX
592207371Spjd		xprintf("0",0);
593207371Spjd#else
594204076Spjd		xprintf("%ld", r1->ru_nvcsw - r0->ru_nvcsw);
595204076Spjd#endif
596204076Spjd		break;
597204076Spjd
598214284Spjd	    case 'c':		/* PWP:	involuntary context switches */
599214284Spjd#ifdef _OSD_POSIX
600214284Spjd		xprintf("0",0);
601214284Spjd#else
602214284Spjd		xprintf("%ld", r1->ru_nivcsw - r0->ru_nivcsw);
603214284Spjd#endif
604214284Spjd		break;
605214284Spjd#else /* BSDTIMES */
606214284Spjd# ifdef	_SEQUENT_
607214284Spjd	    case 'W':		/* number of swaps */
608214284Spjd		i = r1->ps_swap	- r0->ps_swap;
609214284Spjd		xprintf("%ld", i);
610214284Spjd		break;
611204076Spjd
612204076Spjd	    case 'M':
613204076Spjd		xprintf("%ld", r1->ps_maxrss / 2);
614204076Spjd		break;
615204076Spjd
616204076Spjd	    case 'F':
617204076Spjd		xprintf("%ld", r1->ps_pagein - r0->ps_pagein);
618204076Spjd		break;
619204076Spjd
620204076Spjd	    case 'R':
621205738Spjd		xprintf("%ld", r1->ps_reclaim -	r0->ps_reclaim);
622204076Spjd		break;
623204076Spjd
624204076Spjd	    case 'I':
625204076Spjd		xprintf("%ld", r1->ps_bread - r0->ps_bread);
626204076Spjd		break;
627204076Spjd
628204076Spjd	    case 'O':
629205738Spjd		xprintf("%ld", r1->ps_bwrite - r0->ps_bwrite);
630204076Spjd		break;
631204076Spjd
632204076Spjd	    case 'k':
633204076Spjd		xprintf("%ld", r1->ps_signal - r0->ps_signal);
634204076Spjd		break;
635204076Spjd
636204076Spjd	    case 'w':
637204076Spjd		xprintf("%ld", r1->ps_volcsw - r0->ps_volcsw);
638204076Spjd		break;
639204076Spjd
640204076Spjd	    case 'c':
641204076Spjd		xprintf("%ld", r1->ps_involcsw - r0->ps_involcsw);
642204076Spjd		break;
643204076Spjd
644204076Spjd	    case 'Z':
645204076Spjd		xprintf("%ld", r1->ps_zerofill - r0->ps_zerofill);
646204076Spjd		break;
647204076Spjd
648204076Spjd	    case 'i':
649204076Spjd		xprintf("%ld", r1->ps_pffincr -	r0->ps_pffincr);
650204076Spjd		break;
651204076Spjd
652204076Spjd	    case 'd':
653204076Spjd		xprintf("%ld", r1->ps_pffdecr -	r0->ps_pffdecr);
654204076Spjd		break;
655204076Spjd
656204076Spjd	    case 'Y':
657204076Spjd		xprintf("%ld", r1->ps_syscall -	r0->ps_syscall);
658204076Spjd		break;
659204076Spjd
660204076Spjd	    case 'l':
661204076Spjd		xprintf("%ld", r1->ps_lread - r0->ps_lread);
662204076Spjd		break;
663204076Spjd
664204076Spjd	    case 'm':
665204076Spjd		xprintf("%ld", r1->ps_lwrite - r0->ps_lwrite);
666204076Spjd		break;
667204076Spjd
668204076Spjd	    case 'p':
669204076Spjd		xprintf("%ld", r1->ps_phread - r0->ps_phread);
670204076Spjd		break;
671204076Spjd
672205738Spjd	    case 'q':
673204076Spjd		xprintf("%ld", r1->ps_phwrite -	r0->ps_phwrite);
674204076Spjd		break;
675204076Spjd# endif	/* _SEQUENT_ */
676204076Spjd#endif /* BSDTIMES */
677204076Spjd	    default:
678204076Spjd		break;
679204076Spjd	    }
680204076Spjd    xputchar('\n');
681204076Spjd}
682204076Spjd
683204076Spjd#if defined(BSDTIMES) || defined(_SEQUENT_)
684204076Spjdstatic void
685204076Spjdpdeltat(timeval_t *t1, timeval_t *t0)
686204076Spjd{
687204076Spjd    timeval_t td;
688204076Spjd
689204076Spjd    tvsub(&td, t1, t0);
690204076Spjd    xprintf("%ld.%03ld", td.tv_sec, td.tv_usec / 1000L);
691214274Spjd}
692204076Spjd
693205738Spjdstatic void
694205738Spjdtvadd(timeval_t *tsum, timeval_t *t0)
695205738Spjd{
696205738Spjd
697205738Spjd    tsum->tv_sec += t0->tv_sec;
698205738Spjd    tsum->tv_usec += t0->tv_usec;
699205738Spjd    if (tsum->tv_usec >= 1000000)
700212038Spjd	tsum->tv_sec++,	tsum->tv_usec -= 1000000;
701205738Spjd}
702205738Spjd
703211983Spjdvoid
704212038Spjdtvsub(timeval_t *tdiff, timeval_t *t1, timeval_t *t0)
705205738Spjd{
706205738Spjd
707205738Spjd    tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
708205738Spjd    tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
709205738Spjd    if (tdiff->tv_usec < 0)
710205738Spjd	tdiff->tv_sec--, tdiff->tv_usec	+= 1000000;
711205738Spjd}
712205738Spjd
713205738Spjd#else /* !BSDTIMES && !_SEQUENT_ */
714205738Spjdstatic void
715204076Spjd#ifndef	POSIX
716204076Spjdpdtimet(time_t eval, time_t bval)
717204076Spjd
718204076Spjd#else /* POSIX */
719204076Spjdpdtimet(clock_t eval, clock_t bval)
720204076Spjd
721204076Spjd#endif /* POSIX	*/
722211878Spjd{
723211878Spjd#ifndef	POSIX
724211878Spjd    time_t  val;
725211878Spjd
726211878Spjd#else /* POSIX */
727211878Spjd    clock_t val;
728211878Spjd
729211878Spjd#endif /* POSIX	*/
730211878Spjd
731211878Spjd#ifndef	POSIX
732204076Spjd    val	= (eval	- bval)	* 100 /	HZ;
733204076Spjd#else /* POSIX */
734204076Spjd    val	= (eval	- bval)	* 100 /	clk_tck;
735204076Spjd#endif /* POSIX	*/
736204076Spjd
737204076Spjd    xprintf("%ld.%02ld", val / 100, val	- (val / 100 * 100));
738204076Spjd}
739204076Spjd#endif /* BSDTIMES || _SEQUENT_	*/
740204076Spjd