VirtualBox

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

Last change on this file since 1905 was 1894, checked in by bird, 16 years ago

kmk_time: linux compile issues.

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