Revert "Merge remote-tracking branch 'remotes/origin/upstream'"
[framework/uifw/ecore.git] / src / lib / ecore / ecore.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <errno.h>
11
12 #ifndef _MSC_VER
13 # include <unistd.h>
14 #endif
15
16 #ifdef HAVE_LOCALE_H
17 # include <locale.h>
18 #endif
19
20 #ifdef HAVE_LANGINFO_H
21 # include <langinfo.h>
22 #endif
23
24 #ifdef HAVE_SYS_MMAN_H
25 # include <sys/mman.h>
26 #endif
27
28 #ifdef HAVE_EVIL
29 # include <Evil.h>
30 #endif
31 #include <Eina.h>
32
33 #include "Ecore.h"
34 #include "ecore_private.h"
35
36 #if HAVE_MALLINFO
37 #include <malloc.h>
38
39 static Ecore_Version _version = { VERS_MAJ, VERS_MIN, VERS_MIC, VERS_REV };
40 EAPI Ecore_Version *ecore_version = &_version;
41
42 #define KEEP_MAX(Global, Local) \
43   if (Global < (Local))         \
44     Global = Local;
45
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;
50 #endif
51
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;
56
57 typedef struct _Ecore_Safe_Call Ecore_Safe_Call;
58 struct _Ecore_Safe_Call
59 {
60    union {
61       Ecore_Cb      async;
62       Ecore_Data_Cb sync;
63    } cb;
64    void          *data;
65
66    Eina_Lock      m;
67    Eina_Condition c;
68
69    int            current_id;
70
71    Eina_Bool      sync : 1;
72    Eina_Bool      suspend : 1;
73 };
74
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,
78                              void        *buffer,
79                              unsigned int nbyte);
80 static Eina_List *_thread_cb = NULL;
81 static Ecore_Pipe *_thread_call = NULL;
82 static Eina_Lock _thread_safety;
83
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;
89
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;
94
95 Eina_Lock _ecore_main_loop_lock;
96 int _ecore_main_lock_count;
97
98 /** OpenBSD does not define CODESET
99  * FIXME ??
100  */
101
102 #ifndef CODESET
103 # define CODESET "INVALID"
104 #endif
105
106 /**
107  * @addtogroup Ecore_Init_Group
108  *
109  * @{
110  */
111
112 /**
113  * Set up connections, signal handlers, sockets etc.
114  * @return 1 or greater on success, 0 otherwise
115  *
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.
118  *
119  * @code
120  * #include <Ecore.h>
121  *
122  * int main(int argc, char **argv)
123  * {
124  *   if (!ecore_init())
125  *   {
126  *     printf("ERROR: Cannot init Ecore!\n");
127  *     return -1;
128  *   }
129  *   ecore_main_loop_begin();
130  *   ecore_shutdown();
131  * }
132  * @endcode
133  */
134 EAPI int
135 ecore_init(void)
136 {
137    if (++_ecore_init_count != 1)
138      return _ecore_init_count;
139
140 #ifdef HAVE_LOCALE_H
141    setlocale(LC_CTYPE, "");
142 #endif
143    /*
144       if (strcmp(nl_langinfo(CODESET), "UTF-8"))
145       {
146         WRN("Not a utf8 locale!");
147       }
148     */
149 #ifdef HAVE_EVIL
150    if (!evil_init())
151      return --_ecore_init_count;
152 #endif
153    if (!eina_init())
154      goto shutdown_evil;
155    _ecore_log_dom = eina_log_domain_register("ecore", ECORE_DEFAULT_LOG_COLOR);
156    if (_ecore_log_dom < 0)
157      {
158         EINA_LOG_ERR("Ecore was unable to create a log domain.");
159         goto shutdown_log_dom;
160      }
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();
166 #ifndef HAVE_EXOTIC
167    _ecore_exe_init();
168 #endif
169    _ecore_thread_init();
170    _ecore_glib_init();
171    _ecore_job_init();
172    _ecore_time_init();
173
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);
178    if (!_thread_call)
179      {
180        _thread_call = ecore_pipe_add(_thread_callback, NULL);
181        eina_lock_new(&_thread_safety);
182      }
183
184    eina_lock_new(&_thread_id_lock);
185
186    eina_lock_new(&_ecore_main_loop_lock);
187
188 #if HAVE_MALLINFO
189    if (getenv("ECORE_MEM_STAT"))
190      {
191         _ecore_memory_pid = getpid();
192         ecore_animator_add(_ecore_memory_statistic, NULL);
193      }
194 #endif
195
196 #if defined(GLIB_INTEGRATION_ALWAYS)
197    if (_ecore_glib_always_integrate) ecore_main_loop_glib_integrate();
198 #endif
199
200    return _ecore_init_count;
201
202 shutdown_mempool:
203    ecore_mempool_shutdown();
204 shutdown_log_dom:
205    eina_shutdown();
206 shutdown_evil:
207 #ifdef HAVE_EVIL
208    evil_shutdown();
209 #endif
210    return --_ecore_init_count;
211 }
212
213 /**
214  * Shut down connections, signal handlers sockets etc.
215  *
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.
220  *
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.
223  */
224 EAPI int
225 ecore_shutdown(void)
226 {
227    /*
228     * take a lock here because _ecore_event_shutdown() does callbacks
229     */
230      _ecore_lock();
231      if (_ecore_init_count <= 0)
232        {
233           ERR("Init count not greater than 0 in shutdown.");
234           _ecore_unlock();
235           return 0;
236        }
237      if (--_ecore_init_count != 0)
238        goto unlock;
239    
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 */
245    /*
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
249      Ecore_Pipe *p;
250      p = _thread_call;
251      _thread_call = NULL;
252      ecore_pipe_wait(p, 1, 0.1);
253      ecore_pipe_del(p);
254      eina_lock_free(&_thread_safety);
255     */
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);
261
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();
268 #ifndef HAVE_EXOTIC
269      _ecore_exe_shutdown();
270 #endif
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();
279
280 #if HAVE_MALLINFO
281      if (getenv("ECORE_MEM_STAT"))
282        {
283           _ecore_memory_statistic(NULL);
284
285           ERR("[%i] Memory MAX total: %i, free: %i",
286               _ecore_memory_pid,
287               _ecore_memory_max_total,
288               _ecore_memory_max_free);
289        }
290 #endif
291      ecore_mempool_shutdown();
292      eina_log_domain_unregister(_ecore_log_dom);
293      _ecore_log_dom = -1;
294      eina_shutdown();
295 #ifdef HAVE_EVIL
296      evil_shutdown();
297 #endif
298 unlock:
299      _ecore_unlock();
300
301      return _ecore_init_count;
302 }
303
304 /**
305  * @}
306  */
307
308 static int wakeup = 42;
309
310 EAPI void
311 ecore_main_loop_thread_safe_call_async(Ecore_Cb callback,
312                                        void    *data)
313 {
314    Ecore_Safe_Call *order;
315
316    if (!callback) return;
317
318    if (eina_main_loop_is())
319      {
320         callback(data);
321         return;
322      }
323
324    order = malloc(sizeof (Ecore_Safe_Call));
325    if (!order) return;
326
327    order->cb.async = callback;
328    order->data = data;
329    order->sync = EINA_FALSE;
330    order->suspend = EINA_FALSE;
331
332    _ecore_main_loop_thread_safe_call(order);
333 }
334
335 EAPI void *
336 ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback,
337                                       void         *data)
338 {
339    Ecore_Safe_Call *order;
340    void *ret;
341
342    if (!callback) return NULL;
343
344    if (eina_main_loop_is())
345      {
346         return callback(data);
347      }
348
349    order = malloc(sizeof (Ecore_Safe_Call));
350    if (!order) return NULL;
351
352    order->cb.sync = callback;
353    order->data = data;
354    eina_lock_new(&order->m);
355    eina_condition_new(&order->c, &order->m);
356    order->sync = EINA_TRUE;
357    order->suspend = EINA_FALSE;
358
359    _ecore_main_loop_thread_safe_call(order);
360
361    eina_lock_take(&order->m);
362    eina_condition_wait(&order->c);
363    eina_lock_release(&order->m);
364
365    ret = order->data;
366
367    order->sync = EINA_FALSE;
368    order->cb.async = _thread_safe_cleanup;
369    order->data = order;
370
371    _ecore_main_loop_thread_safe_call(order);
372
373    return ret;
374 }
375
376 EAPI int
377 ecore_thread_main_loop_begin(void)
378 {
379    Ecore_Safe_Call *order;
380
381    if (eina_main_loop_is())
382      {
383         return ++_thread_loop;
384      }
385
386    order = malloc(sizeof (Ecore_Safe_Call));
387    if (!order) return -1;
388
389    eina_lock_take(&_thread_id_lock);
390    order->current_id = ++_thread_id_max;
391    if (order->current_id < 0)
392      {
393         _thread_id_max = 0;
394         order->current_id = ++_thread_id_max;
395      }
396    eina_lock_release(&_thread_id_lock);
397
398    eina_lock_new(&order->m);
399    eina_condition_new(&order->c, &order->m);
400    order->suspend = EINA_TRUE;
401
402    _ecore_main_loop_thread_safe_call(order);
403
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);
408
409    eina_main_loop_define();
410
411    _thread_loop = 1;
412
413    return EINA_TRUE;
414 }
415
416 EAPI int
417 ecore_thread_main_loop_end(void)
418 {
419    int current_id;
420
421    if (_thread_loop == 0)
422      {
423         ERR("the main loop is not locked ! No matching call to ecore_thread_main_loop_begin().");
424         return -1;
425      }
426
427    /* until we unlock the main loop, this thread has the main loop id */
428    if (!eina_main_loop_is())
429      {
430         ERR("Not in a locked thread !");
431         return -1;
432      }
433
434    _thread_loop--;
435    if (_thread_loop > 0)
436      return _thread_loop;
437
438    current_id = _thread_id;
439
440    eina_lock_take(&_thread_mutex);
441    _thread_id_update = _thread_id;
442    eina_condition_broadcast(&_thread_cond);
443    eina_lock_release(&_thread_mutex);
444
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);
449
450    return 0;
451 }
452
453 EAPI void
454 ecore_print_warning(const char *function,
455                     const char *sparam)
456 {
457    WRN("***** Developer Warning ***** :\n"
458        "\tThis program is calling:\n\n"
459        "\t%s();\n\n"
460        "\tWith the parameter:\n\n"
461        "\t%s\n\n"
462        "\tbeing NULL. Please fix your program.", function, sparam);
463    if (getenv("ECORE_ERROR_ABORT")) abort();
464 }
465
466 EAPI void
467 _ecore_magic_fail(const void *d,
468                   Ecore_Magic m,
469                   Ecore_Magic req_m,
470                   const char *fname)
471 {
472    ERR("\n"
473        "*** ECORE ERROR: Ecore Magic Check Failed!!!\n"
474        "*** IN FUNCTION: %s()", fname);
475    if (!d)
476      ERR("  Input handle pointer is NULL!");
477    else if (m == ECORE_MAGIC_NONE)
478      ERR("  Input handle has already been freed!");
479    else if (m != req_m)
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();
489 }
490
491 static const char *
492 _ecore_magic_string_get(Ecore_Magic m)
493 {
494    switch (m)
495      {
496       case ECORE_MAGIC_NONE:
497         return "None (Freed Object)";
498         break;
499
500       case ECORE_MAGIC_EXE:
501         return "Ecore_Exe (Executable)";
502         break;
503
504       case ECORE_MAGIC_TIMER:
505         return "Ecore_Timer (Timer)";
506         break;
507
508       case ECORE_MAGIC_IDLER:
509         return "Ecore_Idler (Idler)";
510         break;
511
512       case ECORE_MAGIC_IDLE_ENTERER:
513         return "Ecore_Idle_Enterer (Idler Enterer)";
514         break;
515
516       case ECORE_MAGIC_IDLE_EXITER:
517         return "Ecore_Idle_Exiter (Idler Exiter)";
518         break;
519
520       case ECORE_MAGIC_FD_HANDLER:
521         return "Ecore_Fd_Handler (Fd Handler)";
522         break;
523
524       case ECORE_MAGIC_WIN32_HANDLER:
525         return "Ecore_Win32_Handler (Win32 Handler)";
526         break;
527
528       case ECORE_MAGIC_EVENT_HANDLER:
529         return "Ecore_Event_Handler (Event Handler)";
530         break;
531
532       case ECORE_MAGIC_EVENT:
533         return "Ecore_Event (Event)";
534         break;
535
536       default:
537         return "<UNKNOWN>";
538      }
539 }
540
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... */
544
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;
548
549 void
550 _ecore_fps_debug_init(void)
551 {
552    char buf[PATH_MAX];
553    const char *tmp;
554    int pid;
555
556    _ecore_fps_debug_init_count++;
557    if (_ecore_fps_debug_init_count > 1) return;
558
559 #ifndef HAVE_EVIL
560    tmp = "/tmp";
561 #else
562    tmp = evil_tmpdir_get ();
563 #endif /* HAVE_EVIL */
564    pid = (int)getpid();
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)
568      {
569         unlink(buf);
570         _ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
571      }
572    if (_ecore_fps_debug_fd >= 0)
573      {
574         unsigned int zero = 0;
575         char *buf2 = (char *)&zero;
576         ssize_t todo = sizeof(unsigned int);
577
578         while (todo > 0)
579           {
580              ssize_t r = write(_ecore_fps_debug_fd, buf2, todo);
581              if (r > 0)
582                {
583                   todo -= r;
584                   buf2 += r;
585                }
586              else if ((r < 0) && (errno == EINTR))
587                continue;
588              else
589                {
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;
594                   return;
595                }
596           }
597         _ecore_fps_runtime_mmap = mmap(NULL, sizeof(unsigned int),
598                                        PROT_READ | PROT_WRITE,
599                                        MAP_SHARED,
600                                        _ecore_fps_debug_fd, 0);
601         if (_ecore_fps_runtime_mmap == MAP_FAILED)
602           _ecore_fps_runtime_mmap = NULL;
603      }
604 }
605
606 void
607 _ecore_fps_debug_shutdown(void)
608 {
609    _ecore_fps_debug_init_count--;
610    if (_ecore_fps_debug_init_count > 0) return;
611    if (_ecore_fps_debug_fd >= 0)
612      {
613         char buf[4096];
614         const char *tmp;
615         int pid;
616
617 #ifndef HAVE_EVIL
618         tmp = "/tmp";
619 #else
620         tmp = (char *)evil_tmpdir_get ();
621 #endif /* HAVE_EVIL */
622         pid = (int)getpid();
623         snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid);
624         unlink(buf);
625         if (_ecore_fps_runtime_mmap)
626           {
627              munmap(_ecore_fps_runtime_mmap, sizeof(int));
628              _ecore_fps_runtime_mmap = NULL;
629           }
630         close(_ecore_fps_debug_fd);
631         _ecore_fps_debug_fd = -1;
632      }
633 }
634
635 void
636 _ecore_fps_debug_runtime_add(double t)
637 {
638    if ((_ecore_fps_debug_fd >= 0) &&
639        (_ecore_fps_runtime_mmap))
640      {
641         unsigned int tm;
642
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;
651      }
652 }
653
654 #if HAVE_MALLINFO
655 static Eina_Bool
656 _ecore_memory_statistic(__UNUSED__ void *data)
657 {
658    struct mallinfo mi;
659    static int uordblks = 0;
660    static int fordblks = 0;
661    Eina_Bool changed = EINA_FALSE;
662
663    mi = mallinfo();
664
665 #define HAS_CHANGED(Global, Local) \
666   if (Global != Local)             \
667     {                              \
668        Global = Local;             \
669        changed = EINA_TRUE;        \
670     }
671
672    HAS_CHANGED(uordblks, mi.uordblks);
673    HAS_CHANGED(fordblks, mi.fordblks);
674
675    if (changed)
676      ERR("[%i] Memory total: %i, free: %i",
677          _ecore_memory_pid,
678          mi.uordblks,
679          mi.fordblks);
680
681    KEEP_MAX(_ecore_memory_max_total, mi.uordblks);
682    KEEP_MAX(_ecore_memory_max_free, mi.fordblks);
683
684    return ECORE_CALLBACK_RENEW;
685 }
686
687 #endif
688
689 static void
690 _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order)
691 {
692    Eina_Bool count;
693
694    eina_lock_take(&_thread_safety);
695
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));
699
700    eina_lock_release(&_thread_safety);
701 }
702
703 static void
704 _thread_safe_cleanup(void *data)
705 {
706    Ecore_Safe_Call *call = data;
707
708    eina_condition_free(&call->c);
709    eina_lock_free(&call->m);
710 }
711
712 void
713 _ecore_main_call_flush(void)
714 {
715    Ecore_Safe_Call *call;
716    Eina_List *callback;
717
718    eina_lock_take(&_thread_safety);
719    callback = _thread_cb;
720    _thread_cb = NULL;
721    eina_lock_release(&_thread_safety);
722
723    EINA_LIST_FREE(callback, call)
724      {
725         if (call->suspend)
726           {
727              eina_lock_take(&_thread_mutex);
728
729              eina_lock_take(&call->m);
730              _thread_id = call->current_id;
731              eina_condition_broadcast(&call->c);
732              eina_lock_release(&call->m);
733
734              while (_thread_id_update != _thread_id)
735                eina_condition_wait(&_thread_cond);
736              eina_lock_release(&_thread_mutex);
737
738              eina_main_loop_define();
739
740              eina_lock_take(&_thread_feedback_mutex);
741
742              _thread_id = -1;
743
744              eina_condition_broadcast(&_thread_feedback_cond);
745              eina_lock_release(&_thread_feedback_mutex);
746
747              _thread_safe_cleanup(call);
748              free(call);
749           }
750         else if (call->sync)
751           {
752              call->data = call->cb.sync(call->data);
753              eina_condition_broadcast(&call->c);
754           }
755         else
756           {
757              call->cb.async(call->data);
758              free(call);
759           }
760      }
761 }
762
763 static void
764 _thread_callback(void        *data __UNUSED__,
765                  void        *buffer __UNUSED__,
766                  unsigned int nbyte __UNUSED__)
767 {
768    _ecore_main_call_flush();
769 }
770