1 /* EINA - EFL data type library
2 * Copyright (C) 2008 Cedric Bail, Vincent Torri
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library;
16 * if not, see <http://www.gnu.org/licenses/>.
29 # include <sys/time.h>
31 # define WIN32_LEAN_AND_MEAN
33 # undef WIN32_LEAN_AND_MEAN
36 #include "eina_config.h"
37 #include "eina_private.h"
38 #include "eina_inlist.h"
39 #include "eina_error.h"
41 /* undefs EINA_ARG_NONULL() so NULL checks are not compiled out! */
42 #include "eina_safety_checks.h"
43 #include "eina_counter.h"
49 /*============================================================================*
51 *============================================================================*/
58 typedef struct timespec Eina_Nano_Time;
60 typedef LARGE_INTEGER Eina_Nano_Time;
63 typedef struct _Eina_Clock Eina_Clock;
86 _eina_counter_time_get(Eina_Nano_Time *tp)
88 # if defined(CLOCK_PROCESS_CPUTIME_ID)
89 return clock_gettime(CLOCK_PROCESS_CPUTIME_ID, tp);
90 # elif defined(CLOCK_PROF)
91 return clock_gettime(CLOCK_PROF, tp);
92 # elif defined(CLOCK_REALTIME)
93 return clock_gettime(CLOCK_REALTIME, tp);
97 if (gettimeofday(&tv, NULL))
100 tp->tv_sec = tv.tv_sec;
101 tp->tv_nsec = tv.tv_usec * 1000L;
107 static const char EINA_ERROR_COUNTER_WINDOWS_STR[] =
108 "Change your OS, you moron !";
109 static int EINA_ERROR_COUNTER_WINDOWS = 0;
110 static LARGE_INTEGER _eina_counter_frequency;
113 _eina_counter_time_get(Eina_Nano_Time *tp)
115 return QueryPerformanceCounter(tp);
120 _eina_counter_asiprintf(char *base, int *position, const char *format, ...)
127 tmp = realloc(base, sizeof (char) * (*position + size));
135 va_start(ap, format);
136 n = vsnprintf(result + *position, size, format, ap);
139 if (n > -1 && n < size)
141 /* If we always have glibc > 2.2, we could just return *position += n. */
142 *position += strlen(result + *position);
151 tmp = realloc(result, sizeof (char) * (*position + size));
163 /*============================================================================*
165 *============================================================================*/
169 * @brief Initialize the eina counter internal structure.
171 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
173 * This function shuts down the counter module set up by
174 * eina_counter_init(). It is called by eina_init().
176 * This function sets up the error module of Eina and only on Windows,
177 * it initializes the high precision timer. It also registers, only on
178 * Windows, the error #EINA_ERROR_COUNTER_WINDOWS. It is also called
179 * by eina_init(). It returns 0 on failure, otherwise it returns the
180 * number of times it has already been called.
185 eina_counter_init(void)
188 EINA_ERROR_COUNTER_WINDOWS = eina_error_msg_static_register(
189 EINA_ERROR_COUNTER_WINDOWS_STR);
190 if (!QueryPerformanceFrequency(&_eina_counter_frequency))
192 eina_error_set(EINA_ERROR_COUNTER_WINDOWS);
202 * @brief Shut down the counter module.
204 * @return #EINA_TRUE on success, #EINA_FALSE on failure.
206 * This function shuts down the counter module set up by
207 * eina_counter_init(). It is called by eina_shutdown().
209 * @see eina_shutdown()
212 eina_counter_shutdown(void)
217 /*============================================================================*
219 *============================================================================*/
222 eina_counter_new(const char *name)
224 Eina_Counter *counter;
227 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
229 length = strlen(name) + 1;
232 counter = calloc(1, sizeof (Eina_Counter) + length);
235 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
239 counter->name = (char *)(counter + 1);
240 memcpy((char *)counter->name, name, length);
246 eina_counter_free(Eina_Counter *counter)
248 EINA_SAFETY_ON_NULL_RETURN(counter);
250 while (counter->clocks)
252 Eina_Clock *clk = (Eina_Clock *)counter->clocks;
254 counter->clocks = eina_inlist_remove(counter->clocks, counter->clocks);
262 eina_counter_start(Eina_Counter *counter)
267 EINA_SAFETY_ON_NULL_RETURN(counter);
268 if (_eina_counter_time_get(&tp) != 0)
272 clk = calloc(1, sizeof (Eina_Clock));
275 eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
279 counter->clocks = eina_inlist_prepend(counter->clocks, EINA_INLIST_GET(clk));
281 clk->valid = EINA_FALSE;
286 eina_counter_stop(Eina_Counter *counter, int specimen)
291 EINA_SAFETY_ON_NULL_RETURN(counter);
292 if (_eina_counter_time_get(&tp) != 0)
295 clk = (Eina_Clock *)counter->clocks;
297 if (!clk || clk->valid == EINA_TRUE)
301 clk->specimen = specimen;
302 clk->valid = EINA_TRUE;
306 eina_counter_dump(Eina_Counter *counter)
312 EINA_SAFETY_ON_NULL_RETURN_VAL(counter, NULL);
314 result = _eina_counter_asiprintf(
317 "# specimen\texperiment time\tstarting time\tending time\n");
321 EINA_INLIST_REVERSE_FOREACH(counter->clocks, clk)
327 if (clk->valid == EINA_FALSE)
331 start = clk->start.tv_sec * 1000000000 + clk->start.tv_nsec;
332 end = clk->end.tv_sec * 1000000000 + clk->end.tv_nsec;
335 clk->start.tv_sec) * 1000000000 + clk->end.tv_nsec -
339 (long int)(((long long int)clk->start.QuadPart *
341 (long long int)_eina_counter_frequency.QuadPart);
343 (long int)(((long long int)clk->end.QuadPart *
345 (long long int)_eina_counter_frequency.QuadPart);
347 (long int)(((long long int)(clk->end.QuadPart -
348 clk->start.QuadPart) *
350 (long long int)_eina_counter_frequency.QuadPart);
353 result = _eina_counter_asiprintf(result, &position,
354 "%i\t%li\t%li\t%li\n",