VirtualBox

source: kBuild/trunk/src/misc/kmk_time.c@ 1885

Last change on this file since 1885 was 1884, checked in by bird, 16 years ago

kmk_time: windows fix, bettern alignment.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.2 KB
Line 
1/* $Id: kmk_time.c 1884 2008-10-19 20:40:02Z bird $ */
2/** @file
3 * kmk_time - Time program execution.
4 *
5 * This is based on kmk/kmkbuiltin/redirect.c.
6 */
7
8/*
9 * Copyright (c) 2007-2008 knut st. osmundsen <[email protected]>
10 *
11 * This file is part of kBuild.
12 *
13 * kBuild is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * kBuild is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with kBuild; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 *
27 */
28
29
30/*******************************************************************************
31* Header Files *
32*******************************************************************************/
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37#include <fcntl.h>
38#include <time.h>
39#if defined(_MSC_VER)
40# include <io.h>
41# include <direct.h>
42# include <process.h>
43# include <Windows.h>
44#else
45# include <unistd.h>
46# include <sys/times.h>
47# include <signal.h>
48#endif
49
50#ifdef __OS2__
51# define INCL_BASE
52# include <os2.h>
53# ifndef LIBPATHSTRICT
54# define LIBPATHSTRICT 3
55# endif
56#endif
57
58#ifndef _MSC_VER
59static const char *my_strsignal(int signo)
60{
61#define CASE_SIG_RET_STR(sig) if (signo == SIG##sig) return #sig
62#ifdef SIGHUP
63 CASE_SIG_RET_STR(HUP);
64#endif
65#ifdef SIGINT
66 CASE_SIG_RET_STR(INT);
67#endif
68#ifdef SIGQUIT
69 CASE_SIG_RET_STR(QUIT);
70#endif
71#ifdef SIGILL
72 CASE_SIG_RET_STR(ILL);
73#endif
74#ifdef SIGTRAP
75 CASE_SIG_RET_STR(TRAP);
76#endif
77#ifdef SIGABRT
78 CASE_SIG_RET_STR(ABRT);
79#endif
80#ifdef SIGIOT
81 CASE_SIG_RET_STR(IOT);
82#endif
83#ifdef SIGBUS
84 CASE_SIG_RET_STR(BUS);
85#endif
86#ifdef SIGFPE
87 CASE_SIG_RET_STR(FPE);
88#endif
89#ifdef SIGKILL
90 CASE_SIG_RET_STR(KILL);
91#endif
92#ifdef SIGUSR1
93 CASE_SIG_RET_STR(USR1);
94#endif
95#ifdef SIGSEGV
96 CASE_SIG_RET_STR(SEGV);
97#endif
98#ifdef SIGUSR2
99 CASE_SIG_RET_STR(USR2);
100#endif
101#ifdef SIGPIPE
102 CASE_SIG_RET_STR(PIPE);
103#endif
104#ifdef SIGALRM
105 CASE_SIG_RET_STR(ALRM);
106#endif
107#ifdef SIGTERM
108 CASE_SIG_RET_STR(TERM);
109#endif
110#ifdef SIGSTKFLT
111 CASE_SIG_RET_STR(STKFLT);
112#endif
113#ifdef SIGCHLD
114 CASE_SIG_RET_STR(CHLD);
115#endif
116#ifdef SIGCONT
117 CASE_SIG_RET_STR(CONT);
118#endif
119#ifdef SIGSTOP
120 CASE_SIG_RET_STR(STOP);
121#endif
122#ifdef SIGTSTP
123 CASE_SIG_RET_STR(TSTP);
124#endif
125#ifdef SIGTTIN
126 CASE_SIG_RET_STR(TTIN);
127#endif
128#ifdef SIGTTOU
129 CASE_SIG_RET_STR(TTOU);
130#endif
131#ifdef SIGURG
132 CASE_SIG_RET_STR(URG);
133#endif
134#ifdef SIGXCPU
135 CASE_SIG_RET_STR(XCPU);
136#endif
137#ifdef SIGXFSZ
138 CASE_SIG_RET_STR(XFSZ);
139#endif
140#ifdef SIGVTALRM
141 CASE_SIG_RET_STR(VTALRM);
142#endif
143#ifdef SIGPROF
144 CASE_SIG_RET_STR(PROF);
145#endif
146#ifdef SIGWINCH
147 CASE_SIG_RET_STR(WINCH);
148#endif
149#ifdef SIGIO
150 CASE_SIG_RET_STR(IO);
151#endif
152#ifdef SIGPWR
153 CASE_SIG_RET_STR(PWR);
154#endif
155#ifdef SIGSYS
156 CASE_SIG_RET_STR(SYS);
157#endif
158#ifdef SIGBREAK
159 CASE_SIG_RET_STR(BREAK);
160#endif
161#undef CASE_SIG_RET_STR
162 return "???";
163}
164#endif /* unix */
165
166static const char *name(const char *pszName)
167{
168 const char *psz = strrchr(pszName, '/');
169#if defined(_MSC_VER) || defined(__OS2__)
170 const char *psz2 = strrchr(pszName, '\\');
171 if (!psz2)
172 psz2 = strrchr(pszName, ':');
173 if (psz2 && (!psz || psz2 > psz))
174 psz = psz2;
175#endif
176 return psz ? psz + 1 : pszName;
177}
178
179
180static int usage(FILE *pOut, const char *argv0)
181{
182 fprintf(pOut,
183 "usage: %s <program> [args]\n"
184 " or: %s --help\n"
185 " or: %s --version\n"
186 ,
187 argv0, argv0, argv0);
188 return 1;
189}
190
191
192int main(int argc, char **argv)
193{
194 int i, j;
195 int cTimes = 3;
196#if defined(_MSC_VER)
197 FILETIME ftStart, ft;
198 unsigned _int64 usMin, usMax, usAvg, usTotal, usCur;
199 unsigned _int64 iStart;
200 intptr_t rc;
201#else
202 struct timeval tvStart, tv;
203 unsigned long long usMin, usMax, usAvg, usTotal, usCur;
204 pid_t pid;
205 int rc;
206#endif
207
208 /*
209 * Parse arguments.
210 */
211 if (argc <= 1)
212 return usage(stderr, name(argv[0]));
213 for (i = 1; i < argc; i++)
214 {
215 char *psz = &argv[i][0];
216 if (*psz++ != '-')
217 break;
218
219 if (*psz == '-')
220 {
221 /* '--' ? */
222 if (!psz[1])
223 {
224 i++;
225 break;
226 }
227
228 /* convert to short. */
229 if (!strcmp(psz, "-help"))
230 psz = "h";
231 else if (!strcmp(psz, "-version"))
232 psz = "V";
233 else if (!strcmp(psz, "-iterations"))
234 psz = "i";
235 }
236
237 switch (*psz)
238 {
239 case 'h':
240 usage(stdout, name(argv[0]));
241 return 0;
242
243 case 'V':
244 printf("kmk_time - kBuild version %d.%d.%d (r%u)\n"
245 "Copyright (C) 2007-2008 Knut St. Osmundsen\n",
246 KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH,
247 KBUILD_SVN_REV);
248 return 0;
249
250 case 'i':
251 if (i + 1 >= argc)
252 {
253 fprintf(stderr, "%s: syntax error: missing iteration count\n", name(argv[0]));
254 return 1;
255 }
256 cTimes = atoi(argv[++i]);
257 if (cTimes <= 0)
258 {
259 fprintf(stderr, "%s: error: invalid interation count '%s'.\n", name(argv[0]), argv[i]);
260 return 1;
261 }
262 break;
263
264 default:
265 fprintf(stderr, "%s: error: syntax error '%s'\n", name(argv[0]), argv[i]);
266 return 1;
267 }
268 }
269
270 /*
271 * Make sure there's something to execute.
272 */
273 if (i >= argc)
274 {
275 fprintf(stderr, "%s: syntax error: nothing to execute!\n", name(argv[0]));
276 return usage(stderr, name(argv[0]));
277 }
278
279 /*
280 * Execute the program the specified number of times.
281 */
282 usMax = usMin = usTotal = 0;
283 usMin--; /* wraps to max value */
284 for (j = 0; j < cTimes; j++)
285 {
286 /*
287 * Execute the program (it's actually supposed to be a command I think, but wtf).
288 */
289
290#if defined(_MSC_VER)
291 /** @todo
292 * We'll have to find the '--' in the commandline and pass that
293 * on to CreateProcess or spawn. Otherwise, the argument qouting
294 * is gonna be messed up.
295 */
296 GetSystemTimeAsFileTime(&ftStart);
297 rc = _spawnvp(_P_WAIT, argv[i], &argv[i]);
298 if (rc == -1)
299 {
300 fprintf(stderr, "%s: error: _spawnvp(_P_WAIT, \"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno));
301 return 8;
302 }
303
304 GetSystemTimeAsFileTime(&ft);
305
306 iStart = ftStart.dwLowDateTime | ((unsigned _int64)ftStart.dwHighDateTime << 32);
307 usCur = ft.dwLowDateTime | ((unsigned _int64)ft.dwHighDateTime << 32);
308 usCur -= iStart;
309 usCur /= 10; /* to usecs */
310
311 printf("%s: ", name(argv[0]));
312 if (cTimes != 1)
313 printf("#%02u ", j + 1);
314 printf("%um%u.%06us - exit code: %d\n",
315 (unsigned)(usCur / (60 * 1000000)),
316 (unsigned)(usCur % (60 * 1000000)) / 1000000,
317 (unsigned)(usCur % 1000000),
318 rc);
319
320#else /* unix: */
321 rc = 1;
322 gettimeofday(&tvStart, NULL);
323 pid = fork();
324 if (!pid)
325 {
326 /* child */
327 execvp(argv[i], &argv[i]);
328 fprintf(stderr, "%s: error: _execvp(\"%s\", ...) failed: %s\n", name(argv[0]), argv[i], strerror(errno));
329 return 8;
330 }
331 if (pid < 0)
332 {
333 fprintf(stderr, "%s: error: fork() failed: %s\n", name(argv[0]), strerror(errno));
334 return 8;
335 }
336
337 /* parent, wait for child. */
338 rc = 9;
339 while (waitpid(pid, &rc, 0) == -1 && errno == EINTR)
340 /* nothing */;
341 gettimeofday(&tv, NULL);
342
343 /* calc elapsed time */
344 tv.tv_sec -= tvStart.tv_sec;
345 if (tv.tv_usec > tvStart.tv_usec)
346 tv.tv_usec -= tvStart.tv_usec;
347 else
348 {
349 tv.tv_sec--;
350 tv.tv_usec = tv.tv_usec + 1000000 - tvStart.tv_usec;
351 }
352 usCur = tv.tv_sec * 1000000ULL
353 + tv.tv_usec;
354
355 printf("%s: ", name(argv[0]));
356 if (cTimes != 1)
357 printf("#%02u ", j + 1);
358 printf("%um%u.%06us",
359 (unsigned)(tv.tv_sec / 60),
360 (unsigned)(tv.tv_sec % 60),
361 (unsigned)tv.tv_usec);
362 if (WIFEXITED(rc))
363 printf(" - normal exit: %d\n", WEXITSTATUS(rc));
364 else if (WIFSIGNALED(rc) && WCOREDUMP(rc))
365 printf(" - dumped core: %s (%d)\n", my_strsignal(WTERMSIG(rc)), WTERMSIG(rc));
366 else if (WIFSIGNALED(rc))
367 printf(" - killed by: %s (%d)\n", my_strsignal(WTERMSIG(rc)), WTERMSIG(rc));
368 else if (WIFSTOPPED(rc))
369 printf(" - stopped by: %s (%d)\n", my_strsignal(WSTOPSIG(rc)), WSTOPSIG(rc));
370 else
371 printf(" unknown exit status %#x (%d)\n", rc, rc);
372#endif /* unix */
373
374 /* calc min/max/avg */
375 usTotal += usCur;
376 if (usMax < usCur)
377 usMax = usCur;
378 if (usMin > usCur)
379 usMin = usCur;
380 }
381
382 /*
383 * Summary if more than one run.
384 */
385 if (cTimes != 1)
386 {
387 usAvg = usTotal / cTimes;
388
389 printf("%s: avg %um%u.%06us\n", name(argv[0]), (unsigned)(usAvg / 60000000), (unsigned)(usAvg % 60000000) / 1000000, (unsigned)(usAvg % 1000000));
390 printf("%s: min %um%u.%06us\n", name(argv[0]), (unsigned)(usMin / 60000000), (unsigned)(usMin % 60000000) / 1000000, (unsigned)(usMin % 1000000));
391 printf("%s: max %um%u.%06us\n", name(argv[0]), (unsigned)(usMax / 60000000), (unsigned)(usMax % 60000000) / 1000000, (unsigned)(usMax % 1000000));
392 }
393
394 return rc;
395}
396
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette