1 /* $NetBSD: time.c,v 1.16 2007/02/24 21:29:13 matt Exp $ */
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)time.c 8.1 (Berkeley) 5/31/93";
37 __RCSID("$NetBSD: time.c,v 1.16 2007/02/24 21:29:13 matt Exp $");
42 #include <sys/types.h>
49 * C Shell - routines handling process timing and niceing
51 static void pdeltat(FILE *, struct timeval
*, struct timeval
*);
52 static void pcsecs(FILE *, long);
53 extern char *strpct(u_long
, u_long
, u_int
);
61 (void)gettimeofday(&time0
, NULL
);
62 (void)getrusage(RUSAGE_SELF
, &ru0
);
63 (void)getrusage(RUSAGE_CHILDREN
, &ruch
);
68 * dotime is only called if it is truly a builtin function and not a
69 * prefix to another command
73 dotime(Char
**v
, struct command
*t
)
75 struct rusage ru1
, ruch
;
76 struct timeval timedol
;
78 (void)getrusage(RUSAGE_SELF
, &ru1
);
79 (void)getrusage(RUSAGE_CHILDREN
, &ruch
);
81 (void)gettimeofday(&timedol
, NULL
);
82 prusage(cshout
, &ru0
, &ru1
, &timedol
, &time0
);
86 * donice is only called when it on the line by itself or with a +- value
90 donice(Char
**v
, struct command
*t
)
100 else if (*v
== 0 && any("+-", cp
[0]))
102 (void)setpriority(PRIO_PROCESS
, 0, nval
);
106 ruadd(struct rusage
*ru
, struct rusage
*ru2
)
108 timeradd(&ru
->ru_utime
, &ru2
->ru_utime
, &ru
->ru_utime
);
109 timeradd(&ru
->ru_stime
, &ru2
->ru_stime
, &ru
->ru_stime
);
110 if (ru2
->ru_maxrss
> ru
->ru_maxrss
)
111 ru
->ru_maxrss
= ru2
->ru_maxrss
;
113 ru
->ru_ixrss
+= ru2
->ru_ixrss
;
114 ru
->ru_idrss
+= ru2
->ru_idrss
;
115 ru
->ru_isrss
+= ru2
->ru_isrss
;
116 ru
->ru_minflt
+= ru2
->ru_minflt
;
117 ru
->ru_majflt
+= ru2
->ru_majflt
;
118 ru
->ru_nswap
+= ru2
->ru_nswap
;
119 ru
->ru_inblock
+= ru2
->ru_inblock
;
120 ru
->ru_oublock
+= ru2
->ru_oublock
;
121 ru
->ru_msgsnd
+= ru2
->ru_msgsnd
;
122 ru
->ru_msgrcv
+= ru2
->ru_msgrcv
;
123 ru
->ru_nsignals
+= ru2
->ru_nsignals
;
124 ru
->ru_nvcsw
+= ru2
->ru_nvcsw
;
125 ru
->ru_nivcsw
+= ru2
->ru_nivcsw
;
130 prusage(FILE *fp
, struct rusage
*r0
, struct rusage
*r1
, struct timeval
*e
,
141 cp
= "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww";
142 ms
= (e
->tv_sec
- b
->tv_sec
) * 100 + (e
->tv_usec
- b
->tv_usec
) / 10000;
143 t
= (r1
->ru_utime
.tv_sec
- r0
->ru_utime
.tv_sec
) * 100 +
144 (r1
->ru_utime
.tv_usec
- r0
->ru_utime
.tv_usec
) / 10000 +
145 (r1
->ru_stime
.tv_sec
- r0
->ru_stime
.tv_sec
) * 100 +
146 (r1
->ru_stime
.tv_usec
- r0
->ru_stime
.tv_usec
) / 10000;
150 if (vp
&& vp
->vec
[0] && vp
->vec
[1])
151 cp
= short2str(vp
->vec
[1]);
156 (void) fputc(*cp
, fp
);
159 case 'D': /* (average) unshared data size */
160 (void)fprintf(fp
, "%ld", t
== 0 ? 0L :
161 (long)((r1
->ru_idrss
+ r1
->ru_isrss
-
162 (r0
->ru_idrss
+ r0
->ru_isrss
)) / t
));
164 case 'E': /* elapsed (wall-clock) time */
165 pcsecs(fp
, (long) ms
);
167 case 'F': /* page faults */
168 (void)fprintf(fp
, "%ld", r1
->ru_majflt
- r0
->ru_majflt
);
170 case 'I': /* FS blocks in */
171 (void)fprintf(fp
, "%ld", r1
->ru_inblock
- r0
->ru_inblock
);
173 case 'K': /* (average) total data memory used */
174 (void)fprintf(fp
, "%ld", t
== 0 ? 0L :
175 (long)(((r1
->ru_ixrss
+ r1
->ru_isrss
+ r1
->ru_idrss
) -
176 (r0
->ru_ixrss
+ r0
->ru_idrss
+ r0
->ru_isrss
)) / t
));
178 case 'M': /* max. Resident Set Size */
179 (void)fprintf(fp
, "%ld", r1
->ru_maxrss
/ 2L);
181 case 'O': /* FS blocks out */
182 (void)fprintf(fp
, "%ld", r1
->ru_oublock
- r0
->ru_oublock
);
184 case 'P': /* percent time spent running */
185 /* check if it did not run at all */
187 (void)fputs("0.0%", fp
);
189 (void)fputs(strpct((ulong
)t
, (ulong
)ms
, 1), fp
);
192 case 'R': /* page reclaims */
193 (void)fprintf(fp
, "%ld", r1
->ru_minflt
- r0
->ru_minflt
);
195 case 'S': /* system CPU time used */
196 pdeltat(fp
, &r1
->ru_stime
, &r0
->ru_stime
);
198 case 'U': /* user CPU time used */
199 pdeltat(fp
, &r1
->ru_utime
, &r0
->ru_utime
);
201 case 'W': /* number of swaps */
202 i
= r1
->ru_nswap
- r0
->ru_nswap
;
203 (void)fprintf(fp
, "%ld", i
);
205 case 'X': /* (average) shared text size */
206 (void)fprintf(fp
, "%ld", t
== 0 ? 0L :
207 (long)((r1
->ru_ixrss
- r0
->ru_ixrss
) / t
));
209 case 'c': /* num. involuntary context switches */
210 (void)fprintf(fp
, "%ld", r1
->ru_nivcsw
- r0
->ru_nivcsw
);
212 case 'k': /* number of signals received */
213 (void)fprintf(fp
, "%ld", r1
->ru_nsignals
-r0
->ru_nsignals
);
215 case 'r': /* socket messages received */
216 (void)fprintf(fp
, "%ld", r1
->ru_msgrcv
- r0
->ru_msgrcv
);
218 case 's': /* socket messages sent */
219 (void)fprintf(fp
, "%ld", r1
->ru_msgsnd
- r0
->ru_msgsnd
);
221 case 'w': /* num. voluntary context switches (waits) */
222 (void)fprintf(fp
, "%ld", r1
->ru_nvcsw
- r0
->ru_nvcsw
);
225 (void)fputc('\n', fp
);
229 pdeltat(FILE *fp
, struct timeval
*t1
, struct timeval
*t0
)
233 timersub(t1
, t0
, &td
);
234 (void)fprintf(fp
, "%ld.%01ld", (long)td
.tv_sec
,
235 (long)(td
.tv_usec
/ 100000));
238 #define P2DIG(fp, i) (void)fprintf(fp, "%d%d", (i) / 10, (i) % 10)
248 (void)fprintf(cshout
, "%d:", i
);
250 P2DIG(cshout
, i
/ 60);
254 (void)fprintf(cshout
, "%d", i
/ 60);
257 (void)fputc(':', cshout
);
263 pcsecs(FILE *fp
, long l
) /* PWP: print mm:ss.dd, l is in sec*100 */
269 (void)fprintf(fp
, "%d:", i
);
270 i
= (l
% 360000) / 100;
275 (void)fprintf(fp
, "%d", i
/ 60);
278 (void)fputc(':', fp
);
280 (void)fputc('.', fp
);
281 P2DIG(fp
, (int) (l
% 100));