]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - bin/csh/time.c
This commit was generated by cvs2svn to compensate for changes in r50894,
[FreeBSD/FreeBSD.git] / bin / csh / time.c
1 /*-
2  * Copyright (c) 1980, 1991, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. 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
34 #ifndef lint
35 #if 0
36 static char sccsid[] = "@(#)time.c      8.1 (Berkeley) 5/31/93";
37 #else
38 static const char rcsid[] =
39   "$FreeBSD$";
40 #endif
41 #endif /* not lint */
42
43 #include <sys/types.h>
44 #if __STDC__
45 # include <stdarg.h>
46 #else
47 # include <varargs.h>
48 #endif
49
50 #include "csh.h"
51 #include "extern.h"
52
53 /*
54  * C Shell - routines handling process timing and niceing
55  */
56 static void     pdeltat __P((struct timeval *, struct timeval *));
57
58 void
59 settimes()
60 {
61     struct rusage ruch;
62
63     (void) gettimeofday(&time0, NULL);
64     (void) getrusage(RUSAGE_SELF, &ru0);
65     (void) getrusage(RUSAGE_CHILDREN, &ruch);
66     ruadd(&ru0, &ruch);
67 }
68
69 /*
70  * dotime is only called if it is truly a builtin function and not a
71  * prefix to another command
72  */
73 void
74 /*ARGSUSED*/
75 dotime(v, t)
76     Char **v;
77     struct command *t;
78 {
79     struct timeval timedol;
80     struct rusage ru1, ruch;
81
82     (void) getrusage(RUSAGE_SELF, &ru1);
83     (void) getrusage(RUSAGE_CHILDREN, &ruch);
84     ruadd(&ru1, &ruch);
85     (void) gettimeofday(&timedol, NULL);
86     prusage(&ru0, &ru1, &timedol, &time0);
87 }
88
89 /*
90  * donice is only called when it on the line by itself or with a +- value
91  */
92 void
93 /*ARGSUSED*/
94 donice(v, t)
95     Char **v;
96     struct command *t;
97 {
98     Char *cp;
99     int     nval = 0;
100
101     v++, cp = *v++;
102     if (cp == 0)
103         nval = 4;
104     else if (*v == 0 && any("+-", cp[0]))
105         nval = getn(cp);
106     (void) setpriority(PRIO_PROCESS, 0, nval);
107 }
108
109 void
110 ruadd(ru, ru2)
111     struct rusage *ru, *ru2;
112 {
113     tvadd(&ru->ru_utime, &ru2->ru_utime);
114     tvadd(&ru->ru_stime, &ru2->ru_stime);
115     if (ru2->ru_maxrss > ru->ru_maxrss)
116         ru->ru_maxrss = ru2->ru_maxrss;
117
118     ru->ru_ixrss += ru2->ru_ixrss;
119     ru->ru_idrss += ru2->ru_idrss;
120     ru->ru_isrss += ru2->ru_isrss;
121     ru->ru_minflt += ru2->ru_minflt;
122     ru->ru_majflt += ru2->ru_majflt;
123     ru->ru_nswap += ru2->ru_nswap;
124     ru->ru_inblock += ru2->ru_inblock;
125     ru->ru_oublock += ru2->ru_oublock;
126     ru->ru_msgsnd += ru2->ru_msgsnd;
127     ru->ru_msgrcv += ru2->ru_msgrcv;
128     ru->ru_nsignals += ru2->ru_nsignals;
129     ru->ru_nvcsw += ru2->ru_nvcsw;
130     ru->ru_nivcsw += ru2->ru_nivcsw;
131 }
132
133 void
134 prusage(r0, r1, e, b)
135     struct rusage *r0, *r1;
136     struct timeval *e, *b;
137 {
138     time_t t =
139     (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
140     (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
141     (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
142     (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
143     char *cp;
144     long i;
145     struct varent *vp = adrof(STRtime);
146
147     int     ms =
148     (e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000;
149
150     cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww";
151
152     if (vp && vp->vec[0] && vp->vec[1])
153         cp = short2str(vp->vec[1]);
154
155     for (; *cp; cp++)
156         if (*cp != '%')
157             (void) fputc(*cp, cshout);
158         else if (cp[1])
159             switch (*++cp) {
160
161             case 'U':           /* user CPU time used */
162                 pdeltat(&r1->ru_utime, &r0->ru_utime);
163                 break;
164
165             case 'S':           /* system CPU time used */
166                 pdeltat(&r1->ru_stime, &r0->ru_stime);
167                 break;
168
169             case 'E':           /* elapsed (wall-clock) time */
170                 pcsecs((long) ms);
171                 break;
172
173             case 'P':           /* percent time spent running */
174                 /* check if it did not run at all */
175                 i = (ms == 0) ? 0 : (t * 1000 / ms);
176                 /* nn.n% */
177                 (void) fprintf(cshout, "%ld.%01ld%%", i / 10, i % 10);
178                 break;
179
180             case 'W':           /* number of swaps */
181                 i = r1->ru_nswap - r0->ru_nswap;
182                 (void) fprintf(cshout, "%ld", i);
183                 break;
184
185             case 'X':           /* (average) shared text size */
186                 (void) fprintf(cshout, "%ld", t == 0 ? 0L :
187                                (r1->ru_ixrss - r0->ru_ixrss) / t);
188                 break;
189
190             case 'D':           /* (average) unshared data size */
191                 (void) fprintf(cshout, "%ld", t == 0 ? 0L :
192                         (r1->ru_idrss + r1->ru_isrss -
193                          (r0->ru_idrss + r0->ru_isrss)) / t);
194                 break;
195
196             case 'K':           /* (average) total data memory used  */
197                 (void) fprintf(cshout, "%ld", t == 0 ? 0L :
198                         ((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
199                          (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
200                 break;
201
202             case 'M':           /* max. Resident Set Size */
203                 (void) fprintf(cshout, "%ld", r1->ru_maxrss / 2L);
204                 break;
205
206             case 'F':           /* page faults */
207                 (void) fprintf(cshout, "%ld", r1->ru_majflt - r0->ru_majflt);
208                 break;
209
210             case 'R':           /* page reclaims */
211                 (void) fprintf(cshout, "%ld", r1->ru_minflt - r0->ru_minflt);
212                 break;
213
214             case 'I':           /* FS blocks in */
215                 (void) fprintf(cshout, "%ld", r1->ru_inblock - r0->ru_inblock);
216                 break;
217
218             case 'O':           /* FS blocks out */
219                 (void) fprintf(cshout, "%ld", r1->ru_oublock - r0->ru_oublock);
220                 break;
221
222             case 'r':           /* socket messages received */
223                 (void) fprintf(cshout, "%ld", r1->ru_msgrcv - r0->ru_msgrcv);
224                 break;
225
226             case 's':           /* socket messages sent */
227                 (void) fprintf(cshout, "%ld", r1->ru_msgsnd - r0->ru_msgsnd);
228                 break;
229
230             case 'k':           /* number of signals received */
231                 (void) fprintf(cshout, "%ld", r1->ru_nsignals-r0->ru_nsignals);
232                 break;
233
234             case 'w':           /* num. voluntary context switches (waits) */
235                 (void) fprintf(cshout, "%ld", r1->ru_nvcsw - r0->ru_nvcsw);
236                 break;
237
238             case 'c':           /* num. involuntary context switches */
239                 (void) fprintf(cshout, "%ld", r1->ru_nivcsw - r0->ru_nivcsw);
240                 break;
241             }
242     (void) fputc('\n', cshout);
243 }
244
245 static void
246 pdeltat(t1, t0)
247     struct timeval *t1, *t0;
248 {
249     struct timeval td;
250
251     tvsub(&td, t1, t0);
252     (void) fprintf(cshout, "%ld.%01ld", td.tv_sec, td.tv_usec / 100000L);
253 }
254
255 void
256 tvadd(tsum, t0)
257     struct timeval *tsum, *t0;
258 {
259
260     tsum->tv_sec += t0->tv_sec;
261     tsum->tv_usec += t0->tv_usec;
262     if (tsum->tv_usec >= 1000000)
263         tsum->tv_sec++, tsum->tv_usec -= 1000000;
264 }
265
266 void
267 tvsub(tdiff, t1, t0)
268     struct timeval *tdiff, *t1, *t0;
269 {
270
271     tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
272     tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
273     if (tdiff->tv_usec < 0)
274         tdiff->tv_sec--, tdiff->tv_usec += 1000000;
275 }
276
277 #define  P2DIG(i) (void) fprintf(cshout, "%d%d", (i) / 10, (i) % 10)
278
279 void
280 psecs(l)
281     long    l;
282 {
283     int i;
284
285     i = l / 3600;
286     if (i) {
287         (void) fprintf(cshout, "%d:", i);
288         i = l % 3600;
289         P2DIG(i / 60);
290         goto minsec;
291     }
292     i = l;
293     (void) fprintf(cshout, "%d", i / 60);
294 minsec:
295     i %= 60;
296     (void) fputc(':', cshout);
297     P2DIG(i);
298 }
299
300 void
301 pcsecs(l)                       /* PWP: print mm:ss.dd, l is in sec*100 */
302     long    l;
303 {
304     int i;
305
306     i = l / 360000;
307     if (i) {
308         (void) fprintf(cshout, "%d:", i);
309         i = (l % 360000) / 100;
310         P2DIG(i / 60);
311         goto minsec;
312     }
313     i = l / 100;
314     (void) fprintf(cshout, "%d", i / 60);
315 minsec:
316     i %= 60;
317     (void) fputc(':', cshout);
318     P2DIG(i);
319     (void) fputc('.', cshout);
320     P2DIG((int) (l % 100));
321 }