Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into mq
[simgrid.git] / src / xbt / xbt_os_time.c
1 /* xbt_os_time.c -- portable interface to time-related functions            */
2
3 /* Copyright (c) 2007-2023. 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 #include <unistd.h>
17
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
21 #endif
22
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>
36 #endif
37
38 double xbt_os_time(void)
39 {
40 #if HAVE_GETTIMEOFDAY
41   struct timeval tv;
42   gettimeofday(&tv, NULL);
43
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? */
48 }
49
50 void xbt_os_sleep(double sec)
51 {
52
53 #if HAVE_NANOSLEEP
54   struct timespec ts;
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;
60
61   timeout.tv_sec  = (long)sec;
62   timeout.tv_usec = (long)(sec - floor(sec)) * 1e6;
63
64   select(0, NULL, NULL, NULL, &timeout);
65 #endif
66 }
67
68 /* TSC (tick-level) timers are said to be unreliable on SMP hosts and thus  disabled in SDL source code */
69
70 /* @defgroup XBT_sysdep All system dependency
71  * @brief This section describes many macros/functions that can serve as  an OS abstraction.
72  */
73 struct s_xbt_os_timer {
74 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
75   struct timespec start;
76   struct timespec stop;
77   struct timespec elapse;
78 #elif HAVE_GETTIMEOFDAY
79   struct timeval start;
80   struct timeval stop;
81   struct timeval elapse;
82 #else
83   unsigned long int start;
84   unsigned long int stop;
85   unsigned long int elapse;
86 #endif
87 };
88
89 size_t xbt_os_timer_size(void)
90 {
91   return sizeof(struct s_xbt_os_timer);
92 }
93
94 xbt_os_timer_t xbt_os_timer_new(void)
95 {
96   return xbt_new0(struct s_xbt_os_timer, 1);
97 }
98
99 void xbt_os_timer_free(xbt_os_timer_t timer)
100 {
101   free(timer);
102 }
103
104 double xbt_os_timer_elapsed(const_xbt_os_timer_t timer)
105 {
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 )) /
112          1000000.0);
113 #else
114   return (double) timer->stop - (double) timer->start + (double) timer->elapse;
115 #endif
116 }
117
118 void xbt_os_walltimer_start(xbt_os_timer_t timer)
119 {
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);
128 #else
129   timer->elapse = 0;
130   timer->start = (unsigned long int) (time(NULL));
131 #endif
132 }
133
134 void xbt_os_walltimer_resume(xbt_os_timer_t timer)
135 {
136 #if HAVE_POSIX_GETTIME && defined (_POSIX_THREAD_CPUTIME)
137   timer->elapse.tv_sec += timer->stop.tv_sec - timer->start.tv_sec;
138
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);
145 #else
146   timer->elapse = timer->stop - timer->start;
147   timer->start = (unsigned long int) (time(NULL));
148 #endif
149 }
150
151 void xbt_os_walltimer_stop(xbt_os_timer_t timer)
152 {
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);
157 #else
158   timer->stop = (unsigned long int) (time(NULL));
159 #endif
160 }
161
162 void xbt_os_cputimer_start(xbt_os_timer_t timer)
163 {
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);
172 #else
173 # error The cpu timers of SimGrid do not seem to work on your platform.
174 #endif
175 }
176
177 void xbt_os_cputimer_resume(xbt_os_timer_t timer)
178 {
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);
187 #else
188 # error The cpu timers of SimGrid do not seem to work on your platform.
189 #endif
190 }
191
192 void xbt_os_cputimer_stop(xbt_os_timer_t timer)
193 {
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);
198 #else
199 # error The cpu timers of SimGrid do not seem to work on your platform.
200 #endif
201 }
202
203 void xbt_os_threadtimer_start(xbt_os_timer_t timer)
204 {
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);
222 #else
223 # error The thread timers of SimGrid do not seem to work on your platform.
224 #endif
225 }
226
227 void xbt_os_threadtimer_resume(xbt_os_timer_t timer)
228 {
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);
246 #else
247 # error The thread timers of SimGrid do not seem to work on your platform.
248 #endif
249 }
250
251 void xbt_os_threadtimer_stop(xbt_os_timer_t timer)
252 {
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);
264 #else
265 # error The thread timers of SimGrid do not seem to work on your platform.
266 #endif
267 }