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