1 /* xbt_os_time.c -- portable interface to time-related functions */
3 /* Copyright (c) 2007-2010, 2012-2014. The SimGrid Team.
4 * All rights reserved. */
6 /* This program is free software; you can redistribute it and/or modify it
7 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "xbt/sysdep.h"
10 #include "xbt/xbt_os_time.h" /* this module */
13 #include <math.h> /* floor */
16 #include <sys/timeb.h>
20 //Freebsd doesn't provide this clock_gettime flag yet, because it was added too recently (after 1993)
21 #if defined (CLOCK_PROF) && ! defined (CLOCK_PROCESS_CPUTIME_ID)
22 #define CLOCK_PROCESS_CPUTIME_ID CLOCK_PROF
25 #if defined(__APPLE__) && defined(__MACH__)
26 #include <sys/types.h>
27 #include <sys/sysctl.h>
28 #include <mach/mach_init.h>
29 #include <mach/mach_host.h>
30 #include <mach/mach_port.h>
31 #include <mach/mach_traps.h>
32 #include <mach/task_info.h>
33 #include <mach/thread_info.h>
34 #include <mach/thread_act.h>
35 #include <mach/vm_region.h>
36 #include <mach/vm_map.h>
37 #include <mach/task.h>
40 double xbt_os_time(void)
42 #ifdef HAVE_GETTIMEOFDAY
44 gettimeofday(&tv, NULL);
45 #elif defined(_XBT_WIN32)
47 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
53 tv.tv_usec = tm.millitm * 1000;
59 GetSystemTimeAsFileTime(&ft);
60 tm = (unsigned __int64) ft.dwHighDateTime << 32;
61 tm |= ft.dwLowDateTime;
63 tm -= 11644473600000000ULL;
65 tv.tv_sec = (long) (tm / 1000000L);
66 tv.tv_usec = (long) (tm % 1000000L);
67 # endif /* windows version checker */
69 #else /* not windows, no gettimeofday => poor resolution */
70 return (double) (time(NULL));
71 #endif /* HAVE_GETTIMEOFDAY? */
73 return (double) (tv.tv_sec + tv.tv_usec / 1000000.0);
76 void xbt_os_sleep(double sec)
80 Sleep((floor(sec) * 1000) + ((sec - floor(sec)) * 1000));
85 ts.tv_nsec = (sec - floor(sec)) * 1e9;
86 nanosleep (&ts, NULL);
87 #else /* don't have nanosleep. Use select to sleep less than one second */
88 struct timeval timeout;
90 timeout.tv_sec = (unsigned long) (sec);
91 timeout.tv_usec = (sec - floor(sec)) * 1000000;
93 select(0, NULL, NULL, NULL, &timeout);
97 /* TSC (tick-level) timers are said to be unreliable on SMP hosts and thus
98 disabled in SDL source code */
101 /* \defgroup XBT_sysdep All system dependency
102 * \brief This section describes many macros/functions that can serve as
107 struct s_xbt_os_timer {
108 #ifdef HAVE_POSIX_GETTIME
109 struct timespec start, stop, elapse;
110 #elif defined(HAVE_GETTIMEOFDAY) || defined(_XBT_WIN32)
111 struct timeval start, stop, elapse;
113 unsigned long int start, stop, elapse;
117 size_t xbt_os_timer_size(void){
118 return sizeof(struct s_xbt_os_timer);
121 xbt_os_timer_t xbt_os_timer_new(void)
123 return xbt_new0(struct s_xbt_os_timer, 1);
126 void xbt_os_timer_free(xbt_os_timer_t timer)
131 double xbt_os_timer_elapsed(xbt_os_timer_t timer)
133 #ifdef HAVE_POSIX_GETTIME
134 return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec) +
135 ((double) timer->elapse.tv_sec ) +
136 ((((double) timer->stop.tv_nsec) -
137 ((double) timer->start.tv_nsec) + ((double) timer->elapse.tv_nsec )) / 1e9);
138 #elif defined(HAVE_GETTIMEOFDAY) || defined(_XBT_WIN32)
139 return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec)
140 + ((double) timer->elapse.tv_sec ) +
141 ((((double) timer->stop.tv_usec) -
142 ((double) timer->start.tv_usec) + ((double) timer->elapse.tv_usec )) / 1000000.0);
144 return (double) timer->stop - (double) timer->start + (double)
149 void xbt_os_walltimer_start(xbt_os_timer_t timer)
151 #ifdef HAVE_POSIX_GETTIME
152 timer->elapse.tv_sec = 0;
153 timer->elapse.tv_nsec = 0;
154 clock_gettime(CLOCK_REALTIME, &(timer->start));
155 #elif defined(HAVE_GETTIMEOFDAY)
156 timer->elapse.tv_sec = 0;
157 timer->elapse.tv_usec = 0;
158 gettimeofday(&(timer->start), NULL);
159 #elif defined(_XBT_WIN32)
160 timer->elapse.tv_sec = 0;
161 timer->elapse.tv_usec = 0;
162 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
167 timer->start.tv_sec = tm.time;
168 timer->start.tv_usec = tm.millitm * 1000;
174 GetSystemTimeAsFileTime(&ft);
175 tm = (unsigned __int64) ft.dwHighDateTime << 32;
176 tm |= ft.dwLowDateTime;
178 tm -= 11644473600000000ULL;
180 timer->start.tv_sec = (long) (tm / 1000000L);
181 timer->start.tv_usec = (long) (tm % 1000000L);
182 # endif /* windows version checker */
185 timer->start = (unsigned long int) (time(NULL));
189 void xbt_os_walltimer_resume(xbt_os_timer_t timer)
191 #ifdef HAVE_POSIX_GETTIME
192 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
194 timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
195 clock_gettime(CLOCK_REALTIME, &(timer->start));
196 #elif defined(HAVE_GETTIMEOFDAY)
197 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
198 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
199 gettimeofday(&(timer->start), NULL);
200 #elif defined(_XBT_WIN32)
201 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
202 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
203 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
208 timer->start.tv_sec = tm.time;
209 timer->start.tv_usec = tm.millitm * 1000;
215 GetSystemTimeAsFileTime(&ft);
216 tm = (unsigned __int64) ft.dwHighDateTime << 32;
217 tm |= ft.dwLowDateTime;
219 tm -= 11644473600000000ULL;
221 timer->start.tv_sec = (long) (tm / 1000000L);
222 timer->start.tv_usec = (long) (tm % 1000000L);
225 timer->elapse = timer->stop - timer->start;
226 timer->start = (unsigned long int) (time(NULL));
230 void xbt_os_walltimer_stop(xbt_os_timer_t timer)
232 #ifdef HAVE_POSIX_GETTIME
233 clock_gettime(CLOCK_REALTIME, &(timer->stop));
234 #elif defined(HAVE_GETTIMEOFDAY)
235 gettimeofday(&(timer->stop), NULL);
236 #elif defined(_XBT_WIN32)
237 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
242 timer->stop.tv_sec = tm.time;
243 timer->stop.tv_usec = tm.millitm * 1000;
249 GetSystemTimeAsFileTime(&ft);
250 tm = (unsigned __int64) ft.dwHighDateTime << 32;
251 tm |= ft.dwLowDateTime;
253 tm -= 11644473600000000ULL;
255 timer->stop.tv_sec = (long) (tm / 1000000L);
256 timer->stop.tv_usec = (long) (tm % 1000000L);
259 timer->stop = (unsigned long int) (time(NULL));
263 void xbt_os_cputimer_start(xbt_os_timer_t timer)
265 #ifdef HAVE_POSIX_GETTIME
266 timer->elapse.tv_sec = 0;
267 timer->elapse.tv_nsec = 0;
268 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
269 #elif defined(HAVE_GETTIMEOFDAY)//return time and not cputime in this case
270 timer->elapse.tv_sec = 0;
271 timer->elapse.tv_usec = 0;
272 gettimeofday(&(timer->start), NULL);
273 #elif defined(_XBT_WIN32)
274 timer->elapse.tv_sec = 0;
275 timer->elapse.tv_usec = 0;
276 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
279 HANDLE h = GetCurrentProcess();
280 FILETIME creationTime, exitTime, kernelTime, userTime;
281 GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
282 unsigned __int64 ktm, utm;
283 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
284 ktm |= kernelTime.dwLowDateTime;
286 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
287 utm |= userTime.dwLowDateTime;
289 timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
290 timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
291 # endif /* windows version checker */
295 void xbt_os_cputimer_resume(xbt_os_timer_t timer)
297 #ifdef HAVE_POSIX_GETTIME
298 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
299 timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
300 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
301 #elif defined(HAVE_GETTIMEOFDAY)
302 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
303 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
304 gettimeofday(&(timer->start), NULL);
305 #elif defined(_XBT_WIN32)
306 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
307 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
308 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
311 HANDLE h = GetCurrentProcess();
312 FILETIME creationTime, exitTime, kernelTime, userTime;
313 GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
314 unsigned __int64 ktm, utm;
315 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
316 ktm |= kernelTime.dwLowDateTime;
318 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
319 utm |= userTime.dwLowDateTime;
321 timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
322 timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
323 # endif /* windows version checker */
328 void xbt_os_cputimer_stop(xbt_os_timer_t timer)
330 #ifdef HAVE_POSIX_GETTIME
331 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->stop));
332 #elif defined(HAVE_GETTIMEOFDAY)
333 gettimeofday(&(timer->stop), NULL);
334 #elif defined(_XBT_WIN32)
335 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
338 HANDLE h = GetCurrentProcess();
339 FILETIME creationTime, exitTime, kernelTime, userTime;
340 GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
341 unsigned __int64 ktm, utm;
342 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
343 ktm |= kernelTime.dwLowDateTime;
345 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
346 utm |= userTime.dwLowDateTime;
348 timer->stop.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
349 timer->stop.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
350 # endif /* windows version checker */
354 void xbt_os_threadtimer_start(xbt_os_timer_t timer)
356 #ifdef HAVE_POSIX_GETTIME
357 timer->elapse.tv_sec = 0;
358 timer->elapse.tv_nsec = 0;
359 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
360 #elif defined(HAVE_GETTIMEOFDAY) && defined(__MACH__) && defined(__APPLE__)//attempt for timing of the thread on OSX
361 timer->elapse.tv_sec = 0;
362 timer->elapse.tv_usec = 0;
363 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
364 thread_basic_info_data_t thi_data;
365 thread_basic_info_t thi = &thi_data;
366 thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
367 timer->start.tv_usec = thi->system_time.microseconds + thi->user_time.microseconds;
368 timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
369 #elif defined(HAVE_GETTIMEOFDAY)//return time and not cputime in this case
370 timer->elapse.tv_sec = 0;
371 timer->elapse.tv_usec = 0;
372 gettimeofday(&(timer->start), NULL);
373 #elif defined(_XBT_WIN32)
375 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
378 HANDLE h = GetCurrentThread();
379 FILETIME creationTime, exitTime, kernelTime, userTime;
380 GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
381 unsigned __int64 ktm, utm;
382 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
383 ktm |= kernelTime.dwLowDateTime;
385 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
386 utm |= userTime.dwLowDateTime;
388 timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
389 timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
390 # endif /* windows version checker */
394 void xbt_os_threadtimer_resume(xbt_os_timer_t timer)
396 #ifdef HAVE_POSIX_GETTIME
397 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
398 timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
399 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
400 #elif defined(HAVE_GETTIMEOFDAY) && defined(__MACH__) && defined(__APPLE__)
401 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
402 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
403 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
404 thread_basic_info_data_t thi_data;
405 thread_basic_info_t thi = &thi_data;
406 thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
407 timer->start.tv_usec = thi->system_time.microseconds + thi->user_time.microseconds;
408 timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
409 #elif defined(HAVE_GETTIMEOFDAY)
410 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
411 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
412 gettimeofday(&(timer->start), NULL);
413 #elif defined(_XBT_WIN32)
414 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
415 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
416 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
419 HANDLE h = GetCurrentThread();
420 FILETIME creationTime, exitTime, kernelTime, userTime;
421 GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
422 unsigned __int64 ktm, utm;
423 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
424 ktm |= kernelTime.dwLowDateTime;
426 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
427 utm |= userTime.dwLowDateTime;
429 timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
430 timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
431 # endif /* windows version checker */
435 void xbt_os_threadtimer_stop(xbt_os_timer_t timer)
437 #ifdef HAVE_POSIX_GETTIME
438 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->stop));
439 #elif defined(HAVE_GETTIMEOFDAY) && defined(__MACH__) && defined(__APPLE__)
440 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
441 thread_basic_info_data_t thi_data;
442 thread_basic_info_t thi = &thi_data;
443 thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
444 timer->stop.tv_usec = thi->system_time.microseconds + thi->user_time.microseconds;
445 timer->stop.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
446 #elif defined(HAVE_GETTIMEOFDAY)//if nothing else is available, return just time
447 gettimeofday(&(timer->stop), NULL);
448 #elif defined(_XBT_WIN32)
449 # if defined(WIN32_WCE) || (_WIN32_WINNT < 0x0400)
452 HANDLE h = GetCurrentThread();
453 FILETIME creationTime, exitTime, kernelTime, userTime;
454 GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
455 unsigned __int64 ktm, utm;
456 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
457 ktm |= kernelTime.dwLowDateTime;
459 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
460 utm |= userTime.dwLowDateTime;
462 timer->stop.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
463 timer->stop.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
464 # endif /* windows version checker */