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;
83 static const int wakeup = 42;
85 static int _thread_loop = 0;
86 static Eina_Lock _thread_mutex;
87 static Eina_Condition _thread_cond;
88 static Eina_Lock _thread_feedback_mutex;
89 static Eina_Condition _thread_feedback_cond;
91 static Eina_Lock _thread_id_lock;
92 static int _thread_id = -1;
93 static int _thread_id_max = 0;
94 static int _thread_id_update = 0;
96 Eina_Lock _ecore_main_loop_lock;
97 int _ecore_main_lock_count;
99 /** OpenBSD does not define CODESET
104 # define CODESET "INVALID"
108 * @addtogroup Ecore_Init_Group
114 * Set up connections, signal handlers, sockets etc.
115 * @return 1 or greater on success, 0 otherwise
117 * This function sets up all singal handlers and the basic event loop. If it
118 * succeeds, 1 will be returned, otherwise 0 will be returned.
123 * int main(int argc, char **argv)
127 * printf("ERROR: Cannot init Ecore!\n");
130 * ecore_main_loop_begin();
138 if (++_ecore_init_count != 1)
139 return _ecore_init_count;
142 setlocale(LC_CTYPE, "");
145 if (strcmp(nl_langinfo(CODESET), "UTF-8"))
147 WRN("Not a utf8 locale!");
152 return --_ecore_init_count;
156 _ecore_log_dom = eina_log_domain_register("ecore", ECORE_DEFAULT_LOG_COLOR);
157 if (_ecore_log_dom < 0)
159 EINA_LOG_ERR("Ecore was unable to create a log domain.");
160 goto shutdown_log_dom;
162 if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1;
163 if (_ecore_fps_debug) _ecore_fps_debug_init();
164 if (!ecore_mempool_init()) goto shutdown_mempool;
165 _ecore_main_loop_init();
166 _ecore_signal_init();
170 _ecore_thread_init();
175 eina_lock_new(&_thread_mutex);
176 eina_condition_new(&_thread_cond, &_thread_mutex);
177 eina_lock_new(&_thread_feedback_mutex);
178 eina_condition_new(&_thread_feedback_cond, &_thread_feedback_mutex);
179 _thread_call = ecore_pipe_add(_thread_callback, NULL);
180 eina_lock_new(&_thread_safety);
182 eina_lock_new(&_thread_id_lock);
184 eina_lock_new(&_ecore_main_loop_lock);
187 if (getenv("ECORE_MEM_STAT"))
189 _ecore_memory_pid = getpid();
190 ecore_animator_add(_ecore_memory_statistic, NULL);
194 #if defined(GLIB_INTEGRATION_ALWAYS)
195 if (_ecore_glib_always_integrate) ecore_main_loop_glib_integrate();
198 return _ecore_init_count;
201 ecore_mempool_shutdown();
208 return --_ecore_init_count;
212 * Shut down connections, signal handlers sockets etc.
214 * @return 0 if ecore shuts down, greater than 0 otherwise.
215 * This function shuts down all things set up in ecore_init() and cleans up all
216 * event queues, handlers, filters, timers, idlers, idle enterers/exiters
217 * etc. set up after ecore_init() was called.
219 * Do not call this function from any callback that may be called from the main
220 * loop, as the main loop will then fall over and not function properly.
227 * take a lock here because _ecore_event_shutdown() does callbacks
230 if (_ecore_init_count <= 0)
232 ERR("Init count not greater than 0 in shutdown.");
236 if (--_ecore_init_count != 0)
239 if (_ecore_fps_debug) _ecore_fps_debug_shutdown();
240 _ecore_poller_shutdown();
241 _ecore_animator_shutdown();
242 _ecore_glib_shutdown();
243 _ecore_job_shutdown();
244 _ecore_thread_shutdown();
246 /* this looks horrible - a hack for now, but something to note. as
247 * we delete the _thread_call pipe a thread COULD be doing
248 * ecore_pipe_write() or what not to it at the same time - we
249 * must ensure all possible users of this _thread_call are finished
250 * and exited before we delete it here */
252 * ok - this causes other valgrind complaints regarding glib aquiring
253 * locks internally. so fix bug a or bug b. let's leave the original
254 * bug in then and leave this as a note for now
257 * It should be fine now as we do wait for thread to shutdown before
258 * we try to destroy the pipe.
262 ecore_pipe_wait(p, 1, 0.1);
264 eina_lock_free(&_thread_safety);
265 eina_condition_free(&_thread_cond);
266 eina_lock_free(&_thread_mutex);
267 eina_condition_free(&_thread_feedback_cond);
268 eina_lock_free(&_thread_feedback_mutex);
269 eina_lock_free(&_thread_id_lock);
273 _ecore_exe_shutdown();
275 _ecore_idle_enterer_shutdown();
276 _ecore_idle_exiter_shutdown();
277 _ecore_idler_shutdown();
278 _ecore_timer_shutdown();
279 _ecore_event_shutdown();
280 _ecore_main_shutdown();
281 _ecore_signal_shutdown();
282 _ecore_main_loop_shutdown();
285 if (getenv("ECORE_MEM_STAT"))
287 _ecore_memory_statistic(NULL);
289 ERR("[%i] Memory MAX total: %i, free: %i",
291 _ecore_memory_max_total,
292 _ecore_memory_max_free);
295 ecore_mempool_shutdown();
296 eina_log_domain_unregister(_ecore_log_dom);
305 return _ecore_init_count;
308 struct _Ecore_Fork_Cb
312 Eina_Bool delete_me : 1;
315 typedef struct _Ecore_Fork_Cb Ecore_Fork_Cb;
317 static int fork_cbs_walking = 0;
318 static Eina_List *fork_cbs = NULL;
321 ecore_fork_reset_callback_add(Ecore_Cb func, const void *data)
325 fcb = calloc(1, sizeof(Ecore_Fork_Cb));
326 if (!fcb) return EINA_FALSE;
328 fcb->data = (void *)data;
329 fork_cbs = eina_list_append(fork_cbs, fcb);
334 ecore_fork_reset_callback_del(Ecore_Cb func, const void *data)
339 EINA_LIST_FOREACH(fork_cbs, l, fcb)
341 if ((fcb->func == func) && (fcb->data == data))
343 if (!fork_cbs_walking)
345 fork_cbs = eina_list_remove_list(fork_cbs, l);
349 fcb->delete_me = EINA_TRUE;
357 ecore_fork_reset(void)
362 eina_lock_take(&_thread_safety);
364 ecore_pipe_del(_thread_call);
365 _thread_call = ecore_pipe_add(_thread_callback, NULL);
366 /* If there was something in the pipe, trigger a wakeup again */
367 if (_thread_cb) ecore_pipe_write(_thread_call, &wakeup, sizeof (int));
369 eina_lock_release(&_thread_safety);
371 // should this be done withing the eina lock stuff?
374 EINA_LIST_FOREACH(fork_cbs, l, fcb)
376 fcb->func(fcb->data);
380 EINA_LIST_FOREACH_SAFE(fork_cbs, l, ln, fcb)
384 fork_cbs = eina_list_remove_list(fork_cbs, l);
395 ecore_main_loop_thread_safe_call_async(Ecore_Cb callback,
398 Ecore_Safe_Call *order;
400 if (!callback) return;
402 if (eina_main_loop_is())
408 order = malloc(sizeof (Ecore_Safe_Call));
411 order->cb.async = callback;
413 order->sync = EINA_FALSE;
414 order->suspend = EINA_FALSE;
416 _ecore_main_loop_thread_safe_call(order);
420 ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback,
423 Ecore_Safe_Call *order;
426 if (!callback) return NULL;
428 if (eina_main_loop_is())
430 return callback(data);
433 order = malloc(sizeof (Ecore_Safe_Call));
434 if (!order) return NULL;
436 order->cb.sync = callback;
438 eina_lock_new(&order->m);
439 eina_condition_new(&order->c, &order->m);
440 order->sync = EINA_TRUE;
441 order->suspend = EINA_FALSE;
443 _ecore_main_loop_thread_safe_call(order);
445 eina_lock_take(&order->m);
446 eina_condition_wait(&order->c);
447 eina_lock_release(&order->m);
451 order->sync = EINA_FALSE;
452 order->cb.async = _thread_safe_cleanup;
455 _ecore_main_loop_thread_safe_call(order);
461 ecore_thread_main_loop_begin(void)
463 Ecore_Safe_Call *order;
465 if (eina_main_loop_is())
467 return ++_thread_loop;
470 order = malloc(sizeof (Ecore_Safe_Call));
471 if (!order) return -1;
473 eina_lock_take(&_thread_id_lock);
474 order->current_id = ++_thread_id_max;
475 if (order->current_id < 0)
478 order->current_id = ++_thread_id_max;
480 eina_lock_release(&_thread_id_lock);
482 eina_lock_new(&order->m);
483 eina_condition_new(&order->c, &order->m);
484 order->suspend = EINA_TRUE;
486 _ecore_main_loop_thread_safe_call(order);
488 eina_lock_take(&order->m);
489 while (order->current_id != _thread_id)
490 eina_condition_wait(&order->c);
491 eina_lock_release(&order->m);
493 eina_main_loop_define();
501 ecore_thread_main_loop_end(void)
505 if (_thread_loop == 0)
507 ERR("the main loop is not locked ! No matching call to ecore_thread_main_loop_begin().");
511 /* until we unlock the main loop, this thread has the main loop id */
512 if (!eina_main_loop_is())
514 ERR("Not in a locked thread !");
519 if (_thread_loop > 0)
522 current_id = _thread_id;
524 eina_lock_take(&_thread_mutex);
525 _thread_id_update = _thread_id;
526 eina_condition_broadcast(&_thread_cond);
527 eina_lock_release(&_thread_mutex);
529 eina_lock_take(&_thread_feedback_mutex);
530 while (current_id == _thread_id && _thread_id != -1)
531 eina_condition_wait(&_thread_feedback_cond);
532 eina_lock_release(&_thread_feedback_mutex);
538 ecore_print_warning(const char *function __UNUSED__,
539 const char *sparam __UNUSED__)
541 WRN("***** Developer Warning ***** :\n"
542 "\tThis program is calling:\n\n"
544 "\tWith the parameter:\n\n"
546 "\tbeing NULL. Please fix your program.", function, sparam);
547 if (getenv("ECORE_ERROR_ABORT")) abort();
551 _ecore_magic_fail(const void *d,
554 const char *fname __UNUSED__)
557 "*** ECORE ERROR: Ecore Magic Check Failed!!!\n"
558 "*** IN FUNCTION: %s()", fname);
560 ERR(" Input handle pointer is NULL!");
561 else if (m == ECORE_MAGIC_NONE)
562 ERR(" Input handle has already been freed!");
564 ERR(" Input handle is wrong type\n"
565 " Expected: %08x - %s\n"
566 " Supplied: %08x - %s",
567 (unsigned int)req_m, _ecore_magic_string_get(req_m),
568 (unsigned int)m, _ecore_magic_string_get(m));
569 ERR("*** NAUGHTY PROGRAMMER!!!\n"
570 "*** SPANK SPANK SPANK!!!\n"
571 "*** Now go fix your code. Tut tut tut!");
572 if (getenv("ECORE_ERROR_ABORT")) abort();
576 _ecore_magic_string_get(Ecore_Magic m)
580 case ECORE_MAGIC_NONE:
581 return "None (Freed Object)";
584 case ECORE_MAGIC_EXE:
585 return "Ecore_Exe (Executable)";
588 case ECORE_MAGIC_TIMER:
589 return "Ecore_Timer (Timer)";
592 case ECORE_MAGIC_IDLER:
593 return "Ecore_Idler (Idler)";
596 case ECORE_MAGIC_IDLE_ENTERER:
597 return "Ecore_Idle_Enterer (Idler Enterer)";
600 case ECORE_MAGIC_IDLE_EXITER:
601 return "Ecore_Idle_Exiter (Idler Exiter)";
604 case ECORE_MAGIC_FD_HANDLER:
605 return "Ecore_Fd_Handler (Fd Handler)";
608 case ECORE_MAGIC_WIN32_HANDLER:
609 return "Ecore_Win32_Handler (Win32 Handler)";
612 case ECORE_MAGIC_EVENT_HANDLER:
613 return "Ecore_Event_Handler (Event Handler)";
616 case ECORE_MAGIC_EVENT:
617 return "Ecore_Event (Event)";
625 /* fps debug calls - for debugging how much time your app actually spends */
626 /* "running" (and the inverse being time spent running)... this does not */
627 /* account for other apps and multitasking... */
629 static int _ecore_fps_debug_init_count = 0;
630 static int _ecore_fps_debug_fd = -1;
631 unsigned int *_ecore_fps_runtime_mmap = NULL;
634 _ecore_fps_debug_init(void)
640 _ecore_fps_debug_init_count++;
641 if (_ecore_fps_debug_init_count > 1) return;
646 tmp = evil_tmpdir_get ();
647 #endif /* HAVE_EVIL */
649 snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid);
650 _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
651 if (_ecore_fps_debug_fd < 0)
654 _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
656 if (_ecore_fps_debug_fd >= 0)
658 unsigned int zero = 0;
659 char *buf2 = (char *)&zero;
660 ssize_t todo = sizeof(unsigned int);
664 ssize_t r = write(_ecore_fps_debug_fd, buf2, todo);
670 else if ((r < 0) && (errno == EINTR))
674 ERR("could not write to file '%s' fd %d: %s",
675 tmp, _ecore_fps_debug_fd, strerror(errno));
676 close(_ecore_fps_debug_fd);
677 _ecore_fps_debug_fd = -1;
681 _ecore_fps_runtime_mmap = mmap(NULL, sizeof(unsigned int),
682 PROT_READ | PROT_WRITE,
684 _ecore_fps_debug_fd, 0);
685 if (_ecore_fps_runtime_mmap == MAP_FAILED)
686 _ecore_fps_runtime_mmap = NULL;
691 _ecore_fps_debug_shutdown(void)
693 _ecore_fps_debug_init_count--;
694 if (_ecore_fps_debug_init_count > 0) return;
695 if (_ecore_fps_debug_fd >= 0)
704 tmp = (char *)evil_tmpdir_get ();
705 #endif /* HAVE_EVIL */
707 snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid);
709 if (_ecore_fps_runtime_mmap)
711 munmap(_ecore_fps_runtime_mmap, sizeof(int));
712 _ecore_fps_runtime_mmap = NULL;
714 close(_ecore_fps_debug_fd);
715 _ecore_fps_debug_fd = -1;
720 _ecore_fps_debug_runtime_add(double t)
722 if ((_ecore_fps_debug_fd >= 0) &&
723 (_ecore_fps_runtime_mmap))
727 tm = (unsigned int)(t * 1000000.0);
728 /* i know its not 100% theoretically guaranteed, but i'd say a write */
729 /* of an int could be considered atomic for all practical purposes */
730 /* oh and since this is cumulative, 1 second = 1,000,000 ticks, so */
731 /* this can run for about 4294 seconds becore looping. if you are */
732 /* doing performance testing in one run for over an hour... well */
733 /* time to restart or handle a loop condition :) */
734 *(_ecore_fps_runtime_mmap) += tm;
740 _ecore_memory_statistic(__UNUSED__ void *data)
743 static int uordblks = 0;
744 static int fordblks = 0;
745 Eina_Bool changed = EINA_FALSE;
749 #define HAS_CHANGED(Global, Local) \
750 if (Global != Local) \
753 changed = EINA_TRUE; \
756 HAS_CHANGED(uordblks, mi.uordblks);
757 HAS_CHANGED(fordblks, mi.fordblks);
760 ERR("[%i] Memory total: %i, free: %i",
765 KEEP_MAX(_ecore_memory_max_total, mi.uordblks);
766 KEEP_MAX(_ecore_memory_max_free, mi.fordblks);
768 return ECORE_CALLBACK_RENEW;
774 _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order)
778 eina_lock_take(&_thread_safety);
780 count = _thread_cb ? 0 : 1;
781 _thread_cb = eina_list_append(_thread_cb, order);
782 if (count) ecore_pipe_write(_thread_call, &wakeup, sizeof (int));
784 eina_lock_release(&_thread_safety);
788 _thread_safe_cleanup(void *data)
790 Ecore_Safe_Call *call = data;
792 eina_condition_free(&call->c);
793 eina_lock_free(&call->m);
797 _ecore_main_call_flush(void)
799 Ecore_Safe_Call *call;
802 eina_lock_take(&_thread_safety);
803 callback = _thread_cb;
805 eina_lock_release(&_thread_safety);
807 EINA_LIST_FREE(callback, call)
811 eina_lock_take(&_thread_mutex);
813 eina_lock_take(&call->m);
814 _thread_id = call->current_id;
815 eina_condition_broadcast(&call->c);
816 eina_lock_release(&call->m);
818 while (_thread_id_update != _thread_id)
819 eina_condition_wait(&_thread_cond);
820 eina_lock_release(&_thread_mutex);
822 eina_main_loop_define();
824 eina_lock_take(&_thread_feedback_mutex);
828 eina_condition_broadcast(&_thread_feedback_cond);
829 eina_lock_release(&_thread_feedback_mutex);
831 _thread_safe_cleanup(call);
836 call->data = call->cb.sync(call->data);
837 eina_condition_broadcast(&call->c);
841 call->cb.async(call->data);
848 _thread_callback(void *data __UNUSED__,
849 void *buffer __UNUSED__,
850 unsigned int nbyte __UNUSED__)
852 _ecore_main_call_flush();