diff options
Diffstat (limited to 'libraries/ecore/src/lib/ecore/ecore.c')
-rw-r--r-- | libraries/ecore/src/lib/ecore/ecore.c | 731 |
1 files changed, 731 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore/ecore.c b/libraries/ecore/src/lib/ecore/ecore.c new file mode 100644 index 0000000..99d79c1 --- /dev/null +++ b/libraries/ecore/src/lib/ecore/ecore.c | |||
@@ -0,0 +1,731 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif | ||
4 | |||
5 | #include <stdio.h> | ||
6 | #include <sys/types.h> | ||
7 | #include <sys/stat.h> | ||
8 | #include <fcntl.h> | ||
9 | #include <errno.h> | ||
10 | |||
11 | #ifndef _MSC_VER | ||
12 | # include <unistd.h> | ||
13 | #endif | ||
14 | |||
15 | #ifdef HAVE_LOCALE_H | ||
16 | # include <locale.h> | ||
17 | #endif | ||
18 | |||
19 | #ifdef HAVE_LANGINFO_H | ||
20 | # include <langinfo.h> | ||
21 | #endif | ||
22 | |||
23 | #ifdef HAVE_SYS_MMAN_H | ||
24 | # include <sys/mman.h> | ||
25 | #endif | ||
26 | |||
27 | #ifdef HAVE_EVIL | ||
28 | # include <Evil.h> | ||
29 | #endif | ||
30 | #include <Eina.h> | ||
31 | |||
32 | #include "Ecore.h" | ||
33 | #include "ecore_private.h" | ||
34 | |||
35 | #if HAVE_MALLINFO | ||
36 | #include <malloc.h> | ||
37 | |||
38 | static Ecore_Version _version = { VERS_MAJ, VERS_MIN, VERS_MIC, VERS_REV }; | ||
39 | EAPI Ecore_Version *ecore_version = &_version; | ||
40 | |||
41 | #define KEEP_MAX(Global, Local) \ | ||
42 | if (Global < (Local)) \ | ||
43 | Global = Local; | ||
44 | |||
45 | static Eina_Bool _ecore_memory_statistic(void *data); | ||
46 | static int _ecore_memory_max_total = 0; | ||
47 | static int _ecore_memory_max_free = 0; | ||
48 | static pid_t _ecore_memory_pid = 0; | ||
49 | #endif | ||
50 | |||
51 | static const char *_ecore_magic_string_get(Ecore_Magic m); | ||
52 | static int _ecore_init_count = 0; | ||
53 | int _ecore_log_dom = -1; | ||
54 | int _ecore_fps_debug = 0; | ||
55 | |||
56 | typedef struct _Ecore_Safe_Call Ecore_Safe_Call; | ||
57 | struct _Ecore_Safe_Call | ||
58 | { | ||
59 | union { | ||
60 | Ecore_Cb async; | ||
61 | Ecore_Data_Cb sync; | ||
62 | } cb; | ||
63 | void *data; | ||
64 | |||
65 | Eina_Lock m; | ||
66 | Eina_Condition c; | ||
67 | |||
68 | int current_id; | ||
69 | |||
70 | Eina_Bool sync : 1; | ||
71 | Eina_Bool suspend : 1; | ||
72 | }; | ||
73 | |||
74 | static void _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order); | ||
75 | static void _thread_safe_cleanup(void *data); | ||
76 | static void _thread_callback(void *data, | ||
77 | void *buffer, | ||
78 | unsigned int nbyte); | ||
79 | static Eina_List *_thread_cb = NULL; | ||
80 | static Ecore_Pipe *_thread_call = NULL; | ||
81 | static Eina_Lock _thread_safety; | ||
82 | |||
83 | static int _thread_loop = 0; | ||
84 | static Eina_Lock _thread_mutex; | ||
85 | static Eina_Condition _thread_cond; | ||
86 | static Eina_Lock _thread_feedback_mutex; | ||
87 | static Eina_Condition _thread_feedback_cond; | ||
88 | |||
89 | static Eina_Lock _thread_id_lock; | ||
90 | static int _thread_id = -1; | ||
91 | static int _thread_id_max = 0; | ||
92 | static int _thread_id_update = 0; | ||
93 | |||
94 | Eina_Lock _ecore_main_loop_lock; | ||
95 | int _ecore_main_lock_count; | ||
96 | |||
97 | /** OpenBSD does not define CODESET | ||
98 | * FIXME ?? | ||
99 | */ | ||
100 | |||
101 | #ifndef CODESET | ||
102 | # define CODESET "INVALID" | ||
103 | #endif | ||
104 | |||
105 | /** | ||
106 | * @addtogroup Ecore_Init_Group | ||
107 | * | ||
108 | * @{ | ||
109 | */ | ||
110 | |||
111 | /** | ||
112 | * Set up connections, signal handlers, sockets etc. | ||
113 | * @return 1 or greater on success, 0 otherwise | ||
114 | * | ||
115 | * This function sets up all singal handlers and the basic event loop. If it | ||
116 | * succeeds, 1 will be returned, otherwise 0 will be returned. | ||
117 | * | ||
118 | * @code | ||
119 | * #include <Ecore.h> | ||
120 | * | ||
121 | * int main(int argc, char **argv) | ||
122 | * { | ||
123 | * if (!ecore_init()) | ||
124 | * { | ||
125 | * printf("ERROR: Cannot init Ecore!\n"); | ||
126 | * return -1; | ||
127 | * } | ||
128 | * ecore_main_loop_begin(); | ||
129 | * ecore_shutdown(); | ||
130 | * } | ||
131 | * @endcode | ||
132 | */ | ||
133 | EAPI int | ||
134 | ecore_init(void) | ||
135 | { | ||
136 | if (++_ecore_init_count != 1) | ||
137 | return _ecore_init_count; | ||
138 | |||
139 | #ifdef HAVE_LOCALE_H | ||
140 | setlocale(LC_CTYPE, ""); | ||
141 | #endif | ||
142 | /* | ||
143 | if (strcmp(nl_langinfo(CODESET), "UTF-8")) | ||
144 | { | ||
145 | WRN("Not a utf8 locale!"); | ||
146 | } | ||
147 | */ | ||
148 | #ifdef HAVE_EVIL | ||
149 | if (!evil_init()) | ||
150 | return --_ecore_init_count; | ||
151 | #endif | ||
152 | if (!eina_init()) | ||
153 | goto shutdown_evil; | ||
154 | _ecore_log_dom = eina_log_domain_register("ecore", ECORE_DEFAULT_LOG_COLOR); | ||
155 | if (_ecore_log_dom < 0) | ||
156 | { | ||
157 | EINA_LOG_ERR("Ecore was unable to create a log domain."); | ||
158 | goto shutdown_log_dom; | ||
159 | } | ||
160 | if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1; | ||
161 | if (_ecore_fps_debug) _ecore_fps_debug_init(); | ||
162 | _ecore_main_loop_init(); | ||
163 | _ecore_signal_init(); | ||
164 | _ecore_thread_init(); | ||
165 | _ecore_exe_init(); | ||
166 | _ecore_glib_init(); | ||
167 | _ecore_job_init(); | ||
168 | _ecore_time_init(); | ||
169 | |||
170 | eina_lock_new(&_thread_safety); | ||
171 | eina_lock_new(&_thread_mutex); | ||
172 | eina_condition_new(&_thread_cond, &_thread_mutex); | ||
173 | eina_lock_new(&_thread_feedback_mutex); | ||
174 | eina_condition_new(&_thread_feedback_cond, &_thread_feedback_mutex); | ||
175 | _thread_call = ecore_pipe_add(_thread_callback, NULL); | ||
176 | eina_lock_new(&_thread_id_lock); | ||
177 | |||
178 | eina_lock_new(&_ecore_main_loop_lock); | ||
179 | |||
180 | #if HAVE_MALLINFO | ||
181 | if (getenv("ECORE_MEM_STAT")) | ||
182 | { | ||
183 | _ecore_memory_pid = getpid(); | ||
184 | ecore_animator_add(_ecore_memory_statistic, NULL); | ||
185 | } | ||
186 | #endif | ||
187 | |||
188 | #if defined(GLIB_INTEGRATION_ALWAYS) | ||
189 | if (_ecore_glib_always_integrate) ecore_main_loop_glib_integrate(); | ||
190 | #endif | ||
191 | |||
192 | return _ecore_init_count; | ||
193 | |||
194 | shutdown_log_dom: | ||
195 | eina_shutdown(); | ||
196 | shutdown_evil: | ||
197 | #ifdef HAVE_EVIL | ||
198 | evil_shutdown(); | ||
199 | #endif | ||
200 | return --_ecore_init_count; | ||
201 | } | ||
202 | |||
203 | /** | ||
204 | * Shut down connections, signal handlers sockets etc. | ||
205 | * | ||
206 | * This function shuts down all things set up in ecore_init() and cleans up all | ||
207 | * event queues, handlers, filters, timers, idlers, idle enterers/exiters | ||
208 | * etc. set up after ecore_init() was called. | ||
209 | * | ||
210 | * Do not call this function from any callback that may be called from the main | ||
211 | * loop, as the main loop will then fall over and not function properly. | ||
212 | */ | ||
213 | EAPI int | ||
214 | ecore_shutdown(void) | ||
215 | { | ||
216 | /* | ||
217 | * take a lock here because _ecore_event_shutdown() does callbacks | ||
218 | */ | ||
219 | _ecore_lock(); | ||
220 | if (--_ecore_init_count != 0) | ||
221 | goto unlock; | ||
222 | |||
223 | ecore_pipe_del(_thread_call); | ||
224 | eina_lock_free(&_thread_safety); | ||
225 | eina_condition_free(&_thread_cond); | ||
226 | eina_lock_free(&_thread_mutex); | ||
227 | eina_condition_free(&_thread_feedback_cond); | ||
228 | eina_lock_free(&_thread_feedback_mutex); | ||
229 | eina_lock_free(&_thread_id_lock); | ||
230 | |||
231 | if (_ecore_fps_debug) _ecore_fps_debug_shutdown(); | ||
232 | _ecore_poller_shutdown(); | ||
233 | _ecore_animator_shutdown(); | ||
234 | _ecore_glib_shutdown(); | ||
235 | _ecore_job_shutdown(); | ||
236 | _ecore_thread_shutdown(); | ||
237 | _ecore_exe_shutdown(); | ||
238 | _ecore_idle_enterer_shutdown(); | ||
239 | _ecore_idle_exiter_shutdown(); | ||
240 | _ecore_idler_shutdown(); | ||
241 | _ecore_timer_shutdown(); | ||
242 | _ecore_event_shutdown(); | ||
243 | _ecore_main_shutdown(); | ||
244 | _ecore_signal_shutdown(); | ||
245 | _ecore_main_loop_shutdown(); | ||
246 | |||
247 | #if HAVE_MALLINFO | ||
248 | if (getenv("ECORE_MEM_STAT")) | ||
249 | { | ||
250 | _ecore_memory_statistic(NULL); | ||
251 | |||
252 | ERR("[%i] Memory MAX total: %i, free: %i", | ||
253 | _ecore_memory_pid, | ||
254 | _ecore_memory_max_total, | ||
255 | _ecore_memory_max_free); | ||
256 | } | ||
257 | #endif | ||
258 | |||
259 | eina_log_domain_unregister(_ecore_log_dom); | ||
260 | _ecore_log_dom = -1; | ||
261 | eina_shutdown(); | ||
262 | #ifdef HAVE_EVIL | ||
263 | evil_shutdown(); | ||
264 | #endif | ||
265 | unlock: | ||
266 | _ecore_unlock(); | ||
267 | |||
268 | return _ecore_init_count; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * @} | ||
273 | */ | ||
274 | |||
275 | static int wakeup = 42; | ||
276 | |||
277 | EAPI void | ||
278 | ecore_main_loop_thread_safe_call_async(Ecore_Cb callback, | ||
279 | void *data) | ||
280 | { | ||
281 | Ecore_Safe_Call *order; | ||
282 | |||
283 | if (!callback) return; | ||
284 | |||
285 | if (eina_main_loop_is()) | ||
286 | { | ||
287 | callback(data); | ||
288 | return; | ||
289 | } | ||
290 | |||
291 | order = malloc(sizeof (Ecore_Safe_Call)); | ||
292 | if (!order) return; | ||
293 | |||
294 | order->cb.async = callback; | ||
295 | order->data = data; | ||
296 | order->sync = EINA_FALSE; | ||
297 | order->suspend = EINA_FALSE; | ||
298 | |||
299 | _ecore_main_loop_thread_safe_call(order); | ||
300 | } | ||
301 | |||
302 | EAPI void * | ||
303 | ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback, | ||
304 | void *data) | ||
305 | { | ||
306 | Ecore_Safe_Call *order; | ||
307 | void *ret; | ||
308 | |||
309 | if (!callback) return NULL; | ||
310 | |||
311 | if (eina_main_loop_is()) | ||
312 | { | ||
313 | return callback(data); | ||
314 | } | ||
315 | |||
316 | order = malloc(sizeof (Ecore_Safe_Call)); | ||
317 | if (!order) return NULL; | ||
318 | |||
319 | order->cb.sync = callback; | ||
320 | order->data = data; | ||
321 | eina_lock_new(&order->m); | ||
322 | eina_condition_new(&order->c, &order->m); | ||
323 | order->sync = EINA_TRUE; | ||
324 | order->suspend = EINA_FALSE; | ||
325 | |||
326 | _ecore_main_loop_thread_safe_call(order); | ||
327 | |||
328 | eina_lock_take(&order->m); | ||
329 | eina_condition_wait(&order->c); | ||
330 | eina_lock_release(&order->m); | ||
331 | |||
332 | ret = order->data; | ||
333 | |||
334 | order->sync = EINA_FALSE; | ||
335 | order->cb.async = _thread_safe_cleanup; | ||
336 | order->data = order; | ||
337 | |||
338 | _ecore_main_loop_thread_safe_call(order); | ||
339 | |||
340 | return ret; | ||
341 | } | ||
342 | |||
343 | EAPI int | ||
344 | ecore_thread_main_loop_begin(void) | ||
345 | { | ||
346 | Ecore_Safe_Call *order; | ||
347 | |||
348 | if (eina_main_loop_is()) | ||
349 | { | ||
350 | return ++_thread_loop; | ||
351 | } | ||
352 | |||
353 | order = malloc(sizeof (Ecore_Safe_Call)); | ||
354 | if (!order) return -1; | ||
355 | |||
356 | eina_lock_take(&_thread_id_lock); | ||
357 | order->current_id = ++_thread_id_max; | ||
358 | if (order->current_id < 0) | ||
359 | { | ||
360 | _thread_id_max = 0; | ||
361 | order->current_id = ++_thread_id_max; | ||
362 | } | ||
363 | eina_lock_release(&_thread_id_lock); | ||
364 | |||
365 | eina_lock_new(&order->m); | ||
366 | eina_condition_new(&order->c, &order->m); | ||
367 | order->suspend = EINA_TRUE; | ||
368 | |||
369 | _ecore_main_loop_thread_safe_call(order); | ||
370 | |||
371 | eina_lock_take(&order->m); | ||
372 | while (order->current_id != _thread_id) | ||
373 | eina_condition_wait(&order->c); | ||
374 | eina_lock_release(&order->m); | ||
375 | |||
376 | eina_main_loop_define(); | ||
377 | |||
378 | _thread_loop = 1; | ||
379 | |||
380 | return EINA_TRUE; | ||
381 | } | ||
382 | |||
383 | EAPI int | ||
384 | ecore_thread_main_loop_end(void) | ||
385 | { | ||
386 | int current_id; | ||
387 | |||
388 | if (_thread_loop == 0) | ||
389 | { | ||
390 | ERR("the main loop is not locked ! No matching call to ecore_thread_main_loop_begin()."); | ||
391 | return -1; | ||
392 | } | ||
393 | |||
394 | /* until we unlock the main loop, this thread has the main loop id */ | ||
395 | if (!eina_main_loop_is()) | ||
396 | { | ||
397 | ERR("Not in a locked thread !"); | ||
398 | return -1; | ||
399 | } | ||
400 | |||
401 | _thread_loop--; | ||
402 | if (_thread_loop > 0) | ||
403 | return _thread_loop; | ||
404 | |||
405 | current_id = _thread_id; | ||
406 | |||
407 | eina_lock_take(&_thread_mutex); | ||
408 | _thread_id_update = _thread_id; | ||
409 | eina_condition_broadcast(&_thread_cond); | ||
410 | eina_lock_release(&_thread_mutex); | ||
411 | |||
412 | eina_lock_take(&_thread_feedback_mutex); | ||
413 | while (current_id == _thread_id && _thread_id != -1) | ||
414 | eina_condition_wait(&_thread_feedback_cond); | ||
415 | eina_lock_release(&_thread_feedback_mutex); | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | |||
420 | EAPI void | ||
421 | ecore_print_warning(const char *function, | ||
422 | const char *sparam) | ||
423 | { | ||
424 | WRN("***** Developer Warning ***** :\n" | ||
425 | "\tThis program is calling:\n\n" | ||
426 | "\t%s();\n\n" | ||
427 | "\tWith the parameter:\n\n" | ||
428 | "\t%s\n\n" | ||
429 | "\tbeing NULL. Please fix your program.", function, sparam); | ||
430 | if (getenv("ECORE_ERROR_ABORT")) abort(); | ||
431 | } | ||
432 | |||
433 | EAPI void | ||
434 | _ecore_magic_fail(const void *d, | ||
435 | Ecore_Magic m, | ||
436 | Ecore_Magic req_m, | ||
437 | const char *fname) | ||
438 | { | ||
439 | ERR("\n" | ||
440 | "*** ECORE ERROR: Ecore Magic Check Failed!!!\n" | ||
441 | "*** IN FUNCTION: %s()", fname); | ||
442 | if (!d) | ||
443 | ERR(" Input handle pointer is NULL!"); | ||
444 | else if (m == ECORE_MAGIC_NONE) | ||
445 | ERR(" Input handle has already been freed!"); | ||
446 | else if (m != req_m) | ||
447 | ERR(" Input handle is wrong type\n" | ||
448 | " Expected: %08x - %s\n" | ||
449 | " Supplied: %08x - %s", | ||
450 | (unsigned int)req_m, _ecore_magic_string_get(req_m), | ||
451 | (unsigned int)m, _ecore_magic_string_get(m)); | ||
452 | ERR("*** NAUGHTY PROGRAMMER!!!\n" | ||
453 | "*** SPANK SPANK SPANK!!!\n" | ||
454 | "*** Now go fix your code. Tut tut tut!"); | ||
455 | if (getenv("ECORE_ERROR_ABORT")) abort(); | ||
456 | } | ||
457 | |||
458 | static const char * | ||
459 | _ecore_magic_string_get(Ecore_Magic m) | ||
460 | { | ||
461 | switch (m) | ||
462 | { | ||
463 | case ECORE_MAGIC_NONE: | ||
464 | return "None (Freed Object)"; | ||
465 | break; | ||
466 | |||
467 | case ECORE_MAGIC_EXE: | ||
468 | return "Ecore_Exe (Executable)"; | ||
469 | break; | ||
470 | |||
471 | case ECORE_MAGIC_TIMER: | ||
472 | return "Ecore_Timer (Timer)"; | ||
473 | break; | ||
474 | |||
475 | case ECORE_MAGIC_IDLER: | ||
476 | return "Ecore_Idler (Idler)"; | ||
477 | break; | ||
478 | |||
479 | case ECORE_MAGIC_IDLE_ENTERER: | ||
480 | return "Ecore_Idle_Enterer (Idler Enterer)"; | ||
481 | break; | ||
482 | |||
483 | case ECORE_MAGIC_IDLE_EXITER: | ||
484 | return "Ecore_Idle_Exiter (Idler Exiter)"; | ||
485 | break; | ||
486 | |||
487 | case ECORE_MAGIC_FD_HANDLER: | ||
488 | return "Ecore_Fd_Handler (Fd Handler)"; | ||
489 | break; | ||
490 | |||
491 | case ECORE_MAGIC_WIN32_HANDLER: | ||
492 | return "Ecore_Win32_Handler (Win32 Handler)"; | ||
493 | break; | ||
494 | |||
495 | case ECORE_MAGIC_EVENT_HANDLER: | ||
496 | return "Ecore_Event_Handler (Event Handler)"; | ||
497 | break; | ||
498 | |||
499 | case ECORE_MAGIC_EVENT: | ||
500 | return "Ecore_Event (Event)"; | ||
501 | break; | ||
502 | |||
503 | default: | ||
504 | return "<UNKNOWN>"; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | /* fps debug calls - for debugging how much time your app actually spends */ | ||
509 | /* "running" (and the inverse being time spent running)... this does not */ | ||
510 | /* account for other apps and multitasking... */ | ||
511 | |||
512 | static int _ecore_fps_debug_init_count = 0; | ||
513 | static int _ecore_fps_debug_fd = -1; | ||
514 | unsigned int *_ecore_fps_runtime_mmap = NULL; | ||
515 | |||
516 | void | ||
517 | _ecore_fps_debug_init(void) | ||
518 | { | ||
519 | char buf[PATH_MAX]; | ||
520 | const char *tmp; | ||
521 | int pid; | ||
522 | |||
523 | _ecore_fps_debug_init_count++; | ||
524 | if (_ecore_fps_debug_init_count > 1) return; | ||
525 | |||
526 | #ifndef HAVE_EVIL | ||
527 | tmp = "/tmp"; | ||
528 | #else | ||
529 | tmp = evil_tmpdir_get (); | ||
530 | #endif /* HAVE_EVIL */ | ||
531 | pid = (int)getpid(); | ||
532 | snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid); | ||
533 | _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644); | ||
534 | if (_ecore_fps_debug_fd < 0) | ||
535 | { | ||
536 | unlink(buf); | ||
537 | _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644); | ||
538 | } | ||
539 | if (_ecore_fps_debug_fd >= 0) | ||
540 | { | ||
541 | unsigned int zero = 0; | ||
542 | char *buf2 = (char *)&zero; | ||
543 | ssize_t todo = sizeof(unsigned int); | ||
544 | |||
545 | while (todo > 0) | ||
546 | { | ||
547 | ssize_t r = write(_ecore_fps_debug_fd, buf2, todo); | ||
548 | if (r > 0) | ||
549 | { | ||
550 | todo -= r; | ||
551 | buf2 += r; | ||
552 | } | ||
553 | else if ((r < 0) && (errno == EINTR)) | ||
554 | continue; | ||
555 | else | ||
556 | { | ||
557 | ERR("could not write to file '%s' fd %d: %s", | ||
558 | tmp, _ecore_fps_debug_fd, strerror(errno)); | ||
559 | close(_ecore_fps_debug_fd); | ||
560 | _ecore_fps_debug_fd = -1; | ||
561 | return; | ||
562 | } | ||
563 | } | ||
564 | _ecore_fps_runtime_mmap = mmap(NULL, sizeof(unsigned int), | ||
565 | PROT_READ | PROT_WRITE, | ||
566 | MAP_SHARED, | ||
567 | _ecore_fps_debug_fd, 0); | ||
568 | if (_ecore_fps_runtime_mmap == MAP_FAILED) | ||
569 | _ecore_fps_runtime_mmap = NULL; | ||
570 | } | ||
571 | } | ||
572 | |||
573 | void | ||
574 | _ecore_fps_debug_shutdown(void) | ||
575 | { | ||
576 | _ecore_fps_debug_init_count--; | ||
577 | if (_ecore_fps_debug_init_count > 0) return; | ||
578 | if (_ecore_fps_debug_fd >= 0) | ||
579 | { | ||
580 | char buf[4096]; | ||
581 | const char *tmp; | ||
582 | int pid; | ||
583 | |||
584 | #ifndef HAVE_EVIL | ||
585 | tmp = "/tmp"; | ||
586 | #else | ||
587 | tmp = (char *)evil_tmpdir_get (); | ||
588 | #endif /* HAVE_EVIL */ | ||
589 | pid = (int)getpid(); | ||
590 | snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid); | ||
591 | unlink(buf); | ||
592 | if (_ecore_fps_runtime_mmap) | ||
593 | { | ||
594 | munmap(_ecore_fps_runtime_mmap, sizeof(int)); | ||
595 | _ecore_fps_runtime_mmap = NULL; | ||
596 | } | ||
597 | close(_ecore_fps_debug_fd); | ||
598 | _ecore_fps_debug_fd = -1; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | void | ||
603 | _ecore_fps_debug_runtime_add(double t) | ||
604 | { | ||
605 | if ((_ecore_fps_debug_fd >= 0) && | ||
606 | (_ecore_fps_runtime_mmap)) | ||
607 | { | ||
608 | unsigned int tm; | ||
609 | |||
610 | tm = (unsigned int)(t * 1000000.0); | ||
611 | /* i know its not 100% theoretically guaranteed, but i'd say a write */ | ||
612 | /* of an int could be considered atomic for all practical purposes */ | ||
613 | /* oh and since this is cumulative, 1 second = 1,000,000 ticks, so */ | ||
614 | /* this can run for about 4294 seconds becore looping. if you are */ | ||
615 | /* doing performance testing in one run for over an hour... well */ | ||
616 | /* time to restart or handle a loop condition :) */ | ||
617 | *(_ecore_fps_runtime_mmap) += tm; | ||
618 | } | ||
619 | } | ||
620 | |||
621 | #if HAVE_MALLINFO | ||
622 | static Eina_Bool | ||
623 | _ecore_memory_statistic(__UNUSED__ void *data) | ||
624 | { | ||
625 | struct mallinfo mi; | ||
626 | static int uordblks = 0; | ||
627 | static int fordblks = 0; | ||
628 | Eina_Bool changed = EINA_FALSE; | ||
629 | |||
630 | mi = mallinfo(); | ||
631 | |||
632 | #define HAS_CHANGED(Global, Local) \ | ||
633 | if (Global != Local) \ | ||
634 | { \ | ||
635 | Global = Local; \ | ||
636 | changed = EINA_TRUE; \ | ||
637 | } | ||
638 | |||
639 | HAS_CHANGED(uordblks, mi.uordblks); | ||
640 | HAS_CHANGED(fordblks, mi.fordblks); | ||
641 | |||
642 | if (changed) | ||
643 | ERR("[%i] Memory total: %i, free: %i", | ||
644 | _ecore_memory_pid, | ||
645 | mi.uordblks, | ||
646 | mi.fordblks); | ||
647 | |||
648 | KEEP_MAX(_ecore_memory_max_total, mi.uordblks); | ||
649 | KEEP_MAX(_ecore_memory_max_free, mi.fordblks); | ||
650 | |||
651 | return ECORE_CALLBACK_RENEW; | ||
652 | } | ||
653 | |||
654 | #endif | ||
655 | |||
656 | static void | ||
657 | _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order) | ||
658 | { | ||
659 | Eina_Bool count; | ||
660 | |||
661 | eina_lock_take(&_thread_safety); | ||
662 | |||
663 | count = _thread_cb ? 0 : 1; | ||
664 | _thread_cb = eina_list_append(_thread_cb, order); | ||
665 | if (count) ecore_pipe_write(_thread_call, &wakeup, sizeof (int)); | ||
666 | |||
667 | eina_lock_release(&_thread_safety); | ||
668 | } | ||
669 | |||
670 | static void | ||
671 | _thread_safe_cleanup(void *data) | ||
672 | { | ||
673 | Ecore_Safe_Call *call = data; | ||
674 | |||
675 | eina_condition_free(&call->c); | ||
676 | eina_lock_free(&call->m); | ||
677 | } | ||
678 | |||
679 | static void | ||
680 | _thread_callback(void *data __UNUSED__, | ||
681 | void *buffer __UNUSED__, | ||
682 | unsigned int nbyte __UNUSED__) | ||
683 | { | ||
684 | Ecore_Safe_Call *call; | ||
685 | Eina_List *callback; | ||
686 | |||
687 | eina_lock_take(&_thread_safety); | ||
688 | callback = _thread_cb; | ||
689 | _thread_cb = NULL; | ||
690 | eina_lock_release(&_thread_safety); | ||
691 | |||
692 | EINA_LIST_FREE(callback, call) | ||
693 | { | ||
694 | if (call->suspend) | ||
695 | { | ||
696 | eina_lock_take(&_thread_mutex); | ||
697 | |||
698 | eina_lock_take(&call->m); | ||
699 | _thread_id = call->current_id; | ||
700 | eina_condition_broadcast(&call->c); | ||
701 | eina_lock_release(&call->m); | ||
702 | |||
703 | while (_thread_id_update != _thread_id) | ||
704 | eina_condition_wait(&_thread_cond); | ||
705 | eina_lock_release(&_thread_mutex); | ||
706 | |||
707 | eina_main_loop_define(); | ||
708 | |||
709 | eina_lock_take(&_thread_feedback_mutex); | ||
710 | |||
711 | _thread_id = -1; | ||
712 | |||
713 | eina_condition_broadcast(&_thread_feedback_cond); | ||
714 | eina_lock_release(&_thread_feedback_mutex); | ||
715 | |||
716 | _thread_safe_cleanup(call); | ||
717 | free(call); | ||
718 | } | ||
719 | else if (call->sync) | ||
720 | { | ||
721 | call->data = call->cb.sync(call->data); | ||
722 | eina_condition_broadcast(&call->c); | ||
723 | } | ||
724 | else | ||
725 | { | ||
726 | call->cb.async(call->data); | ||
727 | free(call); | ||
728 | } | ||
729 | } | ||
730 | } | ||
731 | |||