Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
empty portable.h and spread the include in files
[simgrid.git] / src / xbt / xbt_os_time.c
1 /* xbt_os_time.c -- portable interface to time-related functions            */
2
3 /* Copyright (c) 2007-2016. The SimGrid Team. All rights reserved.          */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "src/internal_config.h"
9 #include "xbt/sysdep.h"
10 #include "xbt/log.h"
11 #include "xbt/xbt_os_time.h"    /* this module */
12 #include <math.h>               /* floor */
13 #include <sys/time.h>
14 #include <time.h>
15
16 #ifdef _WIN32
17 #include <sys/timeb.h>
18 #include <windows.h>
19 #endif
20
21 //Freebsd doesn't provide this clock_gettime flag yet, because it was added too recently (after 1993)
22 #if defined (CLOCK_PROF) && ! defined (CLOCK_PROCESS_CPUTIME_ID)
23 #define CLOCK_PROCESS_CPUTIME_ID CLOCK_PROF
24 #endif
25
26 #if defined(__APPLE__) && defined(__MACH__)
27 #include <sys/types.h>
28 #include <sys/sysctl.h>
29 #include <mach/mach_init.h>
30 #include <mach/mach_host.h>
31 #include <mach/mach_port.h>
32 #include <mach/mach_traps.h>
33 #include <mach/task_info.h>
34 #include <mach/thread_info.h>
35 #include <mach/thread_act.h>
36 #include <mach/vm_region.h>
37 #include <mach/vm_map.h>
38 #include <mach/task.h>
39 #endif
40
41 double xbt_os_time(void)
42 {
43 #ifdef HAVE_GETTIMEOFDAY
44   struct timeval tv;
45   gettimeofday(&tv, NULL);
46 #elif defined(_WIN32)
47   struct timeval tv;
48   FILETIME ft;
49   unsigned __int64 tm;
50
51   GetSystemTimeAsFileTime(&ft);
52   tm = (unsigned __int64) ft.dwHighDateTime << 32;
53   tm |= ft.dwLowDateTime;
54   tm /= 10;
55   tm -= 11644473600000000ULL;
56
57   tv.tv_sec = (long) (tm / 1000000L);
58   tv.tv_usec = (long) (tm % 1000000L);
59
60 #else                           /* not windows, no gettimeofday => poor resolution */
61   return (double) (time(NULL));
62 #endif                          /* HAVE_GETTIMEOFDAY? */
63
64   return (double) (tv.tv_sec + tv.tv_usec / 1000000.0);
65 }
66
67 void xbt_os_sleep(double sec)
68 {
69
70 #ifdef _WIN32
71   Sleep((floor(sec) * 1000) + ((sec - floor(sec)) * 1000));
72
73 #elif HAVE_NANOSLEEP
74   struct timespec ts;
75   ts.tv_sec = sec;
76   ts.tv_nsec = (sec - floor(sec)) * 1e9;
77   nanosleep (&ts, NULL);
78 #else                           /* don't have nanosleep. Use select to sleep less than one second */
79   struct timeval timeout;
80
81   timeout.tv_sec = (unsigned long) (sec);
82   timeout.tv_usec = (sec - floor(sec)) * 1000000;
83
84   select(0, NULL, NULL, NULL, &timeout);
85 #endif
86 }
87
88 /* TSC (tick-level) timers are said to be unreliable on SMP hosts and thus
89    disabled in SDL source code */
90
91
92 /* \defgroup XBT_sysdep All system dependency
93  * \brief This section describes many macros/functions that can serve as
94  *  an OS abstraction.
95  */
96
97
98 struct s_xbt_os_timer {
99 #ifdef HAVE_POSIX_GETTIME
100   struct timespec start, stop, elapse;
101 #elif defined(HAVE_GETTIMEOFDAY) || defined(_WIN32)
102   struct timeval start, stop, elapse;
103 #else
104   unsigned long int start, stop, elapse;
105 #endif
106 };
107
108 size_t xbt_os_timer_size(void){
109   return sizeof(struct s_xbt_os_timer);
110 }
111
112 xbt_os_timer_t xbt_os_timer_new(void)
113 {
114   return xbt_new0(struct s_xbt_os_timer, 1);
115 }
116
117 void xbt_os_timer_free(xbt_os_timer_t timer)
118 {
119   free(timer);
120 }
121
122 double xbt_os_timer_elapsed(xbt_os_timer_t timer)
123 {
124 #ifdef HAVE_POSIX_GETTIME
125   return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec) +
126                                           ((double) timer->elapse.tv_sec ) +
127       ((((double) timer->stop.tv_nsec) -
128         ((double) timer->start.tv_nsec) + ((double) timer->elapse.tv_nsec )) / 1e9);
129 #elif defined(HAVE_GETTIMEOFDAY) || defined(_WIN32)
130   return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec)
131     + ((double) timer->elapse.tv_sec ) +
132       ((((double) timer->stop.tv_usec) -
133         ((double) timer->start.tv_usec) + ((double) timer->elapse.tv_usec )) / 1000000.0);
134 #else
135   return (double) timer->stop - (double) timer->start + (double)
136     timer->elapse;
137 #endif
138 }
139
140 void xbt_os_walltimer_start(xbt_os_timer_t timer)
141 {
142 #ifdef HAVE_POSIX_GETTIME
143   timer->elapse.tv_sec = 0;
144   timer->elapse.tv_nsec = 0;
145   clock_gettime(CLOCK_REALTIME, &(timer->start));
146 #elif defined(HAVE_GETTIMEOFDAY)
147   timer->elapse.tv_sec = 0;
148   timer->elapse.tv_usec = 0;
149   gettimeofday(&(timer->start), NULL);
150 #elif defined(_WIN32)
151   timer->elapse.tv_sec = 0;
152   timer->elapse.tv_usec = 0;
153   FILETIME ft;
154   unsigned __int64 tm;
155
156   GetSystemTimeAsFileTime(&ft);
157   tm = (unsigned __int64) ft.dwHighDateTime << 32;
158   tm |= ft.dwLowDateTime;
159   tm /= 10;
160   tm -= 11644473600000000ULL;
161
162   timer->start.tv_sec = (long) (tm / 1000000L);
163   timer->start.tv_usec = (long) (tm % 1000000L);
164 #else
165   timer->elapse = 0;
166   timer->start = (unsigned long int) (time(NULL));
167 #endif
168 }
169
170 void xbt_os_walltimer_resume(xbt_os_timer_t timer)
171 {
172 #ifdef HAVE_POSIX_GETTIME
173   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
174
175    timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
176   clock_gettime(CLOCK_REALTIME, &(timer->start));
177 #elif defined(HAVE_GETTIMEOFDAY)
178   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
179   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
180   gettimeofday(&(timer->start), NULL);
181 #elif defined(_WIN32)
182   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
183   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
184   FILETIME ft;
185   unsigned __int64 tm;
186
187   GetSystemTimeAsFileTime(&ft);
188   tm = (unsigned __int64) ft.dwHighDateTime << 32;
189   tm |= ft.dwLowDateTime;
190   tm /= 10;
191   tm -= 11644473600000000ULL;
192
193   timer->start.tv_sec = (long) (tm / 1000000L);
194   timer->start.tv_usec = (long) (tm % 1000000L);
195 #else
196   timer->elapse = timer->stop - timer->start;
197   timer->start = (unsigned long int) (time(NULL));
198 #endif
199 }
200
201 void xbt_os_walltimer_stop(xbt_os_timer_t timer)
202 {
203 #ifdef HAVE_POSIX_GETTIME
204   clock_gettime(CLOCK_REALTIME, &(timer->stop));
205 #elif defined(HAVE_GETTIMEOFDAY)
206   gettimeofday(&(timer->stop), NULL);
207 #elif defined(_WIN32)
208   FILETIME ft;
209   unsigned __int64 tm;
210
211   GetSystemTimeAsFileTime(&ft);
212   tm = (unsigned __int64) ft.dwHighDateTime << 32;
213   tm |= ft.dwLowDateTime;
214   tm /= 10;
215   tm -= 11644473600000000ULL;
216
217   timer->stop.tv_sec = (long) (tm / 1000000L);
218   timer->stop.tv_usec = (long) (tm % 1000000L);
219 #else
220   timer->stop = (unsigned long int) (time(NULL));
221 #endif
222 }
223
224 void xbt_os_cputimer_start(xbt_os_timer_t timer)
225 {
226 #ifdef HAVE_POSIX_GETTIME
227   timer->elapse.tv_sec = 0;
228   timer->elapse.tv_nsec = 0;
229   clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
230 #elif defined(HAVE_GETTIMEOFDAY)//return time and not cputime in this case
231   timer->elapse.tv_sec = 0;
232   timer->elapse.tv_usec = 0;
233   gettimeofday(&(timer->start), NULL);
234 #elif defined(_WIN32)
235   timer->elapse.tv_sec = 0;
236   timer->elapse.tv_usec = 0;
237   HANDLE h = GetCurrentProcess();
238   FILETIME creationTime, exitTime, kernelTime, userTime;
239   GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
240   unsigned __int64 ktm, utm;
241   ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
242   ktm |= kernelTime.dwLowDateTime;
243   ktm /= 10;
244   utm = (unsigned __int64) userTime.dwHighDateTime << 32;
245   utm |= userTime.dwLowDateTime;
246   utm /= 10;
247   timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
248   timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
249 #endif
250 }
251
252 void xbt_os_cputimer_resume(xbt_os_timer_t timer)
253 {
254 #ifdef HAVE_POSIX_GETTIME
255   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
256   timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
257   clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
258 #elif defined(HAVE_GETTIMEOFDAY)
259   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
260   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
261   gettimeofday(&(timer->start), NULL);
262 #elif defined(_WIN32)
263   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
264   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
265   HANDLE h = GetCurrentProcess();
266   FILETIME creationTime, exitTime, kernelTime, userTime;
267   GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
268   unsigned __int64 ktm, utm;
269   ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
270   ktm |= kernelTime.dwLowDateTime;
271   ktm /= 10;
272   utm = (unsigned __int64) userTime.dwHighDateTime << 32;
273   utm |= userTime.dwLowDateTime;
274   utm /= 10;
275   timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
276   timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
277 #endif
278 }
279
280 void xbt_os_cputimer_stop(xbt_os_timer_t timer)
281 {
282 #ifdef HAVE_POSIX_GETTIME
283   clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->stop));
284 #elif defined(HAVE_GETTIMEOFDAY)
285   gettimeofday(&(timer->stop), NULL);
286 #elif defined(_WIN32)
287   HANDLE h = GetCurrentProcess();
288   FILETIME creationTime, exitTime, kernelTime, userTime;
289   GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
290   unsigned __int64 ktm, utm;
291   ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
292   ktm |= kernelTime.dwLowDateTime;
293   ktm /= 10;
294   utm = (unsigned __int64) userTime.dwHighDateTime << 32;
295   utm |= userTime.dwLowDateTime;
296   utm /= 10;
297   timer->stop.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
298   timer->stop.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
299 #endif
300 }
301
302 void xbt_os_threadtimer_start(xbt_os_timer_t timer)
303 {
304 #ifdef HAVE_POSIX_GETTIME
305   timer->elapse.tv_sec = 0;
306   timer->elapse.tv_nsec = 0;
307   clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
308 #elif defined(HAVE_GETTIMEOFDAY) && defined(__MACH__) && defined(__APPLE__)
309   timer->elapse.tv_sec = 0;
310   timer->elapse.tv_usec = 0;
311   mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
312   thread_basic_info_data_t thi_data;
313   thread_basic_info_t thi = &thi_data;
314   thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
315   timer->start.tv_usec =  thi->system_time.microseconds + thi->user_time.microseconds;
316   timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
317 #elif defined(HAVE_GETTIMEOFDAY)//return time and not cputime in this case
318   timer->elapse.tv_sec = 0;
319   timer->elapse.tv_usec = 0;
320   gettimeofday(&(timer->start), NULL);
321 #elif defined(_WIN32)
322   HANDLE h = GetCurrentThread();
323   FILETIME creationTime, exitTime, kernelTime, userTime;
324   GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
325   unsigned __int64 ktm, utm;
326   ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
327   ktm |= kernelTime.dwLowDateTime;
328   ktm /= 10;
329   utm = (unsigned __int64) userTime.dwHighDateTime << 32;
330   utm |= userTime.dwLowDateTime;
331   utm /= 10;
332   timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
333   timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
334 #endif
335 }
336
337 void xbt_os_threadtimer_resume(xbt_os_timer_t timer)
338 {
339 #ifdef HAVE_POSIX_GETTIME
340   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
341   timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
342   clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
343 #elif defined(HAVE_GETTIMEOFDAY) && defined(__MACH__) && defined(__APPLE__)
344   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
345   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
346   mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
347   thread_basic_info_data_t thi_data;
348   thread_basic_info_t thi = &thi_data;
349   thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
350   timer->start.tv_usec =  thi->system_time.microseconds + thi->user_time.microseconds;
351   timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
352 #elif defined(HAVE_GETTIMEOFDAY)
353   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
354   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
355   gettimeofday(&(timer->start), NULL);
356 #elif defined(_WIN32)
357   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
358   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
359   HANDLE h = GetCurrentThread();
360   FILETIME creationTime, exitTime, kernelTime, userTime;
361   GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
362   unsigned __int64 ktm, utm;
363   ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
364   ktm |= kernelTime.dwLowDateTime;
365   ktm /= 10;
366   utm = (unsigned __int64) userTime.dwHighDateTime << 32;
367   utm |= userTime.dwLowDateTime;
368   utm /= 10;
369   timer->start.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
370   timer->start.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
371 #endif
372 }
373
374 void xbt_os_threadtimer_stop(xbt_os_timer_t timer)
375 {
376 #ifdef HAVE_POSIX_GETTIME
377   clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->stop));
378 #elif defined(HAVE_GETTIMEOFDAY) && defined(__MACH__) && defined(__APPLE__)
379   mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
380   thread_basic_info_data_t thi_data;
381   thread_basic_info_t thi = &thi_data;
382   thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
383   timer->stop.tv_usec =  thi->system_time.microseconds + thi->user_time.microseconds;
384   timer->stop.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
385 #elif defined(HAVE_GETTIMEOFDAY)//if nothing else is available, return just time
386   gettimeofday(&(timer->stop), NULL);
387 #elif defined(_WIN32)
388   HANDLE h = GetCurrentThread();
389   FILETIME creationTime, exitTime, kernelTime, userTime;
390   GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
391   unsigned __int64 ktm, utm;
392   ktm = (unsigned __int64) kernelTime.dwHighDateTime << 32;
393   ktm |= kernelTime.dwLowDateTime;
394   ktm /= 10;
395   utm = (unsigned __int64) userTime.dwHighDateTime << 32;
396   utm |= userTime.dwLowDateTime;
397   utm /= 10;
398   timer->stop.tv_sec = (long) (ktm / 1000000L) + (long) (utm / 1000000L);
399   timer->stop.tv_usec = (long) (ktm % 1000000L) + (long) (utm % 1000000L);
400 #endif
401 }