Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
remove the argc/argv version of simcall_process_create
[simgrid.git] / src / xbt / xbt_os_time.c
1 /* xbt_os_time.c -- portable interface to time-related functions            */
2
3 /* Copyright (c) 2007-2018. 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 #ifdef _WIN32
42 static void w32_time_to_timeval(struct timeval* tv, const FILETIME* ft)
43 {
44   unsigned __int64 tm;
45   tm = (unsigned __int64)ft->dwHighDateTime << 32;
46   tm |= ft->dwLowDateTime;
47   tm /= 10;
48   tm -= 11644473600000000ULL;
49   tv->tv_sec  = (long)(tm / 1000000L);
50   tv->tv_usec = (long)(tm % 1000000L);
51 }
52
53 static void w32_times_to_timeval(struct timeval* tv, const FILETIME* kernel_time, const FILETIME* user_time)
54 {
55   unsigned __int64 ktm, utm;
56   ktm = (unsigned __int64)kernel_time->dwHighDateTime << 32;
57   ktm |= kernel_time->dwLowDateTime;
58   ktm /= 10;
59   utm = (unsigned __int64)user_time->dwHighDateTime << 32;
60   utm |= user_time->dwLowDateTime;
61   utm /= 10;
62   tv->tv_sec  = (long)(ktm / 1000000L) + (long)(utm / 1000000L);
63   tv->tv_usec = (long)(ktm % 1000000L) + (long)(utm % 1000000L);
64 }
65 #endif
66
67 double xbt_os_time(void)
68 {
69 #if HAVE_GETTIMEOFDAY
70   struct timeval tv;
71   gettimeofday(&tv, NULL);
72 #elif defined(_WIN32)
73   struct timeval tv;
74   FILETIME ft;
75   GetSystemTimeAsFileTime(&ft);
76   w32_time_to_timeval(&tv, &ft);
77 #else                           /* not windows, no gettimeofday => poor resolution */
78   return (double) (time(NULL));
79 #endif                          /* HAVE_GETTIMEOFDAY? */
80
81   return (double) (tv.tv_sec + tv.tv_usec / 1000000.0);
82 }
83
84 void xbt_os_sleep(double sec)
85 {
86
87 #ifdef _WIN32
88   Sleep((floor(sec) * 1000) + ((sec - floor(sec)) * 1000));
89
90 #elif HAVE_NANOSLEEP
91   struct timespec ts;
92   ts.tv_sec = sec;
93   ts.tv_nsec = (sec - floor(sec)) * 1e9;
94   nanosleep (&ts, NULL);
95 #else                           /* don't have nanosleep. Use select to sleep less than one second */
96   struct timeval timeout;
97
98   timeout.tv_sec = (unsigned long) (sec);
99   timeout.tv_usec = (sec - floor(sec)) * 1000000;
100
101   select(0, NULL, NULL, NULL, &timeout);
102 #endif
103 }
104
105 /* TSC (tick-level) timers are said to be unreliable on SMP hosts and thus  disabled in SDL source code */
106
107 /* @defgroup XBT_sysdep All system dependency
108  * @brief This section describes many macros/functions that can serve as  an OS abstraction.
109  */
110 struct s_xbt_os_timer {
111 #if HAVE_POSIX_GETTIME
112   struct timespec start;
113   struct timespec stop;
114   struct timespec elapse;
115 #elif HAVE_GETTIMEOFDAY || defined(_WIN32)
116   struct timeval start;
117   struct timeval stop;
118   struct timeval elapse;
119 #else
120   unsigned long int start;
121   unsigned long int stop;
122   unsigned long int elapse;
123 #endif
124 };
125
126 size_t xbt_os_timer_size(void)
127 {
128   return sizeof(struct s_xbt_os_timer);
129 }
130
131 xbt_os_timer_t xbt_os_timer_new(void)
132 {
133   return xbt_new0(struct s_xbt_os_timer, 1);
134 }
135
136 void xbt_os_timer_free(xbt_os_timer_t timer)
137 {
138   free(timer);
139 }
140
141 double xbt_os_timer_elapsed(xbt_os_timer_t timer)
142 {
143 #if HAVE_POSIX_GETTIME
144   return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec) + ((double) timer->elapse.tv_sec ) +
145       ((((double) timer->stop.tv_nsec) - ((double) timer->start.tv_nsec) + ((double) timer->elapse.tv_nsec )) / 1e9);
146 #elif HAVE_GETTIMEOFDAY || defined(_WIN32)
147   return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec) + ((double) timer->elapse.tv_sec ) +
148       ((((double) timer->stop.tv_usec) - ((double) timer->start.tv_usec) + ((double) timer->elapse.tv_usec )) /
149          1000000.0);
150 #else
151   return (double) timer->stop - (double) timer->start + (double) timer->elapse;
152 #endif
153 }
154
155 void xbt_os_walltimer_start(xbt_os_timer_t timer)
156 {
157 #if HAVE_POSIX_GETTIME
158   timer->elapse.tv_sec = 0;
159   timer->elapse.tv_nsec = 0;
160   clock_gettime(CLOCK_REALTIME, &(timer->start));
161 #elif HAVE_GETTIMEOFDAY
162   timer->elapse.tv_sec = 0;
163   timer->elapse.tv_usec = 0;
164   gettimeofday(&(timer->start), NULL);
165 #elif defined(_WIN32)
166   timer->elapse.tv_sec = 0;
167   timer->elapse.tv_usec = 0;
168   FILETIME ft;
169   GetSystemTimeAsFileTime(&ft);
170   w32_time_to_timeval(&timer->start, &ft);
171 #else
172   timer->elapse = 0;
173   timer->start = (unsigned long int) (time(NULL));
174 #endif
175 }
176
177 void xbt_os_walltimer_resume(xbt_os_timer_t timer)
178 {
179 #if HAVE_POSIX_GETTIME
180   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
181
182    timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
183   clock_gettime(CLOCK_REALTIME, &(timer->start));
184 #elif HAVE_GETTIMEOFDAY
185   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
186   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
187   gettimeofday(&(timer->start), NULL);
188 #elif defined(_WIN32)
189   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
190   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
191   FILETIME ft;
192   GetSystemTimeAsFileTime(&ft);
193   w32_time_to_timeval(&timer->start, &ft);
194 #else
195   timer->elapse = timer->stop - timer->start;
196   timer->start = (unsigned long int) (time(NULL));
197 #endif
198 }
199
200 void xbt_os_walltimer_stop(xbt_os_timer_t timer)
201 {
202 #if HAVE_POSIX_GETTIME
203   clock_gettime(CLOCK_REALTIME, &(timer->stop));
204 #elif HAVE_GETTIMEOFDAY
205   gettimeofday(&(timer->stop), NULL);
206 #elif defined(_WIN32)
207   FILETIME ft;
208   GetSystemTimeAsFileTime(&ft);
209   w32_time_to_timeval(&timer->stop, &ft);
210 #else
211   timer->stop = (unsigned long int) (time(NULL));
212 #endif
213 }
214
215 void xbt_os_cputimer_start(xbt_os_timer_t timer)
216 {
217 #if HAVE_POSIX_GETTIME
218   timer->elapse.tv_sec = 0;
219   timer->elapse.tv_nsec = 0;
220   clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
221 #elif HAVE_GETTIMEOFDAY //return time and not cputime in this case
222   timer->elapse.tv_sec = 0;
223   timer->elapse.tv_usec = 0;
224   gettimeofday(&(timer->start), NULL);
225 #elif defined(_WIN32)
226   timer->elapse.tv_sec = 0;
227   timer->elapse.tv_usec = 0;
228   HANDLE h = GetCurrentProcess();
229   FILETIME creationTime, exitTime, kernelTime, userTime;
230   GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
231   w32_times_to_timeval(&timer->start, &kernelTime, &userTime);
232 #endif
233 }
234
235 void xbt_os_cputimer_resume(xbt_os_timer_t timer)
236 {
237 #if HAVE_POSIX_GETTIME
238   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
239   timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
240   clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
241 #elif HAVE_GETTIMEOFDAY
242   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
243   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
244   gettimeofday(&(timer->start), NULL);
245 #elif defined(_WIN32)
246   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
247   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
248   HANDLE h = GetCurrentProcess();
249   FILETIME creationTime, exitTime, kernelTime, userTime;
250   GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
251   w32_times_to_timeval(&timer->start, &kernelTime, &userTime);
252 #endif
253 }
254
255 void xbt_os_cputimer_stop(xbt_os_timer_t timer)
256 {
257 #if HAVE_POSIX_GETTIME
258   clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->stop));
259 #elif HAVE_GETTIMEOFDAY
260   gettimeofday(&(timer->stop), NULL);
261 #elif defined(_WIN32)
262   HANDLE h = GetCurrentProcess();
263   FILETIME creationTime, exitTime, kernelTime, userTime;
264   GetProcessTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
265   w32_times_to_timeval(&timer->stop, &kernelTime, &userTime);
266 #endif
267 }
268
269 void xbt_os_threadtimer_start(xbt_os_timer_t timer)
270 {
271 #if HAVE_POSIX_GETTIME
272   timer->elapse.tv_sec = 0;
273   timer->elapse.tv_nsec = 0;
274   clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
275 #elif HAVE_GETTIMEOFDAY && defined(__MACH__) && defined(__APPLE__)
276   timer->elapse.tv_sec = 0;
277   timer->elapse.tv_usec = 0;
278   mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
279   thread_basic_info_data_t thi_data;
280   thread_basic_info_t thi = &thi_data;
281   thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
282   timer->start.tv_usec =  thi->system_time.microseconds + thi->user_time.microseconds;
283   timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
284 #elif HAVE_GETTIMEOFDAY //return time and not cputime in this case
285   timer->elapse.tv_sec = 0;
286   timer->elapse.tv_usec = 0;
287   gettimeofday(&(timer->start), NULL);
288 #elif defined(_WIN32)
289   HANDLE h = GetCurrentThread();
290   FILETIME creationTime, exitTime, kernelTime, userTime;
291   GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
292   w32_times_to_timeval(&timer->start, &kernelTime, &userTime);
293 #endif
294 }
295
296 void xbt_os_threadtimer_resume(xbt_os_timer_t timer)
297 {
298 #if HAVE_POSIX_GETTIME
299   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
300   timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
301   clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
302 #elif HAVE_GETTIMEOFDAY && defined(__MACH__) && defined(__APPLE__)
303   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
304   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
305   mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
306   thread_basic_info_data_t thi_data;
307   thread_basic_info_t thi = &thi_data;
308   thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
309   timer->start.tv_usec =  thi->system_time.microseconds + thi->user_time.microseconds;
310   timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
311 #elif HAVE_GETTIMEOFDAY
312   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
313   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
314   gettimeofday(&(timer->start), NULL);
315 #elif defined(_WIN32)
316   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
317   timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
318   HANDLE h = GetCurrentThread();
319   FILETIME creationTime, exitTime, kernelTime, userTime;
320   GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
321   w32_times_to_timeval(&timer->start, &kernelTime, &userTime);
322 #endif
323 }
324
325 void xbt_os_threadtimer_stop(xbt_os_timer_t timer)
326 {
327 #if HAVE_POSIX_GETTIME
328   clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->stop));
329 #elif HAVE_GETTIMEOFDAY && defined(__MACH__) && defined(__APPLE__)
330   mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
331   thread_basic_info_data_t thi_data;
332   thread_basic_info_t thi = &thi_data;
333   thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
334   timer->stop.tv_usec =  thi->system_time.microseconds + thi->user_time.microseconds;
335   timer->stop.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
336 #elif HAVE_GETTIMEOFDAY //if nothing else is available, return just time
337   gettimeofday(&(timer->stop), NULL);
338 #elif defined(_WIN32)
339   HANDLE h = GetCurrentThread();
340   FILETIME creationTime, exitTime, kernelTime, userTime;
341   GetThreadTimes(h, &creationTime, &exitTime, &kernelTime, &userTime);
342   w32_times_to_timeval(&timer->stop, &kernelTime, &userTime);
343 #endif
344 }