1 |
|
|
/* $OpenBSD: time.c,v 1.15 2017/07/22 09:37:21 anton Exp $ */ |
2 |
|
|
/* $NetBSD: time.c,v 1.7 1995/03/21 13:55:25 mycroft Exp $ */ |
3 |
|
|
|
4 |
|
|
/*- |
5 |
|
|
* Copyright (c) 1980, 1991, 1993 |
6 |
|
|
* The Regents of the University of California. All rights reserved. |
7 |
|
|
* |
8 |
|
|
* Redistribution and use in source and binary forms, with or without |
9 |
|
|
* modification, are permitted provided that the following conditions |
10 |
|
|
* are met: |
11 |
|
|
* 1. Redistributions of source code must retain the above copyright |
12 |
|
|
* notice, this list of conditions and the following disclaimer. |
13 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
14 |
|
|
* notice, this list of conditions and the following disclaimer in the |
15 |
|
|
* documentation and/or other materials provided with the distribution. |
16 |
|
|
* 3. Neither the name of the University nor the names of its contributors |
17 |
|
|
* may be used to endorse or promote products derived from this software |
18 |
|
|
* without specific prior written permission. |
19 |
|
|
* |
20 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
21 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
22 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
23 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
24 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
25 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
26 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
27 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
28 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
29 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
30 |
|
|
* SUCH DAMAGE. |
31 |
|
|
*/ |
32 |
|
|
|
33 |
|
|
#include <sys/types.h> |
34 |
|
|
#include <stdarg.h> |
35 |
|
|
|
36 |
|
|
#include "csh.h" |
37 |
|
|
#include "extern.h" |
38 |
|
|
|
39 |
|
|
/* |
40 |
|
|
* C Shell - routines handling process timing and niceing |
41 |
|
|
*/ |
42 |
|
|
static void pdeltat(struct timeval *, struct timeval *); |
43 |
|
|
|
44 |
|
|
void |
45 |
|
|
settimes(void) |
46 |
|
|
{ |
47 |
|
|
struct rusage ruch; |
48 |
|
|
|
49 |
|
|
(void) clock_gettime(CLOCK_MONOTONIC, &time0); |
50 |
|
|
(void) getrusage(RUSAGE_SELF, &ru0); |
51 |
|
|
(void) getrusage(RUSAGE_CHILDREN, &ruch); |
52 |
|
|
ruadd(&ru0, &ruch); |
53 |
|
|
} |
54 |
|
|
|
55 |
|
|
/* |
56 |
|
|
* dotime is only called if it is truly a builtin function and not a |
57 |
|
|
* prefix to another command |
58 |
|
|
*/ |
59 |
|
|
void |
60 |
|
|
/*ARGSUSED*/ |
61 |
|
|
dotime(Char **v, struct command *t) |
62 |
|
|
{ |
63 |
|
|
struct timespec timedol; |
64 |
|
|
struct rusage ru1, ruch; |
65 |
|
|
|
66 |
|
|
(void) getrusage(RUSAGE_SELF, &ru1); |
67 |
|
|
(void) getrusage(RUSAGE_CHILDREN, &ruch); |
68 |
|
|
ruadd(&ru1, &ruch); |
69 |
|
|
(void) clock_gettime(CLOCK_MONOTONIC, &timedol); |
70 |
|
|
prusage(&ru0, &ru1, &timedol, &time0); |
71 |
|
|
} |
72 |
|
|
|
73 |
|
|
/* |
74 |
|
|
* donice is only called when it on the line by itself or with a +- value |
75 |
|
|
*/ |
76 |
|
|
void |
77 |
|
|
/*ARGSUSED*/ |
78 |
|
|
donice(Char **v, struct command *t) |
79 |
|
|
{ |
80 |
|
|
Char *cp; |
81 |
|
|
int nval = 0; |
82 |
|
|
|
83 |
|
|
v++, cp = *v++; |
84 |
|
|
if (cp == 0) |
85 |
|
|
nval = 4; |
86 |
|
|
else if (*v == 0 && any("+-", cp[0])) |
87 |
|
|
nval = getn(cp); |
88 |
|
|
(void) setpriority(PRIO_PROCESS, 0, nval); |
89 |
|
|
} |
90 |
|
|
|
91 |
|
|
void |
92 |
|
|
ruadd(struct rusage *ru, struct rusage *ru2) |
93 |
|
|
{ |
94 |
|
|
timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime); |
95 |
|
|
timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime); |
96 |
|
|
if (ru2->ru_maxrss > ru->ru_maxrss) |
97 |
|
|
ru->ru_maxrss = ru2->ru_maxrss; |
98 |
|
|
|
99 |
|
|
ru->ru_ixrss += ru2->ru_ixrss; |
100 |
|
|
ru->ru_idrss += ru2->ru_idrss; |
101 |
|
|
ru->ru_isrss += ru2->ru_isrss; |
102 |
|
|
ru->ru_minflt += ru2->ru_minflt; |
103 |
|
|
ru->ru_majflt += ru2->ru_majflt; |
104 |
|
|
ru->ru_nswap += ru2->ru_nswap; |
105 |
|
|
ru->ru_inblock += ru2->ru_inblock; |
106 |
|
|
ru->ru_oublock += ru2->ru_oublock; |
107 |
|
|
ru->ru_msgsnd += ru2->ru_msgsnd; |
108 |
|
|
ru->ru_msgrcv += ru2->ru_msgrcv; |
109 |
|
|
ru->ru_nsignals += ru2->ru_nsignals; |
110 |
|
|
ru->ru_nvcsw += ru2->ru_nvcsw; |
111 |
|
|
ru->ru_nivcsw += ru2->ru_nivcsw; |
112 |
|
|
} |
113 |
|
|
|
114 |
|
|
void |
115 |
|
|
prusage(struct rusage *r0, struct rusage *r1, struct timespec *e, |
116 |
|
|
struct timespec *b) |
117 |
|
|
{ |
118 |
|
|
time_t t = |
119 |
|
|
(r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 + |
120 |
|
|
(r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 + |
121 |
|
|
(r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 + |
122 |
|
|
(r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000; |
123 |
|
|
char *cp; |
124 |
|
|
long i; |
125 |
|
|
struct varent *vp = adrof(STRtime); |
126 |
|
|
|
127 |
|
|
int ms = |
128 |
|
|
(e->tv_sec - b->tv_sec) * 100 + (e->tv_nsec - b->tv_nsec) / 10000000; |
129 |
|
|
|
130 |
|
|
cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww"; |
131 |
|
|
|
132 |
|
|
if (vp && vp->vec[0] && vp->vec[1]) |
133 |
|
|
cp = short2str(vp->vec[1]); |
134 |
|
|
|
135 |
|
|
for (; *cp; cp++) |
136 |
|
|
if (*cp != '%') |
137 |
|
|
(void) fputc(*cp, cshout); |
138 |
|
|
else if (cp[1]) |
139 |
|
|
switch (*++cp) { |
140 |
|
|
|
141 |
|
|
case 'U': /* user CPU time used */ |
142 |
|
|
pdeltat(&r1->ru_utime, &r0->ru_utime); |
143 |
|
|
break; |
144 |
|
|
|
145 |
|
|
case 'S': /* system CPU time used */ |
146 |
|
|
pdeltat(&r1->ru_stime, &r0->ru_stime); |
147 |
|
|
break; |
148 |
|
|
|
149 |
|
|
case 'E': /* elapsed (wall-clock) time */ |
150 |
|
|
pcsecs((long) ms); |
151 |
|
|
break; |
152 |
|
|
|
153 |
|
|
case 'P': /* percent time spent running */ |
154 |
|
|
/* check if it did not run at all */ |
155 |
|
|
i = (ms == 0) ? 0 : ((long long)t * 1000 / ms); |
156 |
|
|
/* nn.n% */ |
157 |
|
|
(void) fprintf(cshout, "%ld.%01ld%%", i / 10, i % 10); |
158 |
|
|
break; |
159 |
|
|
|
160 |
|
|
case 'W': /* number of swaps */ |
161 |
|
|
i = r1->ru_nswap - r0->ru_nswap; |
162 |
|
|
(void) fprintf(cshout, "%ld", i); |
163 |
|
|
break; |
164 |
|
|
|
165 |
|
|
case 'X': /* (average) shared text size */ |
166 |
|
|
(void) fprintf(cshout, "%ld", t == 0 ? 0L : |
167 |
|
|
(long)((r1->ru_ixrss - r0->ru_ixrss) / t)); |
168 |
|
|
break; |
169 |
|
|
|
170 |
|
|
case 'D': /* (average) unshared data size */ |
171 |
|
|
(void) fprintf(cshout, "%ld", t == 0 ? 0L : |
172 |
|
|
(long)((r1->ru_idrss + r1->ru_isrss - |
173 |
|
|
(r0->ru_idrss + r0->ru_isrss)) / t)); |
174 |
|
|
break; |
175 |
|
|
|
176 |
|
|
case 'K': /* (average) total data memory used */ |
177 |
|
|
(void) fprintf(cshout, "%ld", t == 0 ? 0L : |
178 |
|
|
(long)(((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) |
179 |
|
|
- (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) |
180 |
|
|
/ t)); |
181 |
|
|
break; |
182 |
|
|
|
183 |
|
|
case 'M': /* max. Resident Set Size */ |
184 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_maxrss / 2L); |
185 |
|
|
break; |
186 |
|
|
|
187 |
|
|
case 'F': /* page faults */ |
188 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_majflt - r0->ru_majflt); |
189 |
|
|
break; |
190 |
|
|
|
191 |
|
|
case 'R': /* page reclaims */ |
192 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_minflt - r0->ru_minflt); |
193 |
|
|
break; |
194 |
|
|
|
195 |
|
|
case 'I': /* FS blocks in */ |
196 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_inblock - r0->ru_inblock); |
197 |
|
|
break; |
198 |
|
|
|
199 |
|
|
case 'O': /* FS blocks out */ |
200 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_oublock - r0->ru_oublock); |
201 |
|
|
break; |
202 |
|
|
|
203 |
|
|
case 'r': /* socket messages received */ |
204 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_msgrcv - r0->ru_msgrcv); |
205 |
|
|
break; |
206 |
|
|
|
207 |
|
|
case 's': /* socket messages sent */ |
208 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_msgsnd - r0->ru_msgsnd); |
209 |
|
|
break; |
210 |
|
|
|
211 |
|
|
case 'k': /* number of signals received */ |
212 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_nsignals-r0->ru_nsignals); |
213 |
|
|
break; |
214 |
|
|
|
215 |
|
|
case 'w': /* num. voluntary context switches (waits) */ |
216 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_nvcsw - r0->ru_nvcsw); |
217 |
|
|
break; |
218 |
|
|
|
219 |
|
|
case 'c': /* num. involuntary context switches */ |
220 |
|
|
(void) fprintf(cshout, "%ld", r1->ru_nivcsw - r0->ru_nivcsw); |
221 |
|
|
break; |
222 |
|
|
} |
223 |
|
|
(void) fputc('\n', cshout); |
224 |
|
|
} |
225 |
|
|
|
226 |
|
|
static void |
227 |
|
|
pdeltat(struct timeval *t1, struct timeval *t0) |
228 |
|
|
{ |
229 |
|
|
struct timeval td; |
230 |
|
|
|
231 |
|
|
timersub(t1, t0, &td); |
232 |
|
|
(void) fprintf(cshout, "%lld.%01ld", (long long)td.tv_sec, |
233 |
|
|
td.tv_usec / 100000); |
234 |
|
|
} |
235 |
|
|
|
236 |
|
|
#define P2DIG(i) (void) fprintf(cshout, "%d%d", (i) / 10, (i) % 10) |
237 |
|
|
|
238 |
|
|
void |
239 |
|
|
psecs(long l) |
240 |
|
|
{ |
241 |
|
|
int i; |
242 |
|
|
|
243 |
|
|
i = l / 3600; |
244 |
|
|
if (i) { |
245 |
|
|
(void) fprintf(cshout, "%d:", i); |
246 |
|
|
i = l % 3600; |
247 |
|
|
P2DIG(i / 60); |
248 |
|
|
goto minsec; |
249 |
|
|
} |
250 |
|
|
i = l; |
251 |
|
|
(void) fprintf(cshout, "%d", i / 60); |
252 |
|
|
minsec: |
253 |
|
|
i %= 60; |
254 |
|
|
(void) fputc(':', cshout); |
255 |
|
|
P2DIG(i); |
256 |
|
|
} |
257 |
|
|
|
258 |
|
|
void |
259 |
|
|
pcsecs(long l) /* PWP: print mm:ss.dd, l is in sec*100 */ |
260 |
|
|
{ |
261 |
|
|
int i; |
262 |
|
|
|
263 |
|
|
i = l / 360000; |
264 |
|
|
if (i) { |
265 |
|
|
(void) fprintf(cshout, "%d:", i); |
266 |
|
|
i = (l % 360000) / 100; |
267 |
|
|
P2DIG(i / 60); |
268 |
|
|
goto minsec; |
269 |
|
|
} |
270 |
|
|
i = l / 100; |
271 |
|
|
(void) fprintf(cshout, "%d", i / 60); |
272 |
|
|
minsec: |
273 |
|
|
i %= 60; |
274 |
|
|
(void) fputc(':', cshout); |
275 |
|
|
P2DIG(i); |
276 |
|
|
(void) fputc('.', cshout); |
277 |
|
|
P2DIG((int) (l % 100)); |
278 |
|
|
} |