time.c revision 1.15 1 /* $NetBSD: time.c,v 1.15 2005/06/26 19:10:48 christos Exp $ */
2
3 /*-
4 * Copyright (c) 1980, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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.
18 *
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
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33 #ifndef lint
34 #if 0
35 static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 5/31/93";
36 #else
37 __RCSID("$NetBSD: time.c,v 1.15 2005/06/26 19:10:48 christos Exp $");
38 #endif
39 #endif /* not lint */
40
41 #include <sys/types.h>
42
43 #include <stdarg.h>
44
45 #include "csh.h"
46 #include "extern.h"
47
48 /*
49 * C Shell - routines handling process timing and niceing
50 */
51 static void pdeltat(struct timeval *, struct timeval *);
52 extern char *strpct(u_long num, u_long denom, u_int digits);
53
54 void
55 settimes(void)
56 {
57 struct rusage ruch;
58
59 (void)gettimeofday(&time0, NULL);
60 (void)getrusage(RUSAGE_SELF, &ru0);
61 (void)getrusage(RUSAGE_CHILDREN, &ruch);
62 ruadd(&ru0, &ruch);
63 }
64
65 /*
66 * dotime is only called if it is truly a builtin function and not a
67 * prefix to another command
68 */
69 void
70 /*ARGSUSED*/
71 dotime(Char **v, struct command *t)
72 {
73 struct rusage ru1, ruch;
74 struct timeval timedol;
75
76 (void)getrusage(RUSAGE_SELF, &ru1);
77 (void)getrusage(RUSAGE_CHILDREN, &ruch);
78 ruadd(&ru1, &ruch);
79 (void)gettimeofday(&timedol, NULL);
80 prusage(&ru0, &ru1, &timedol, &time0);
81 }
82
83 /*
84 * donice is only called when it on the line by itself or with a +- value
85 */
86 void
87 /*ARGSUSED*/
88 donice(Char **v, struct command *t)
89 {
90 Char *cp;
91 int nval;
92
93 nval = 0;
94 v++;
95 cp = *v++;
96 if (cp == 0)
97 nval = 4;
98 else if (*v == 0 && any("+-", cp[0]))
99 nval = getn(cp);
100 (void)setpriority(PRIO_PROCESS, 0, nval);
101 }
102
103 void
104 ruadd(struct rusage *ru, struct rusage *ru2)
105 {
106 timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
107 timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
108 if (ru2->ru_maxrss > ru->ru_maxrss)
109 ru->ru_maxrss = ru2->ru_maxrss;
110
111 ru->ru_ixrss += ru2->ru_ixrss;
112 ru->ru_idrss += ru2->ru_idrss;
113 ru->ru_isrss += ru2->ru_isrss;
114 ru->ru_minflt += ru2->ru_minflt;
115 ru->ru_majflt += ru2->ru_majflt;
116 ru->ru_nswap += ru2->ru_nswap;
117 ru->ru_inblock += ru2->ru_inblock;
118 ru->ru_oublock += ru2->ru_oublock;
119 ru->ru_msgsnd += ru2->ru_msgsnd;
120 ru->ru_msgrcv += ru2->ru_msgrcv;
121 ru->ru_nsignals += ru2->ru_nsignals;
122 ru->ru_nvcsw += ru2->ru_nvcsw;
123 ru->ru_nivcsw += ru2->ru_nivcsw;
124 }
125
126 void
127 prusage(struct rusage *r0, struct rusage *r1, struct timeval *e,
128 struct timeval *b)
129 {
130 struct varent *vp;
131 const char *cp;
132 long i;
133 time_t t;
134 int ms;
135
136 cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww";
137 ms = (e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000;
138 t = (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
139 (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
140 (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
141 (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
142 vp = adrof(STRtime);
143
144 if (vp && vp->vec[0] && vp->vec[1])
145 cp = short2str(vp->vec[1]);
146
147 for (; *cp; cp++)
148 if (*cp != '%')
149 (void) fputc(*cp, cshout);
150 else if (cp[1])
151 switch (*++cp) {
152 case 'D': /* (average) unshared data size */
153 (void)fprintf(cshout, "%ld", t == 0 ? 0L :
154 (r1->ru_idrss + r1->ru_isrss -
155 (r0->ru_idrss + r0->ru_isrss)) / t);
156 break;
157 case 'E': /* elapsed (wall-clock) time */
158 pcsecs((long) ms);
159 break;
160 case 'F': /* page faults */
161 (void)fprintf(cshout, "%ld", r1->ru_majflt - r0->ru_majflt);
162 break;
163 case 'I': /* FS blocks in */
164 (void)fprintf(cshout, "%ld", r1->ru_inblock - r0->ru_inblock);
165 break;
166 case 'K': /* (average) total data memory used */
167 (void)fprintf(cshout, "%ld", t == 0 ? 0L :
168 ((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
169 (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
170 break;
171 case 'M': /* max. Resident Set Size */
172 (void)fprintf(cshout, "%ld", r1->ru_maxrss / 2L);
173 break;
174 case 'O': /* FS blocks out */
175 (void)fprintf(cshout, "%ld", r1->ru_oublock - r0->ru_oublock);
176 break;
177 case 'P': /* percent time spent running */
178 /* check if it did not run at all */
179 if (ms == 0) {
180 (void)fputs("0.0%", cshout);
181 } else {
182 (void)fputs(strpct((ulong)t, (ulong)ms, 1), cshout);
183 }
184 break;
185 case 'R': /* page reclaims */
186 (void)fprintf(cshout, "%ld", r1->ru_minflt - r0->ru_minflt);
187 break;
188 case 'S': /* system CPU time used */
189 pdeltat(&r1->ru_stime, &r0->ru_stime);
190 break;
191 case 'U': /* user CPU time used */
192 pdeltat(&r1->ru_utime, &r0->ru_utime);
193 break;
194 case 'W': /* number of swaps */
195 i = r1->ru_nswap - r0->ru_nswap;
196 (void)fprintf(cshout, "%ld", i);
197 break;
198 case 'X': /* (average) shared text size */
199 (void)fprintf(cshout, "%ld", t == 0 ? 0L :
200 (r1->ru_ixrss - r0->ru_ixrss) / t);
201 break;
202 case 'c': /* num. involuntary context switches */
203 (void)fprintf(cshout, "%ld", r1->ru_nivcsw - r0->ru_nivcsw);
204 break;
205 case 'k': /* number of signals received */
206 (void)fprintf(cshout, "%ld", r1->ru_nsignals-r0->ru_nsignals);
207 break;
208 case 'r': /* socket messages received */
209 (void)fprintf(cshout, "%ld", r1->ru_msgrcv - r0->ru_msgrcv);
210 break;
211 case 's': /* socket messages sent */
212 (void)fprintf(cshout, "%ld", r1->ru_msgsnd - r0->ru_msgsnd);
213 break;
214 case 'w': /* num. voluntary context switches (waits) */
215 (void)fprintf(cshout, "%ld", r1->ru_nvcsw - r0->ru_nvcsw);
216 break;
217 }
218 (void)fputc('\n', cshout);
219 }
220
221 static void
222 pdeltat(struct timeval *t1, struct timeval *t0)
223 {
224 struct timeval td;
225
226 timersub(t1, t0, &td);
227 (void)fprintf(cshout, "%ld.%01ld", (long)td.tv_sec,
228 (long)(td.tv_usec / 100000));
229 }
230
231 #define P2DIG(i) (void)fprintf(cshout, "%d%d", (i) / 10, (i) % 10)
232
233 void
234 psecs(long l)
235 {
236 int i;
237
238 i = l / 3600;
239 if (i) {
240 (void)fprintf(cshout, "%d:", i);
241 i = l % 3600;
242 P2DIG(i / 60);
243 goto minsec;
244 }
245 i = l;
246 (void)fprintf(cshout, "%d", i / 60);
247 minsec:
248 i %= 60;
249 (void)fputc(':', cshout);
250 P2DIG(i);
251 }
252
253 void
254 pcsecs(long l) /* PWP: print mm:ss.dd, l is in sec*100 */
255 {
256 int i;
257
258 i = l / 360000;
259 if (i) {
260 (void)fprintf(cshout, "%d:", i);
261 i = (l % 360000) / 100;
262 P2DIG(i / 60);
263 goto minsec;
264 }
265 i = l / 100;
266 (void)fprintf(cshout, "%d", i / 60);
267 minsec:
268 i %= 60;
269 (void)fputc(':', cshout);
270 P2DIG(i);
271 (void)fputc('.', cshout);
272 P2DIG((int) (l % 100));
273 }
274