20 #ifdef HAVE_LANGINFO_H
21 # include <langinfo.h>
24 #ifdef HAVE_SYS_MMAN_H
25 # include <sys/mman.h>
34 #include "ecore_private.h"
39 static Ecore_Version _version = { VERS_MAJ, VERS_MIN, VERS_MIC, VERS_REV };
40 EAPI Ecore_Version *ecore_version = &_version;
42 #define KEEP_MAX(Global, Local) \
43 if (Global < (Local)) \
46 static Eina_Bool _ecore_memory_statistic(void *data);
47 static int _ecore_memory_max_total = 0;
48 static int _ecore_memory_max_free = 0;
49 static pid_t _ecore_memory_pid = 0;
52 static const char *_ecore_magic_string_get(Ecore_Magic m);
53 static int _ecore_init_count = 0;
54 int _ecore_log_dom = -1;
55 int _ecore_fps_debug = 0;
57 typedef struct _Ecore_Safe_Call Ecore_Safe_Call;
58 struct _Ecore_Safe_Call
72 Eina_Bool suspend : 1;
75 static void _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order);
76 static void _thread_safe_cleanup(void *data);
77 static void _thread_callback(void *data,
80 static Eina_List *_thread_cb = NULL;
81 static Ecore_Pipe *_thread_call = NULL;
82 static Eina_Lock _thread_safety;
84 static int _thread_loop = 0;
85 static Eina_Lock _thread_mutex;
86 static Eina_Condition _thread_cond;
87 static Eina_Lock _thread_feedback_mutex;
88 static Eina_Condition _thread_feedback_cond;
90 static Eina_Lock _thread_id_lock;
91 static int _thread_id = -1;
92 static int _thread_id_max = 0;
93 static int _thread_id_update = 0;
95 Eina_Lock _ecore_main_loop_lock;
96 int _ecore_main_lock_count;
98 /** OpenBSD does not define CODESET
103 # define CODESET "INVALID"
107 * @addtogroup Ecore_Init_Group
113 * Set up connections, signal handlers, sockets etc.
114 * @return 1 or greater on success, 0 otherwise
116 * This function sets up all singal handlers and the basic event loop. If it
117 * succeeds, 1 will be returned, otherwise 0 will be returned.
122 * int main(int argc, char **argv)
126 * printf("ERROR: Cannot init Ecore!\n");
129 * ecore_main_loop_begin();
137 if (++_ecore_init_count != 1)
138 return _ecore_init_count;
141 setlocale(LC_CTYPE, "");
144 if (strcmp(nl_langinfo(CODESET), "UTF-8"))
146 WRN("Not a utf8 locale!");
151 return --_ecore_init_count;
155 _ecore_log_dom = eina_log_domain_register("ecore", ECORE_DEFAULT_LOG_COLOR);
156 if (_ecore_log_dom < 0)
158 EINA_LOG_ERR("Ecore was unable to create a log domain.");
159 goto shutdown_log_dom;
161 if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1;
162 if (_ecore_fps_debug) _ecore_fps_debug_init();
163 if (!ecore_mempool_init()) goto shutdown_mempool;
164 _ecore_main_loop_init();
165 _ecore_signal_init();
169 _ecore_thread_init();
174 eina_lock_new(&_thread_mutex);
175 eina_condition_new(&_thread_cond, &_thread_mutex);
176 eina_lock_new(&_thread_feedback_mutex);
177 eina_condition_new(&_thread_feedback_cond, &_thread_feedback_mutex);
180 _thread_call = ecore_pipe_add(_thread_callback, NULL);
181 eina_lock_new(&_thread_safety);
184 eina_lock_new(&_thread_id_lock);
186 eina_lock_new(&_ecore_main_loop_lock);
189 if (getenv("ECORE_MEM_STAT"))
191 _ecore_memory_pid = getpid();
192 ecore_animator_add(_ecore_memory_statistic, NULL);
196 #if defined(GLIB_INTEGRATION_ALWAYS)
197 if (_ecore_glib_always_integrate) ecore_main_loop_glib_integrate();
200 return _ecore_init_count;
203 ecore_mempool_shutdown();
210 return --_ecore_init_count;
214 * Shut down connections, signal handlers sockets etc.
216 * @return 0 if ecore shuts down, greater than 0 otherwise.
217 * This function shuts down all things set up in ecore_init() and cleans up all
218 * event queues, handlers, filters, timers, idlers, idle enterers/exiters
219 * etc. set up after ecore_init() was called.
221 * Do not call this function from any callback that may be called from the main
222 * loop, as the main loop will then fall over and not function properly.
228 * take a lock here because _ecore_event_shutdown() does callbacks
231 if (_ecore_init_count <= 0)
233 ERR("Init count not greater than 0 in shutdown.");
237 if (--_ecore_init_count != 0)
240 /* this looks horrible - a hack for now, but something to note. as
241 * we delete the _thread_call pipe a thread COULD be doing
242 * ecore_pipe_write() or what not to it at the same time - we
243 * must ensure all possible users of this _thread_call are finished
244 * and exited before we delete it here */
246 * ok - this causes other valgrind complaints regarding glib aquiring
247 * locks internally. so fix bug a or bug b. let's leave the original
248 * bug in then and leave this as a note for now
252 ecore_pipe_wait(p, 1, 0.1);
254 eina_lock_free(&_thread_safety);
256 eina_condition_free(&_thread_cond);
257 eina_lock_free(&_thread_mutex);
258 eina_condition_free(&_thread_feedback_cond);
259 eina_lock_free(&_thread_feedback_mutex);
260 eina_lock_free(&_thread_id_lock);
262 if (_ecore_fps_debug) _ecore_fps_debug_shutdown();
263 _ecore_poller_shutdown();
264 _ecore_animator_shutdown();
265 _ecore_glib_shutdown();
266 _ecore_job_shutdown();
267 _ecore_thread_shutdown();
269 _ecore_exe_shutdown();
271 _ecore_idle_enterer_shutdown();
272 _ecore_idle_exiter_shutdown();
273 _ecore_idler_shutdown();
274 _ecore_timer_shutdown();
275 _ecore_event_shutdown();
276 _ecore_main_shutdown();
277 _ecore_signal_shutdown();
278 _ecore_main_loop_shutdown();
281 if (getenv("ECORE_MEM_STAT"))
283 _ecore_memory_statistic(NULL);
285 ERR("[%i] Memory MAX total: %i, free: %i",
287 _ecore_memory_max_total,
288 _ecore_memory_max_free);
291 ecore_mempool_shutdown();
292 eina_log_domain_unregister(_ecore_log_dom);
301 return _ecore_init_count;
308 static int wakeup = 42;
311 ecore_main_loop_thread_safe_call_async(Ecore_Cb callback,
314 Ecore_Safe_Call *order;
316 if (!callback) return;
318 if (eina_main_loop_is())
324 order = malloc(sizeof (Ecore_Safe_Call));
327 order->cb.async = callback;
329 order->sync = EINA_FALSE;
330 order->suspend = EINA_FALSE;
332 _ecore_main_loop_thread_safe_call(order);
336 ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback,
339 Ecore_Safe_Call *order;
342 if (!callback) return NULL;
344 if (eina_main_loop_is())
346 return callback(data);
349 order = malloc(sizeof (Ecore_Safe_Call));
350 if (!order) return NULL;
352 order->cb.sync = callback;
354 eina_lock_new(&order->m);
355 eina_condition_new(&order->c, &order->m);
356 order->sync = EINA_TRUE;
357 order->suspend = EINA_FALSE;
359 _ecore_main_loop_thread_safe_call(order);
361 eina_lock_take(&order->m);
362 eina_condition_wait(&order->c);
363 eina_lock_release(&order->m);
367 order->sync = EINA_FALSE;
368 order->cb.async = _thread_safe_cleanup;
371 _ecore_main_loop_thread_safe_call(order);
377 ecore_thread_main_loop_begin(void)
379 Ecore_Safe_Call *order;
381 if (eina_main_loop_is())
383 return ++_thread_loop;
386 order = malloc(sizeof (Ecore_Safe_Call));
387 if (!order) return -1;
389 eina_lock_take(&_thread_id_lock);
390 order->current_id = ++_thread_id_max;
391 if (order->current_id < 0)
394 order->current_id = ++_thread_id_max;
396 eina_lock_release(&_thread_id_lock);
398 eina_lock_new(&order->m);
399 eina_condition_new(&order->c, &order->m);
400 order->suspend = EINA_TRUE;
402 _ecore_main_loop_thread_safe_call(order);
404 eina_lock_take(&order->m);
405 while (order->current_id != _thread_id)
406 eina_condition_wait(&order->c);
407 eina_lock_release(&order->m);
409 eina_main_loop_define();
417 ecore_thread_main_loop_end(void)
421 if (_thread_loop == 0)
423 ERR("the main loop is not locked ! No matching call to ecore_thread_main_loop_begin().");
427 /* until we unlock the main loop, this thread has the main loop id */
428 if (!eina_main_loop_is())
430 ERR("Not in a locked thread !");
435 if (_thread_loop > 0)
438 current_id = _thread_id;
440 eina_lock_take(&_thread_mutex);
441 _thread_id_update = _thread_id;
442 eina_condition_broadcast(&_thread_cond);
443 eina_lock_release(&_thread_mutex);
445 eina_lock_take(&_thread_feedback_mutex);
446 while (current_id == _thread_id && _thread_id != -1)
447 eina_condition_wait(&_thread_feedback_cond);
448 eina_lock_release(&_thread_feedback_mutex);
454 ecore_print_warning(const char *function __UNUSED__,
455 const char *sparam __UNUSED__)
457 WRN("***** Developer Warning ***** :\n"
458 "\tThis program is calling:\n\n"
460 "\tWith the parameter:\n\n"
462 "\tbeing NULL. Please fix your program.", function, sparam);
463 if (getenv("ECORE_ERROR_ABORT")) abort();
467 _ecore_magic_fail(const void *d,
470 const char *fname __UNUSED__)
473 "*** ECORE ERROR: Ecore Magic Check Failed!!!\n"
474 "*** IN FUNCTION: %s()", fname);
476 ERR(" Input handle pointer is NULL!");
477 else if (m == ECORE_MAGIC_NONE)
478 ERR(" Input handle has already been freed!");
480 ERR(" Input handle is wrong type\n"
481 " Expected: %08x - %s\n"
482 " Supplied: %08x - %s",
483 (unsigned int)req_m, _ecore_magic_string_get(req_m),
484 (unsigned int)m, _ecore_magic_string_get(m));
485 ERR("*** NAUGHTY PROGRAMMER!!!\n"
486 "*** SPANK SPANK SPANK!!!\n"
487 "*** Now go fix your code. Tut tut tut!");
488 if (getenv("ECORE_ERROR_ABORT")) abort();
492 _ecore_magic_string_get(Ecore_Magic m)
496 case ECORE_MAGIC_NONE:
497 return "None (Freed Object)";
500 case ECORE_MAGIC_EXE:
501 return "Ecore_Exe (Executable)";
504 case ECORE_MAGIC_TIMER:
505 return "Ecore_Timer (Timer)";
508 case ECORE_MAGIC_IDLER:
509 return "Ecore_Idler (Idler)";
512 case ECORE_MAGIC_IDLE_ENTERER:
513 return "Ecore_Idle_Enterer (Idler Enterer)";
516 case ECORE_MAGIC_IDLE_EXITER:
517 return "Ecore_Idle_Exiter (Idler Exiter)";
520 case ECORE_MAGIC_FD_HANDLER:
521 return "Ecore_Fd_Handler (Fd Handler)";
524 case ECORE_MAGIC_WIN32_HANDLER:
525 return "Ecore_Win32_Handler (Win32 Handler)";
528 case ECORE_MAGIC_EVENT_HANDLER:
529 return "Ecore_Event_Handler (Event Handler)";
532 case ECORE_MAGIC_EVENT:
533 return "Ecore_Event (Event)";
541 /* fps debug calls - for debugging how much time your app actually spends */
542 /* "running" (and the inverse being time spent running)... this does not */
543 /* account for other apps and multitasking... */
545 static int _ecore_fps_debug_init_count = 0;
546 static int _ecore_fps_debug_fd = -1;
547 unsigned int *_ecore_fps_runtime_mmap = NULL;
550 _ecore_fps_debug_init(void)
556 _ecore_fps_debug_init_count++;
557 if (_ecore_fps_debug_init_count > 1) return;
562 tmp = evil_tmpdir_get ();
563 #endif /* HAVE_EVIL */
565 snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid);
566 _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
567 if (_ecore_fps_debug_fd < 0)
570 _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
572 if (_ecore_fps_debug_fd >= 0)
574 unsigned int zero = 0;
575 char *buf2 = (char *)&zero;
576 ssize_t todo = sizeof(unsigned int);
580 ssize_t r = write(_ecore_fps_debug_fd, buf2, todo);
586 else if ((r < 0) && (errno == EINTR))
590 ERR("could not write to file '%s' fd %d: %s",
591 tmp, _ecore_fps_debug_fd, strerror(errno));
592 close(_ecore_fps_debug_fd);
593 _ecore_fps_debug_fd = -1;
597 _ecore_fps_runtime_mmap = mmap(NULL, sizeof(unsigned int),
598 PROT_READ | PROT_WRITE,
600 _ecore_fps_debug_fd, 0);
601 if (_ecore_fps_runtime_mmap == MAP_FAILED)
602 _ecore_fps_runtime_mmap = NULL;
607 _ecore_fps_debug_shutdown(void)
609 _ecore_fps_debug_init_count--;
610 if (_ecore_fps_debug_init_count > 0) return;
611 if (_ecore_fps_debug_fd >= 0)
620 tmp = (char *)evil_tmpdir_get ();
621 #endif /* HAVE_EVIL */
623 snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid);
625 if (_ecore_fps_runtime_mmap)
627 munmap(_ecore_fps_runtime_mmap, sizeof(int));
628 _ecore_fps_runtime_mmap = NULL;
630 close(_ecore_fps_debug_fd);
631 _ecore_fps_debug_fd = -1;
636 _ecore_fps_debug_runtime_add(double t)
638 if ((_ecore_fps_debug_fd >= 0) &&
639 (_ecore_fps_runtime_mmap))
643 tm = (unsigned int)(t * 1000000.0);
644 /* i know its not 100% theoretically guaranteed, but i'd say a write */
645 /* of an int could be considered atomic for all practical purposes */
646 /* oh and since this is cumulative, 1 second = 1,000,000 ticks, so */
647 /* this can run for about 4294 seconds becore looping. if you are */
648 /* doing performance testing in one run for over an hour... well */
649 /* time to restart or handle a loop condition :) */
650 *(_ecore_fps_runtime_mmap) += tm;
656 _ecore_memory_statistic(__UNUSED__ void *data)
659 static int uordblks = 0;
660 static int fordblks = 0;
661 Eina_Bool changed = EINA_FALSE;
665 #define HAS_CHANGED(Global, Local) \
666 if (Global != Local) \
669 changed = EINA_TRUE; \
672 HAS_CHANGED(uordblks, mi.uordblks);
673 HAS_CHANGED(fordblks, mi.fordblks);
676 ERR("[%i] Memory total: %i, free: %i",
681 KEEP_MAX(_ecore_memory_max_total, mi.uordblks);
682 KEEP_MAX(_ecore_memory_max_free, mi.fordblks);
684 return ECORE_CALLBACK_RENEW;
690 _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order)
694 eina_lock_take(&_thread_safety);
696 count = _thread_cb ? 0 : 1;
697 _thread_cb = eina_list_append(_thread_cb, order);
698 if (count) ecore_pipe_write(_thread_call, &wakeup, sizeof (int));
700 eina_lock_release(&_thread_safety);
704 _thread_safe_cleanup(void *data)
706 Ecore_Safe_Call *call = data;
708 eina_condition_free(&call->c);
709 eina_lock_free(&call->m);
713 _ecore_main_call_flush(void)
715 Ecore_Safe_Call *call;
718 eina_lock_take(&_thread_safety);
719 callback = _thread_cb;
721 eina_lock_release(&_thread_safety);
723 EINA_LIST_FREE(callback, call)
727 eina_lock_take(&_thread_mutex);
729 eina_lock_take(&call->m);
730 _thread_id = call->current_id;
731 eina_condition_broadcast(&call->c);
732 eina_lock_release(&call->m);
734 while (_thread_id_update != _thread_id)
735 eina_condition_wait(&_thread_cond);
736 eina_lock_release(&_thread_mutex);
738 eina_main_loop_define();
740 eina_lock_take(&_thread_feedback_mutex);
744 eina_condition_broadcast(&_thread_feedback_cond);
745 eina_lock_release(&_thread_feedback_mutex);
747 _thread_safe_cleanup(call);
752 call->data = call->cb.sync(call->data);
753 eina_condition_broadcast(&call->c);
757 call->cb.async(call->data);
764 _thread_callback(void *data __UNUSED__,
765 void *buffer __UNUSED__,
766 unsigned int nbyte __UNUSED__)
768 _ecore_main_call_flush();