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