Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /*- |
2 | * Copyright (c) 1980, 1991 The Regents of the University of California. | |
3 | * 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 | static char sccsid[] = "@(#)time.c 5.14 (Berkeley) 6/8/91"; | |
36 | #endif /* not lint */ | |
37 | ||
38 | #include <sys/types.h> | |
39 | #if __STDC__ | |
40 | # include <stdarg.h> | |
41 | #else | |
42 | # include <varargs.h> | |
43 | #endif | |
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 __P((struct timeval *, struct timeval *)); | |
52 | ||
53 | void | |
54 | settimes() | |
55 | { | |
56 | struct rusage ruch; | |
57 | ||
58 | (void) gettimeofday(&time0, NULL); | |
59 | (void) getrusage(RUSAGE_SELF, &ru0); | |
60 | (void) getrusage(RUSAGE_CHILDREN, &ruch); | |
61 | ruadd(&ru0, &ruch); | |
62 | } | |
63 | ||
64 | /* | |
65 | * dotime is only called if it is truly a builtin function and not a | |
66 | * prefix to another command | |
67 | */ | |
68 | void | |
69 | dotime() | |
70 | { | |
71 | struct timeval timedol; | |
72 | struct rusage ru1, ruch; | |
73 | ||
74 | (void) getrusage(RUSAGE_SELF, &ru1); | |
75 | (void) getrusage(RUSAGE_CHILDREN, &ruch); | |
76 | ruadd(&ru1, &ruch); | |
77 | (void) gettimeofday(&timedol, NULL); | |
78 | prusage(&ru0, &ru1, &timedol, &time0); | |
79 | } | |
80 | ||
81 | /* | |
82 | * donice is only called when it on the line by itself or with a +- value | |
83 | */ | |
84 | void | |
85 | donice(v) | |
86 | register Char **v; | |
87 | { | |
88 | register Char *cp; | |
89 | int nval = 0; | |
90 | ||
91 | v++, cp = *v++; | |
92 | if (cp == 0) | |
93 | nval = 4; | |
94 | else if (*v == 0 && any("+-", cp[0])) | |
95 | nval = getn(cp); | |
96 | (void) setpriority(PRIO_PROCESS, 0, nval); | |
97 | } | |
98 | ||
99 | void | |
100 | ruadd(ru, ru2) | |
101 | register struct rusage *ru, *ru2; | |
102 | { | |
103 | tvadd(&ru->ru_utime, &ru2->ru_utime); | |
104 | tvadd(&ru->ru_stime, &ru2->ru_stime); | |
105 | if (ru2->ru_maxrss > ru->ru_maxrss) | |
106 | ru->ru_maxrss = ru2->ru_maxrss; | |
107 | ||
108 | ru->ru_ixrss += ru2->ru_ixrss; | |
109 | ru->ru_idrss += ru2->ru_idrss; | |
110 | ru->ru_isrss += ru2->ru_isrss; | |
111 | ru->ru_minflt += ru2->ru_minflt; | |
112 | ru->ru_majflt += ru2->ru_majflt; | |
113 | ru->ru_nswap += ru2->ru_nswap; | |
114 | ru->ru_inblock += ru2->ru_inblock; | |
115 | ru->ru_oublock += ru2->ru_oublock; | |
116 | ru->ru_msgsnd += ru2->ru_msgsnd; | |
117 | ru->ru_msgrcv += ru2->ru_msgrcv; | |
118 | ru->ru_nsignals += ru2->ru_nsignals; | |
119 | ru->ru_nvcsw += ru2->ru_nvcsw; | |
120 | ru->ru_nivcsw += ru2->ru_nivcsw; | |
121 | } | |
122 | ||
123 | void | |
124 | prusage(r0, r1, e, b) | |
125 | register struct rusage *r0, *r1; | |
126 | struct timeval *e, *b; | |
127 | { | |
128 | register time_t t = | |
129 | (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 + | |
130 | (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 + | |
131 | (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 + | |
132 | (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000; | |
133 | register char *cp; | |
134 | register long i; | |
135 | register struct varent *vp = adrof(STRtime); | |
136 | ||
137 | int ms = | |
138 | (e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000; | |
139 | ||
140 | cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww"; | |
141 | ||
142 | if (vp && vp->vec[0] && vp->vec[1]) | |
143 | cp = short2str(vp->vec[1]); | |
144 | ||
145 | for (; *cp; cp++) | |
146 | if (*cp != '%') | |
147 | xputchar(*cp); | |
148 | else if (cp[1]) | |
149 | switch (*++cp) { | |
150 | ||
151 | case 'U': /* user CPU time used */ | |
152 | pdeltat(&r1->ru_utime, &r0->ru_utime); | |
153 | break; | |
154 | ||
155 | case 'S': /* system CPU time used */ | |
156 | pdeltat(&r1->ru_stime, &r0->ru_stime); | |
157 | break; | |
158 | ||
159 | case 'E': /* elapsed (wall-clock) time */ | |
160 | pcsecs((long) ms); | |
161 | break; | |
162 | ||
163 | case 'P': /* percent time spent running */ | |
164 | /* check if it did not run at all */ | |
165 | i = (ms == 0) ? 0 : (t * 1000 / ms); | |
166 | xprintf("%ld.%01ld%%", i / 10, i % 10); /* nn.n% */ | |
167 | break; | |
168 | ||
169 | case 'W': /* number of swaps */ | |
170 | i = r1->ru_nswap - r0->ru_nswap; | |
171 | xprintf("%ld", i); | |
172 | break; | |
173 | ||
174 | case 'X': /* (average) shared text size */ | |
175 | xprintf("%ld", t == 0 ? 0L : (r1->ru_ixrss - r0->ru_ixrss) / t); | |
176 | break; | |
177 | ||
178 | case 'D': /* (average) unshared data size */ | |
179 | xprintf("%ld", t == 0 ? 0L : | |
180 | (r1->ru_idrss + r1->ru_isrss - | |
181 | (r0->ru_idrss + r0->ru_isrss)) / t); | |
182 | break; | |
183 | ||
184 | case 'K': /* (average) total data memory used */ | |
185 | xprintf("%ld", t == 0 ? 0L : | |
186 | ((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) - | |
187 | (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t); | |
188 | break; | |
189 | ||
190 | case 'M': /* max. Resident Set Size */ | |
191 | xprintf("%ld", r1->ru_maxrss / 2L); | |
192 | break; | |
193 | ||
194 | case 'F': /* page faults */ | |
195 | xprintf("%ld", r1->ru_majflt - r0->ru_majflt); | |
196 | break; | |
197 | ||
198 | case 'R': /* page reclaims */ | |
199 | xprintf("%ld", r1->ru_minflt - r0->ru_minflt); | |
200 | break; | |
201 | ||
202 | case 'I': /* FS blocks in */ | |
203 | xprintf("%ld", r1->ru_inblock - r0->ru_inblock); | |
204 | break; | |
205 | ||
206 | case 'O': /* FS blocks out */ | |
207 | xprintf("%ld", r1->ru_oublock - r0->ru_oublock); | |
208 | break; | |
209 | ||
210 | case 'r': /* socket messages recieved */ | |
211 | xprintf("%ld", r1->ru_msgrcv - r0->ru_msgrcv); | |
212 | break; | |
213 | ||
214 | case 's': /* socket messages sent */ | |
215 | xprintf("%ld", r1->ru_msgsnd - r0->ru_msgsnd); | |
216 | break; | |
217 | ||
218 | case 'k': /* number of signals recieved */ | |
219 | xprintf("%ld", r1->ru_nsignals - r0->ru_nsignals); | |
220 | break; | |
221 | ||
222 | case 'w': /* num. voluntary context switches (waits) */ | |
223 | xprintf("%ld", r1->ru_nvcsw - r0->ru_nvcsw); | |
224 | break; | |
225 | ||
226 | case 'c': /* num. involuntary context switches */ | |
227 | xprintf("%ld", r1->ru_nivcsw - r0->ru_nivcsw); | |
228 | break; | |
229 | } | |
230 | xputchar('\n'); | |
231 | } | |
232 | ||
233 | static void | |
234 | pdeltat(t1, t0) | |
235 | struct timeval *t1, *t0; | |
236 | { | |
237 | struct timeval td; | |
238 | ||
239 | tvsub(&td, t1, t0); | |
240 | xprintf("%d.%01d", td.tv_sec, td.tv_usec / 100000); | |
241 | } | |
242 | ||
243 | void | |
244 | tvadd(tsum, t0) | |
245 | struct timeval *tsum, *t0; | |
246 | { | |
247 | ||
248 | tsum->tv_sec += t0->tv_sec; | |
249 | tsum->tv_usec += t0->tv_usec; | |
250 | if (tsum->tv_usec > 1000000) | |
251 | tsum->tv_sec++, tsum->tv_usec -= 1000000; | |
252 | } | |
253 | ||
254 | void | |
255 | tvsub(tdiff, t1, t0) | |
256 | struct timeval *tdiff, *t1, *t0; | |
257 | { | |
258 | ||
259 | tdiff->tv_sec = t1->tv_sec - t0->tv_sec; | |
260 | tdiff->tv_usec = t1->tv_usec - t0->tv_usec; | |
261 | if (tdiff->tv_usec < 0) | |
262 | tdiff->tv_sec--, tdiff->tv_usec += 1000000; | |
263 | } |