1 /* xbt_os_time.c -- portable interface to time-related functions */
3 /* Copyright (c) 2007-2023. The SimGrid Team. All rights reserved. */
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. */
8 #include "src/internal_config.h"
9 #include "xbt/sysdep.h"
11 #include "xbt/xbt_os_time.h" /* this module */
12 #include <math.h> /* floor */
18 //Freebsd doesn't provide this clock_gettime flag yet, because it was added too recently (after 1993)
19 #if defined (CLOCK_PROF) && ! defined (CLOCK_PROCESS_CPUTIME_ID)
20 #define CLOCK_PROCESS_CPUTIME_ID CLOCK_PROF
23 #if defined(__APPLE__) && defined(__MACH__)
24 #include <sys/types.h>
25 #include <sys/sysctl.h>
26 #include <mach/mach_init.h>
27 #include <mach/mach_host.h>
28 #include <mach/mach_port.h>
29 #include <mach/mach_traps.h>
30 #include <mach/task_info.h>
31 #include <mach/thread_info.h>
32 #include <mach/thread_act.h>
33 #include <mach/vm_region.h>
34 #include <mach/vm_map.h>
35 #include <mach/task.h>
38 double xbt_os_time(void)
42 gettimeofday(&tv, NULL);
44 return (double)tv.tv_sec + (double)tv.tv_usec / 1e6;
45 #else /* no gettimeofday => poor resolution */
46 return (double) (time(NULL));
47 #endif /* HAVE_GETTIMEOFDAY? */
50 void xbt_os_sleep(double sec)
55 ts.tv_sec = (time_t)sec;
56 ts.tv_nsec = (long)((sec - floor(sec)) * 1e9);
57 nanosleep (&ts, NULL);
58 #else /* don't have nanosleep. Use select to sleep less than one second */
59 struct timeval timeout;
61 timeout.tv_sec = (long)sec;
62 timeout.tv_usec = (long)(sec - floor(sec)) * 1e6;
64 select(0, NULL, NULL, NULL, &timeout);
68 /* TSC (tick-level) timers are said to be unreliable on SMP hosts and thus disabled in SDL source code */
70 /* @defgroup XBT_sysdep All system dependency
71 * @brief This section describes many macros/functions that can serve as an OS abstraction.
73 struct s_xbt_os_timer {
74 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
75 struct timespec start;
77 struct timespec elapse;
78 #elif HAVE_GETTIMEOFDAY
81 struct timeval elapse;
83 unsigned long int start;
84 unsigned long int stop;
85 unsigned long int elapse;
89 size_t xbt_os_timer_size(void)
91 return sizeof(struct s_xbt_os_timer);
94 xbt_os_timer_t xbt_os_timer_new(void)
96 return xbt_new0(struct s_xbt_os_timer, 1);
99 void xbt_os_timer_free(xbt_os_timer_t timer)
104 double xbt_os_timer_elapsed(const_xbt_os_timer_t timer)
106 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
107 return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec) + ((double) timer->elapse.tv_sec ) +
108 ((((double) timer->stop.tv_nsec) - ((double) timer->start.tv_nsec) + ((double) timer->elapse.tv_nsec )) / 1e9);
109 #elif HAVE_GETTIMEOFDAY
110 return ((double) timer->stop.tv_sec) - ((double) timer->start.tv_sec) + ((double) timer->elapse.tv_sec ) +
111 ((((double) timer->stop.tv_usec) - ((double) timer->start.tv_usec) + ((double) timer->elapse.tv_usec )) /
114 return (double) timer->stop - (double) timer->start + (double) timer->elapse;
118 void xbt_os_walltimer_start(xbt_os_timer_t timer)
120 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
121 timer->elapse.tv_sec = 0;
122 timer->elapse.tv_nsec = 0;
123 clock_gettime(CLOCK_REALTIME, &(timer->start));
124 #elif HAVE_GETTIMEOFDAY
125 timer->elapse.tv_sec = 0;
126 timer->elapse.tv_usec = 0;
127 gettimeofday(&(timer->start), NULL);
130 timer->start = (unsigned long int) (time(NULL));
134 void xbt_os_walltimer_resume(xbt_os_timer_t timer)
136 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
137 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
139 timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
140 clock_gettime(CLOCK_REALTIME, &(timer->start));
141 #elif HAVE_GETTIMEOFDAY
142 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
143 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
144 gettimeofday(&(timer->start), NULL);
146 timer->elapse = timer->stop - timer->start;
147 timer->start = (unsigned long int) (time(NULL));
151 void xbt_os_walltimer_stop(xbt_os_timer_t timer)
153 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
154 clock_gettime(CLOCK_REALTIME, &(timer->stop));
155 #elif HAVE_GETTIMEOFDAY
156 gettimeofday(&(timer->stop), NULL);
158 timer->stop = (unsigned long int) (time(NULL));
162 void xbt_os_cputimer_start(xbt_os_timer_t timer)
164 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
165 timer->elapse.tv_sec = 0;
166 timer->elapse.tv_nsec = 0;
167 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
168 #elif HAVE_GETTIMEOFDAY //return time and not cputime in this case
169 timer->elapse.tv_sec = 0;
170 timer->elapse.tv_usec = 0;
171 gettimeofday(&(timer->start), NULL);
173 # error The cpu timers of SimGrid do not seem to work on your platform.
177 void xbt_os_cputimer_resume(xbt_os_timer_t timer)
179 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
180 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
181 timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
182 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->start));
183 #elif HAVE_GETTIMEOFDAY
184 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
185 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
186 gettimeofday(&(timer->start), NULL);
188 # error The cpu timers of SimGrid do not seem to work on your platform.
192 void xbt_os_cputimer_stop(xbt_os_timer_t timer)
194 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
195 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(timer->stop));
196 #elif HAVE_GETTIMEOFDAY
197 gettimeofday(&(timer->stop), NULL);
199 # error The cpu timers of SimGrid do not seem to work on your platform.
203 void xbt_os_threadtimer_start(xbt_os_timer_t timer)
205 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
206 timer->elapse.tv_sec = 0;
207 timer->elapse.tv_nsec = 0;
208 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
209 #elif HAVE_GETTIMEOFDAY && defined(__MACH__) && defined(__APPLE__)
210 timer->elapse.tv_sec = 0;
211 timer->elapse.tv_usec = 0;
212 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
213 thread_basic_info_data_t thi_data;
214 thread_basic_info_t thi = &thi_data;
215 thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
216 timer->start.tv_usec = thi->system_time.microseconds + thi->user_time.microseconds;
217 timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
218 #elif HAVE_GETTIMEOFDAY //return time and not cputime in this case
219 timer->elapse.tv_sec = 0;
220 timer->elapse.tv_usec = 0;
221 gettimeofday(&(timer->start), NULL);
223 # error The thread timers of SimGrid do not seem to work on your platform.
227 void xbt_os_threadtimer_resume(xbt_os_timer_t timer)
229 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
230 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
231 timer->elapse.tv_nsec += timer->stop.tv_nsec - timer->start.tv_nsec;
232 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->start));
233 #elif HAVE_GETTIMEOFDAY && defined(__MACH__) && defined(__APPLE__)
234 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
235 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
236 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
237 thread_basic_info_data_t thi_data;
238 thread_basic_info_t thi = &thi_data;
239 thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
240 timer->start.tv_usec = thi->system_time.microseconds + thi->user_time.microseconds;
241 timer->start.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
242 #elif HAVE_GETTIMEOFDAY
243 timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
244 timer->elapse.tv_usec += timer->stop.tv_usec - timer->start.tv_usec;
245 gettimeofday(&(timer->start), NULL);
247 # error The thread timers of SimGrid do not seem to work on your platform.
251 void xbt_os_threadtimer_stop(xbt_os_timer_t timer)
253 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
254 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &(timer->stop));
255 #elif HAVE_GETTIMEOFDAY && defined(__MACH__) && defined(__APPLE__)
256 mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
257 thread_basic_info_data_t thi_data;
258 thread_basic_info_t thi = &thi_data;
259 thread_info(mach_thread_self(), THREAD_BASIC_INFO, (thread_info_t)thi, &count);
260 timer->stop.tv_usec = thi->system_time.microseconds + thi->user_time.microseconds;
261 timer->stop.tv_sec = thi->system_time.seconds + thi->user_time.seconds;
262 #elif HAVE_GETTIMEOFDAY //if nothing else is available, return just time
263 gettimeofday(&(timer->stop), NULL);
265 # error The thread timers of SimGrid do not seem to work on your platform.