1 /* xbt_os_time.c -- portable interface to time-related functions */
3 /* Copyright (c) 2007-2010, 2012-2015. 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 */
12 #include "src/portable.h"
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);
50 GetSystemTimeAsFileTime(&ft);
51 tm = (unsigned __int64) ft.dwHighDateTime << 32;
52 tm |= ft.dwLowDateTime;
54 tm -= 11644473600000000ULL;
56 tv.tv_sec = (long) (tm / 1000000L);
57 tv.tv_usec = (long) (tm % 1000000L);
59 #else /* not windows, no gettimeofday => poor resolution */
60 return (double) (time(NULL));
61 #endif /* HAVE_GETTIMEOFDAY? */
63 return (double) (tv.tv_sec + tv.tv_usec / 1000000.0);
66 void xbt_os_sleep(double sec)
70 Sleep((floor(sec) * 1000) + ((sec - floor(sec)) * 1000));
75 ts.tv_nsec = (sec - floor(sec)) * 1e9;
76 nanosleep (&ts, NULL);
77 #else /* don't have nanosleep. Use select to sleep less than one second */
78 struct timeval timeout;
80 timeout.tv_sec = (unsigned long) (sec);
81 timeout.tv_usec = (sec - floor(sec)) * 1000000;
83 select(0, NULL, NULL, NULL, &timeout);
87 /* TSC (tick-level) timers are said to be unreliable on SMP hosts and thus
88 disabled in SDL source code */
91 /* \defgroup XBT_sysdep All system dependency
92 * \brief This section describes many macros/functions that can serve as
97 struct s_xbt_os_timer {
98 #ifdef HAVE_POSIX_GETTIME
99 struct timespec start, stop, elapse;
100 #elif defined(HAVE_GETTIMEOFDAY) || defined(_WIN32)
101 struct timeval start, stop, elapse;
103 unsigned long int start, stop, elapse;
107 size_t xbt_os_timer_size(void){
108 return sizeof(struct s_xbt_os_timer);
111 xbt_os_timer_t xbt_os_timer_new(void)
113 return xbt_new0(struct s_xbt_os_timer, 1);
116 void xbt_os_timer_free(xbt_os_timer_t timer)
121 double xbt_os_timer_elapsed(xbt_os_timer_t timer)
123 #ifdef HAVE_POSIX_GETTIME
124 return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec) +
125 ((double) timer->elapse.tv_sec ) +
126 ((((double) timer->stop.tv_nsec) -
127 ((double) timer->start.tv_nsec) + ((double) timer->elapse.tv_nsec )) / 1e9);
128 #elif defined(HAVE_GETTIMEOFDAY) || defined(_WIN32)
129 return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec)
130 + ((double) timer->elapse.tv_sec ) +
131 ((((double) timer->stop.tv_usec) -
132 ((double) timer->start.tv_usec) + ((double) timer->elapse.tv_usec )) / 1000000.0);
134 return (double) timer->stop - (double) timer->start + (double)
139 void xbt_os_walltimer_start(xbt_os_timer_t timer)
141 #ifdef HAVE_POSIX_GETTIME
142 timer->elapse.tv_sec = 0;
143 timer->elapse.tv_nsec = 0;
144 clock_gettime(CLOCK_REALTIME, &(timer->start));
145 #elif defined(HAVE_GETTIMEOFDAY)
146 timer->elapse.tv_sec = 0;
147 timer->elapse.tv_usec = 0;
148 gettimeofday(&(timer->start), NULL);
149 #elif defined(_WIN32)
150 timer->elapse.tv_sec = 0;
151 timer->elapse.tv_usec = 0;
155 GetSystemTimeAsFileTime(&ft);
156 tm = (unsigned __int64) ft.dwHighDateTime << 32;
157 tm |= ft.dwLowDateTime;
159 tm -= 11644473600000000ULL;
161 timer->start.tv_sec = (long) (tm / 1000000L);
162 timer->start.tv_usec = (long) (tm % 1000000L);
165 timer->start = (unsigned long int) (time(NULL));
169 void xbt_os_walltimer_resume(xbt_os_timer_t timer)
171 #ifdef HAVE_POSIX_GETTIME
172 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
174 timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
175 clock_gettime(CLOCK_REALTIME, &(timer->start));
176 #elif defined(HAVE_GETTIMEOFDAY)
177 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
178 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
179 gettimeofday(&(timer->start), NULL);
180 #elif defined(_WIN32)
181 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
182 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
186 GetSystemTimeAsFileTime(&ft);
187 tm = (unsigned __int64) ft.dwHighDateTime << 32;
188 tm |= ft.dwLowDateTime;
190 tm -= 11644473600000000ULL;
192 timer->start.tv_sec = (long) (tm / 1000000L);
193 timer->start.tv_usec = (long) (tm % 1000000L);
195 timer->elapse = timer->stop - timer->start;
196 timer->start = (unsigned long int) (time(NULL));
200 void xbt_os_walltimer_stop(xbt_os_timer_t timer)
202 #ifdef HAVE_POSIX_GETTIME
203 clock_gettime(CLOCK_REALTIME, &(timer->stop));
204 #elif defined(HAVE_GETTIMEOFDAY)
205 gettimeofday(&(timer->stop), NULL);
206 #elif defined(_WIN32)
210 GetSystemTimeAsFileTime(&ft);
211 tm = (unsigned __int64) ft.dwHighDateTime << 32;
212 tm |= ft.dwLowDateTime;
214 tm -= 11644473600000000ULL;
216 timer->stop.tv_sec = (long) (tm / 1000000L);
217 timer->stop.tv_usec = (long) (tm % 1000000L);
219 timer->stop = (unsigned long int) (time(NULL));
223 void xbt_os_cputimer_start(xbt_os_timer_t timer)
225 #ifdef HAVE_POSIX_GETTIME
226 timer->elapse.tv_sec = 0;
227 timer->elapse.tv_nsec = 0;
228 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
229 #elif defined(HAVE_GETTIMEOFDAY)//return time and not cputime in this case
230 timer->elapse.tv_sec = 0;
231 timer->elapse.tv_usec = 0;
232 gettimeofday(&(timer->start), NULL);
233 #elif defined(_WIN32)
234 timer->elapse.tv_sec = 0;
235 timer->elapse.tv_usec = 0;
236 HANDLE h = GetCurrentProcess();
237 FILETIME creationTime, exitTime, kernelTime, userTime;
238 GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
239 unsigned __int64 ktm, utm;
240 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
241 ktm |= kernelTime.dwLowDateTime;
243 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
244 utm |= userTime.dwLowDateTime;
246 timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
247 timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
251 void xbt_os_cputimer_resume(xbt_os_timer_t timer)
253 #ifdef HAVE_POSIX_GETTIME
254 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
255 timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
256 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
257 #elif defined(HAVE_GETTIMEOFDAY)
258 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
259 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
260 gettimeofday(&(timer->start), NULL);
261 #elif defined(_WIN32)
262 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
263 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
264 HANDLE h = GetCurrentProcess();
265 FILETIME creationTime, exitTime, kernelTime, userTime;
266 GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
267 unsigned __int64 ktm, utm;
268 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
269 ktm |= kernelTime.dwLowDateTime;
271 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
272 utm |= userTime.dwLowDateTime;
274 timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
275 timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
279 void xbt_os_cputimer_stop(xbt_os_timer_t timer)
281 #ifdef HAVE_POSIX_GETTIME
282 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->stop));
283 #elif defined(HAVE_GETTIMEOFDAY)
284 gettimeofday(&(timer->stop), NULL);
285 #elif defined(_WIN32)
286 HANDLE h = GetCurrentProcess();
287 FILETIME creationTime, exitTime, kernelTime, userTime;
288 GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
289 unsigned __int64 ktm, utm;
290 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
291 ktm |= kernelTime.dwLowDateTime;
293 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
294 utm |= userTime.dwLowDateTime;
296 timer->stop.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
297 timer->stop.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
301 void xbt_os_threadtimer_start(xbt_os_timer_t timer)
303 #ifdef HAVE_POSIX_GETTIME
304 timer->elapse.tv_sec = 0;
305 timer->elapse.tv_nsec = 0;
306 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
307 #elif defined(HAVE_GETTIMEOFDAY) && defined(__MACH__) && defined(__APPLE__)
308 timer->elapse.tv_sec = 0;
309 timer->elapse.tv_usec = 0;
310 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
311 thread_basic_info_data_t thi_data;
312 thread_basic_info_t thi = &thi_data;
313 thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
314 timer->start.tv_usec = thi->system_time.microseconds + thi->user_time.microseconds;
315 timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
316 #elif defined(HAVE_GETTIMEOFDAY)//return time and not cputime in this case
317 timer->elapse.tv_sec = 0;
318 timer->elapse.tv_usec = 0;
319 gettimeofday(&(timer->start), NULL);
320 #elif defined(_WIN32)
321 HANDLE h = GetCurrentThread();
322 FILETIME creationTime, exitTime, kernelTime, userTime;
323 GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
324 unsigned __int64 ktm, utm;
325 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
326 ktm |= kernelTime.dwLowDateTime;
328 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
329 utm |= userTime.dwLowDateTime;
331 timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
332 timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
336 void xbt_os_threadtimer_resume(xbt_os_timer_t timer)
338 #ifdef HAVE_POSIX_GETTIME
339 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
340 timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
341 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
342 #elif defined(HAVE_GETTIMEOFDAY) && defined(__MACH__) && defined(__APPLE__)
343 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
344 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
345 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
346 thread_basic_info_data_t thi_data;
347 thread_basic_info_t thi = &thi_data;
348 thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
349 timer->start.tv_usec = thi->system_time.microseconds + thi->user_time.microseconds;
350 timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
351 #elif defined(HAVE_GETTIMEOFDAY)
352 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
353 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
354 gettimeofday(&(timer->start), NULL);
355 #elif defined(_WIN32)
356 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
357 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
358 HANDLE h = GetCurrentThread();
359 FILETIME creationTime, exitTime, kernelTime, userTime;
360 GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
361 unsigned __int64 ktm, utm;
362 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
363 ktm |= kernelTime.dwLowDateTime;
365 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
366 utm |= userTime.dwLowDateTime;
368 timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
369 timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
373 void xbt_os_threadtimer_stop(xbt_os_timer_t timer)
375 #ifdef HAVE_POSIX_GETTIME
376 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->stop));
377 #elif defined(HAVE_GETTIMEOFDAY) && defined(__MACH__) && defined(__APPLE__)
378 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
379 thread_basic_info_data_t thi_data;
380 thread_basic_info_t thi = &thi_data;
381 thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
382 timer->stop.tv_usec = thi->system_time.microseconds + thi->user_time.microseconds;
383 timer->stop.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
384 #elif defined(HAVE_GETTIMEOFDAY)//if nothing else is available, return just time
385 gettimeofday(&(timer->stop), NULL);
386 #elif defined(_WIN32)
387 HANDLE h = GetCurrentThread();
388 FILETIME creationTime, exitTime, kernelTime, userTime;
389 GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
390 unsigned __int64 ktm, utm;
391 ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
392 ktm |= kernelTime.dwLowDateTime;
394 utm = (unsigned __int64) userTime.dwHighDateTime << 32;
395 utm |= userTime.dwLowDateTime;
397 timer->stop.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
398 timer->stop.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);