2008-05-25 22:16:34 -07:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2011-12-06 08:09:05 -08:00
|
|
|
#include <stdlib.h>
|
2009-01-31 10:33:39 -08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
2010-02-28 15:27:47 -08:00
|
|
|
#include <errno.h>
|
2009-01-31 10:33:39 -08:00
|
|
|
|
2011-01-07 07:56:54 -08:00
|
|
|
#ifndef _MSC_VER
|
2010-04-05 01:26:48 -07:00
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2008-01-25 21:40:53 -08:00
|
|
|
#ifdef HAVE_LOCALE_H
|
|
|
|
# include <locale.h>
|
|
|
|
#endif
|
2008-05-25 22:16:34 -07:00
|
|
|
|
2008-01-25 21:40:53 -08:00
|
|
|
#ifdef HAVE_LANGINFO_H
|
2007-08-26 04:17:21 -07:00
|
|
|
# include <langinfo.h>
|
2008-01-25 21:40:53 -08:00
|
|
|
#endif
|
|
|
|
|
2009-01-31 10:33:39 -08:00
|
|
|
#ifdef HAVE_SYS_MMAN_H
|
|
|
|
# include <sys/mman.h>
|
|
|
|
#endif
|
2008-05-25 22:16:34 -07:00
|
|
|
|
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
# include <Evil.h>
|
|
|
|
#endif
|
2008-10-26 09:32:21 -07:00
|
|
|
#include <Eina.h>
|
2003-09-23 01:09:32 -07:00
|
|
|
|
2009-01-31 10:33:39 -08:00
|
|
|
#include "Ecore.h"
|
|
|
|
#include "ecore_private.h"
|
|
|
|
|
2010-03-18 07:43:39 -07:00
|
|
|
#if HAVE_MALLINFO
|
|
|
|
#include <malloc.h>
|
|
|
|
|
2010-05-29 06:59:42 -07:00
|
|
|
static Ecore_Version _version = { VERS_MAJ, VERS_MIN, VERS_MIC, VERS_REV };
|
2010-05-28 23:28:25 -07:00
|
|
|
EAPI Ecore_Version *ecore_version = &_version;
|
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
#define KEEP_MAX(Global, Local) \
|
|
|
|
if (Global < (Local)) \
|
|
|
|
Global = Local;
|
2010-03-18 07:43:39 -07:00
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
static Eina_Bool _ecore_memory_statistic(void *data);
|
2010-03-18 07:43:39 -07:00
|
|
|
static int _ecore_memory_max_total = 0;
|
|
|
|
static int _ecore_memory_max_free = 0;
|
|
|
|
static pid_t _ecore_memory_pid = 0;
|
|
|
|
#endif
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
static const char *_ecore_magic_string_get(Ecore_Magic m);
|
2004-02-03 11:49:46 -08:00
|
|
|
static int _ecore_init_count = 0;
|
2010-04-05 01:26:48 -07:00
|
|
|
int _ecore_log_dom = -1;
|
2004-03-16 21:14:13 -08:00
|
|
|
int _ecore_fps_debug = 0;
|
|
|
|
|
2011-07-28 06:33:14 -07:00
|
|
|
typedef struct _Ecore_Safe_Call Ecore_Safe_Call;
|
|
|
|
struct _Ecore_Safe_Call
|
|
|
|
{
|
2011-08-16 07:35:00 -07:00
|
|
|
union {
|
2011-10-20 22:40:39 -07:00
|
|
|
Ecore_Cb async;
|
2011-08-16 07:35:00 -07:00
|
|
|
Ecore_Data_Cb sync;
|
|
|
|
} cb;
|
2011-10-20 22:40:39 -07:00
|
|
|
void *data;
|
2011-08-16 07:35:00 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
Eina_Lock m;
|
2011-08-16 07:35:00 -07:00
|
|
|
Eina_Condition c;
|
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
int current_id;
|
2011-09-23 03:47:33 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
Eina_Bool sync : 1;
|
|
|
|
Eina_Bool suspend : 1;
|
2011-07-28 06:33:14 -07:00
|
|
|
};
|
|
|
|
|
2011-08-16 07:35:00 -07:00
|
|
|
static void _ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order);
|
|
|
|
static void _thread_safe_cleanup(void *data);
|
2011-10-20 22:40:39 -07:00
|
|
|
static void _thread_callback(void *data,
|
|
|
|
void *buffer,
|
|
|
|
unsigned int nbyte);
|
2011-08-01 05:16:39 -07:00
|
|
|
static Eina_List *_thread_cb = NULL;
|
2011-07-28 06:33:14 -07:00
|
|
|
static Ecore_Pipe *_thread_call = NULL;
|
|
|
|
static Eina_Lock _thread_safety;
|
2011-08-17 02:43:49 -07:00
|
|
|
|
2011-08-22 02:47:17 -07:00
|
|
|
static int _thread_loop = 0;
|
2011-08-17 02:43:49 -07:00
|
|
|
static Eina_Lock _thread_mutex;
|
|
|
|
static Eina_Condition _thread_cond;
|
2011-09-15 04:15:46 -07:00
|
|
|
static Eina_Lock _thread_feedback_mutex;
|
|
|
|
static Eina_Condition _thread_feedback_cond;
|
2011-08-17 02:43:49 -07:00
|
|
|
|
2011-09-23 03:47:33 -07:00
|
|
|
static Eina_Lock _thread_id_lock;
|
|
|
|
static int _thread_id = -1;
|
|
|
|
static int _thread_id_max = 0;
|
2011-09-23 06:26:54 -07:00
|
|
|
static int _thread_id_update = 0;
|
2011-09-23 03:47:33 -07:00
|
|
|
|
2011-08-11 22:21:49 -07:00
|
|
|
Eina_Lock _ecore_main_loop_lock;
|
|
|
|
int _ecore_main_lock_count;
|
2011-07-28 06:33:14 -07:00
|
|
|
|
2004-11-25 09:40:42 -08:00
|
|
|
/** OpenBSD does not define CODESET
|
|
|
|
* FIXME ??
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef CODESET
|
2007-08-26 04:17:21 -07:00
|
|
|
# define CODESET "INVALID"
|
2004-11-25 09:40:42 -08:00
|
|
|
#endif
|
|
|
|
|
2010-10-17 00:03:28 -07:00
|
|
|
/**
|
2011-08-10 12:14:48 -07:00
|
|
|
* @addtogroup Ecore_Init_Group
|
2010-10-17 00:03:28 -07:00
|
|
|
*
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
/**
|
|
|
|
* Set up connections, signal handlers, sockets etc.
|
|
|
|
* @return 1 or greater on success, 0 otherwise
|
2007-08-26 04:17:21 -07:00
|
|
|
*
|
2003-09-23 01:09:32 -07:00
|
|
|
* This function sets up all singal handlers and the basic event loop. If it
|
|
|
|
* succeeds, 1 will be returned, otherwise 0 will be returned.
|
2007-08-26 04:17:21 -07:00
|
|
|
*
|
2003-09-23 01:09:32 -07:00
|
|
|
* @code
|
|
|
|
* #include <Ecore.h>
|
2007-08-26 04:17:21 -07:00
|
|
|
*
|
2003-09-23 01:09:32 -07:00
|
|
|
* int main(int argc, char **argv)
|
|
|
|
* {
|
|
|
|
* if (!ecore_init())
|
2007-08-26 04:17:21 -07:00
|
|
|
* {
|
2003-09-23 01:09:32 -07:00
|
|
|
* printf("ERROR: Cannot init Ecore!\n");
|
|
|
|
* return -1;
|
|
|
|
* }
|
|
|
|
* ecore_main_loop_begin();
|
|
|
|
* ecore_shutdown();
|
|
|
|
* }
|
|
|
|
* @endcode
|
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_init(void)
|
|
|
|
{
|
2009-10-09 22:28:43 -07:00
|
|
|
if (++_ecore_init_count != 1)
|
|
|
|
return _ecore_init_count;
|
|
|
|
|
2008-05-25 22:16:34 -07:00
|
|
|
#ifdef HAVE_LOCALE_H
|
2009-10-09 22:28:43 -07:00
|
|
|
setlocale(LC_CTYPE, "");
|
2008-05-25 22:16:34 -07:00
|
|
|
#endif
|
2009-10-09 22:28:43 -07:00
|
|
|
/*
|
2011-10-20 22:40:39 -07:00
|
|
|
if (strcmp(nl_langinfo(CODESET), "UTF-8"))
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
WRN("Not a utf8 locale!");
|
2011-10-20 22:40:39 -07:00
|
|
|
}
|
|
|
|
*/
|
2008-11-21 23:55:02 -08:00
|
|
|
#ifdef HAVE_EVIL
|
2009-10-09 22:28:43 -07:00
|
|
|
if (!evil_init())
|
|
|
|
return --_ecore_init_count;
|
2008-11-21 23:55:02 -08:00
|
|
|
#endif
|
2009-10-09 22:28:43 -07:00
|
|
|
if (!eina_init())
|
|
|
|
goto shutdown_evil;
|
2010-10-07 15:31:46 -07:00
|
|
|
_ecore_log_dom = eina_log_domain_register("ecore", ECORE_DEFAULT_LOG_COLOR);
|
|
|
|
if (_ecore_log_dom < 0)
|
|
|
|
{
|
|
|
|
EINA_LOG_ERR("Ecore was unable to create a log domain.");
|
|
|
|
goto shutdown_log_dom;
|
|
|
|
}
|
2009-10-09 22:28:43 -07:00
|
|
|
if (getenv("ECORE_FPS_DEBUG")) _ecore_fps_debug = 1;
|
|
|
|
if (_ecore_fps_debug) _ecore_fps_debug_init();
|
2011-12-02 19:39:07 -08:00
|
|
|
if (!ecore_mempool_init()) goto shutdown_mempool;
|
2010-08-14 04:19:03 -07:00
|
|
|
_ecore_main_loop_init();
|
2009-10-09 22:28:43 -07:00
|
|
|
_ecore_signal_init();
|
2012-02-24 03:20:25 -08:00
|
|
|
#ifndef HAVE_EXOTIC
|
2011-07-05 04:13:20 -07:00
|
|
|
_ecore_exe_init();
|
2012-02-24 03:20:25 -08:00
|
|
|
#endif
|
|
|
|
_ecore_thread_init();
|
2009-10-09 22:28:43 -07:00
|
|
|
_ecore_glib_init();
|
2010-01-25 13:59:21 -08:00
|
|
|
_ecore_job_init();
|
2010-09-27 15:35:35 -07:00
|
|
|
_ecore_time_init();
|
2004-02-03 11:49:46 -08:00
|
|
|
|
2011-07-28 06:33:14 -07:00
|
|
|
eina_lock_new(&_thread_safety);
|
2011-08-17 02:43:49 -07:00
|
|
|
eina_lock_new(&_thread_mutex);
|
|
|
|
eina_condition_new(&_thread_cond, &_thread_mutex);
|
2011-09-15 04:15:46 -07:00
|
|
|
eina_lock_new(&_thread_feedback_mutex);
|
|
|
|
eina_condition_new(&_thread_feedback_cond, &_thread_feedback_mutex);
|
2011-07-28 06:33:14 -07:00
|
|
|
_thread_call = ecore_pipe_add(_thread_callback, NULL);
|
2011-09-23 03:47:33 -07:00
|
|
|
eina_lock_new(&_thread_id_lock);
|
2011-07-28 06:33:14 -07:00
|
|
|
|
2011-08-17 02:43:49 -07:00
|
|
|
eina_lock_new(&_ecore_main_loop_lock);
|
|
|
|
|
2010-03-18 07:43:39 -07:00
|
|
|
#if HAVE_MALLINFO
|
|
|
|
if (getenv("ECORE_MEM_STAT"))
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
_ecore_memory_pid = getpid();
|
|
|
|
ecore_animator_add(_ecore_memory_statistic, NULL);
|
2010-03-18 07:43:39 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-08-14 04:19:03 -07:00
|
|
|
#if defined(GLIB_INTEGRATION_ALWAYS)
|
2010-03-21 20:30:40 -07:00
|
|
|
if (_ecore_glib_always_integrate) ecore_main_loop_glib_integrate();
|
|
|
|
#endif
|
2011-04-20 07:15:33 -07:00
|
|
|
|
2004-02-03 11:49:46 -08:00
|
|
|
return _ecore_init_count;
|
2009-10-09 22:28:43 -07:00
|
|
|
|
2011-12-02 19:39:07 -08:00
|
|
|
shutdown_mempool:
|
|
|
|
ecore_mempool_shutdown();
|
2011-10-20 22:40:39 -07:00
|
|
|
shutdown_log_dom:
|
2009-12-21 09:32:19 -08:00
|
|
|
eina_shutdown();
|
2011-10-20 22:40:39 -07:00
|
|
|
shutdown_evil:
|
2009-10-09 22:28:43 -07:00
|
|
|
#ifdef HAVE_EVIL
|
|
|
|
evil_shutdown();
|
|
|
|
#endif
|
|
|
|
return --_ecore_init_count;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shut down connections, signal handlers sockets etc.
|
2007-08-26 04:17:21 -07:00
|
|
|
*
|
2012-04-23 13:09:44 -07:00
|
|
|
* @return 0 if ecore shuts down, greater than 0 otherwise.
|
2003-09-23 01:09:32 -07:00
|
|
|
* This function shuts down all things set up in ecore_init() and cleans up all
|
2004-03-16 21:14:13 -08:00
|
|
|
* event queues, handlers, filters, timers, idlers, idle enterers/exiters
|
|
|
|
* etc. set up after ecore_init() was called.
|
2007-08-26 04:17:21 -07:00
|
|
|
*
|
2003-09-23 01:09:32 -07:00
|
|
|
* Do not call this function from any callback that may be called from the main
|
|
|
|
* loop, as the main loop will then fall over and not function properly.
|
2004-02-19 23:06:29 -08:00
|
|
|
*/
|
2006-01-06 09:58:12 -08:00
|
|
|
EAPI int
|
2003-09-23 01:09:32 -07:00
|
|
|
ecore_shutdown(void)
|
|
|
|
{
|
2011-08-11 05:01:19 -07:00
|
|
|
/*
|
|
|
|
* take a lock here because _ecore_event_shutdown() does callbacks
|
|
|
|
*/
|
2011-10-20 22:40:39 -07:00
|
|
|
_ecore_lock();
|
|
|
|
if (--_ecore_init_count != 0)
|
|
|
|
goto unlock;
|
2011-12-15 06:10:42 -08:00
|
|
|
|
2011-12-23 03:40:05 -08:00
|
|
|
/* this looks horrible - a hack for now, but something to note. as
|
|
|
|
* we delete the _thread_call pipe a thread COULD be doing
|
|
|
|
* ecore_pipe_write() or what not to it at the same time - we
|
|
|
|
* must ensure all possible users of this _thread_call are finished
|
|
|
|
* and exited before we delete it here */
|
|
|
|
/*
|
|
|
|
* ok - this causes other valgrind complaints regarding glib aquiring
|
|
|
|
* locks internally. so fix bug a or bug b. let's leave the original
|
|
|
|
* bug in then and leave this as a note for now
|
|
|
|
Ecore_Pipe *p;
|
2011-12-15 06:10:42 -08:00
|
|
|
p = _thread_call;
|
|
|
|
_thread_call = NULL;
|
|
|
|
ecore_pipe_wait(p, 1, 0.1);
|
|
|
|
ecore_pipe_del(p);
|
2011-12-23 03:40:05 -08:00
|
|
|
*/
|
2011-10-20 22:40:39 -07:00
|
|
|
eina_lock_free(&_thread_safety);
|
|
|
|
eina_condition_free(&_thread_cond);
|
|
|
|
eina_lock_free(&_thread_mutex);
|
|
|
|
eina_condition_free(&_thread_feedback_cond);
|
|
|
|
eina_lock_free(&_thread_feedback_mutex);
|
|
|
|
eina_lock_free(&_thread_id_lock);
|
|
|
|
|
|
|
|
if (_ecore_fps_debug) _ecore_fps_debug_shutdown();
|
|
|
|
_ecore_poller_shutdown();
|
|
|
|
_ecore_animator_shutdown();
|
|
|
|
_ecore_glib_shutdown();
|
|
|
|
_ecore_job_shutdown();
|
|
|
|
_ecore_thread_shutdown();
|
2012-02-24 03:20:25 -08:00
|
|
|
#ifndef HAVE_EXOTIC
|
2011-10-20 22:40:39 -07:00
|
|
|
_ecore_exe_shutdown();
|
2012-02-24 03:20:25 -08:00
|
|
|
#endif
|
2011-10-20 22:40:39 -07:00
|
|
|
_ecore_idle_enterer_shutdown();
|
|
|
|
_ecore_idle_exiter_shutdown();
|
|
|
|
_ecore_idler_shutdown();
|
|
|
|
_ecore_timer_shutdown();
|
|
|
|
_ecore_event_shutdown();
|
|
|
|
_ecore_main_shutdown();
|
|
|
|
_ecore_signal_shutdown();
|
|
|
|
_ecore_main_loop_shutdown();
|
2010-03-18 07:43:39 -07:00
|
|
|
|
|
|
|
#if HAVE_MALLINFO
|
2011-10-20 22:40:39 -07:00
|
|
|
if (getenv("ECORE_MEM_STAT"))
|
|
|
|
{
|
|
|
|
_ecore_memory_statistic(NULL);
|
|
|
|
|
|
|
|
ERR("[%i] Memory MAX total: %i, free: %i",
|
|
|
|
_ecore_memory_pid,
|
|
|
|
_ecore_memory_max_total,
|
|
|
|
_ecore_memory_max_free);
|
|
|
|
}
|
2010-03-18 07:43:39 -07:00
|
|
|
#endif
|
2011-12-02 19:39:07 -08:00
|
|
|
ecore_mempool_shutdown();
|
2011-10-20 22:40:39 -07:00
|
|
|
eina_log_domain_unregister(_ecore_log_dom);
|
|
|
|
_ecore_log_dom = -1;
|
|
|
|
eina_shutdown();
|
2008-11-21 23:55:02 -08:00
|
|
|
#ifdef HAVE_EVIL
|
2011-10-20 22:40:39 -07:00
|
|
|
evil_shutdown();
|
2008-11-21 23:55:02 -08:00
|
|
|
#endif
|
2011-08-11 05:01:19 -07:00
|
|
|
unlock:
|
2011-10-20 22:40:39 -07:00
|
|
|
_ecore_unlock();
|
2004-02-03 11:49:46 -08:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
return _ecore_init_count;
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
|
|
|
|
2011-08-10 12:14:48 -07:00
|
|
|
/**
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
2011-08-16 07:35:00 -07:00
|
|
|
static int wakeup = 42;
|
|
|
|
|
2011-07-28 06:33:14 -07:00
|
|
|
EAPI void
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_main_loop_thread_safe_call_async(Ecore_Cb callback,
|
|
|
|
void *data)
|
2011-07-28 06:33:14 -07:00
|
|
|
{
|
|
|
|
Ecore_Safe_Call *order;
|
2011-08-16 07:35:00 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
if (!callback) return;
|
2011-07-28 06:33:14 -07:00
|
|
|
|
2011-07-29 07:59:43 -07:00
|
|
|
if (eina_main_loop_is())
|
|
|
|
{
|
|
|
|
callback(data);
|
2011-10-20 22:40:39 -07:00
|
|
|
return;
|
2011-07-29 07:59:43 -07:00
|
|
|
}
|
|
|
|
|
2011-07-28 06:33:14 -07:00
|
|
|
order = malloc(sizeof (Ecore_Safe_Call));
|
2011-10-20 22:40:39 -07:00
|
|
|
if (!order) return;
|
2011-07-28 06:33:14 -07:00
|
|
|
|
2011-08-16 07:35:00 -07:00
|
|
|
order->cb.async = callback;
|
2011-07-28 06:33:14 -07:00
|
|
|
order->data = data;
|
2011-08-16 07:35:00 -07:00
|
|
|
order->sync = EINA_FALSE;
|
2011-08-17 02:43:49 -07:00
|
|
|
order->suspend = EINA_FALSE;
|
2011-07-28 06:33:14 -07:00
|
|
|
|
2011-08-16 07:35:00 -07:00
|
|
|
_ecore_main_loop_thread_safe_call(order);
|
|
|
|
}
|
2011-08-01 05:16:39 -07:00
|
|
|
|
2011-08-16 07:35:00 -07:00
|
|
|
EAPI void *
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_main_loop_thread_safe_call_sync(Ecore_Data_Cb callback,
|
|
|
|
void *data)
|
2011-08-16 07:35:00 -07:00
|
|
|
{
|
|
|
|
Ecore_Safe_Call *order;
|
|
|
|
void *ret;
|
2011-08-01 05:16:39 -07:00
|
|
|
|
2011-08-16 07:35:00 -07:00
|
|
|
if (!callback) return NULL;
|
|
|
|
|
|
|
|
if (eina_main_loop_is())
|
|
|
|
{
|
|
|
|
return callback(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
order = malloc(sizeof (Ecore_Safe_Call));
|
|
|
|
if (!order) return NULL;
|
|
|
|
|
|
|
|
order->cb.sync = callback;
|
|
|
|
order->data = data;
|
|
|
|
eina_lock_new(&order->m);
|
|
|
|
eina_condition_new(&order->c, &order->m);
|
|
|
|
order->sync = EINA_TRUE;
|
2011-08-17 02:43:49 -07:00
|
|
|
order->suspend = EINA_FALSE;
|
2011-08-16 07:35:00 -07:00
|
|
|
|
|
|
|
_ecore_main_loop_thread_safe_call(order);
|
|
|
|
|
|
|
|
eina_lock_take(&order->m);
|
|
|
|
eina_condition_wait(&order->c);
|
|
|
|
eina_lock_release(&order->m);
|
|
|
|
|
|
|
|
ret = order->data;
|
|
|
|
|
|
|
|
order->sync = EINA_FALSE;
|
|
|
|
order->cb.async = _thread_safe_cleanup;
|
|
|
|
order->data = order;
|
|
|
|
|
|
|
|
_ecore_main_loop_thread_safe_call(order);
|
|
|
|
|
|
|
|
return ret;
|
2011-07-28 06:33:14 -07:00
|
|
|
}
|
|
|
|
|
2011-08-22 02:47:17 -07:00
|
|
|
EAPI int
|
2011-08-17 02:43:49 -07:00
|
|
|
ecore_thread_main_loop_begin(void)
|
|
|
|
{
|
|
|
|
Ecore_Safe_Call *order;
|
|
|
|
|
|
|
|
if (eina_main_loop_is())
|
2011-08-22 02:47:17 -07:00
|
|
|
{
|
|
|
|
return ++_thread_loop;
|
|
|
|
}
|
2011-08-17 02:43:49 -07:00
|
|
|
|
|
|
|
order = malloc(sizeof (Ecore_Safe_Call));
|
2011-08-22 02:47:17 -07:00
|
|
|
if (!order) return -1;
|
2011-08-17 02:43:49 -07:00
|
|
|
|
2011-09-23 03:47:33 -07:00
|
|
|
eina_lock_take(&_thread_id_lock);
|
|
|
|
order->current_id = ++_thread_id_max;
|
|
|
|
if (order->current_id < 0)
|
|
|
|
{
|
|
|
|
_thread_id_max = 0;
|
2011-10-20 22:40:39 -07:00
|
|
|
order->current_id = ++_thread_id_max;
|
2011-09-23 03:47:33 -07:00
|
|
|
}
|
|
|
|
eina_lock_release(&_thread_id_lock);
|
|
|
|
|
2011-08-17 02:43:49 -07:00
|
|
|
eina_lock_new(&order->m);
|
|
|
|
eina_condition_new(&order->c, &order->m);
|
|
|
|
order->suspend = EINA_TRUE;
|
|
|
|
|
|
|
|
_ecore_main_loop_thread_safe_call(order);
|
|
|
|
|
2011-09-23 06:26:54 -07:00
|
|
|
eina_lock_take(&order->m);
|
2011-09-23 03:47:33 -07:00
|
|
|
while (order->current_id != _thread_id)
|
|
|
|
eina_condition_wait(&order->c);
|
2011-08-17 02:43:49 -07:00
|
|
|
eina_lock_release(&order->m);
|
|
|
|
|
|
|
|
eina_main_loop_define();
|
|
|
|
|
2011-08-22 02:47:17 -07:00
|
|
|
_thread_loop = 1;
|
2011-08-17 02:43:49 -07:00
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2011-08-22 02:47:17 -07:00
|
|
|
EAPI int
|
2011-08-17 02:43:49 -07:00
|
|
|
ecore_thread_main_loop_end(void)
|
|
|
|
{
|
2011-09-23 03:47:33 -07:00
|
|
|
int current_id;
|
|
|
|
|
2011-08-22 02:47:17 -07:00
|
|
|
if (_thread_loop == 0)
|
|
|
|
{
|
|
|
|
ERR("the main loop is not locked ! No matching call to ecore_thread_main_loop_begin().");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-08-17 02:43:49 -07:00
|
|
|
/* until we unlock the main loop, this thread has the main loop id */
|
2011-08-22 02:47:17 -07:00
|
|
|
if (!eina_main_loop_is())
|
|
|
|
{
|
|
|
|
ERR("Not in a locked thread !");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_thread_loop--;
|
|
|
|
if (_thread_loop > 0)
|
|
|
|
return _thread_loop;
|
2011-08-17 02:43:49 -07:00
|
|
|
|
2011-09-23 03:47:33 -07:00
|
|
|
current_id = _thread_id;
|
|
|
|
|
|
|
|
eina_lock_take(&_thread_mutex);
|
2011-09-23 06:26:54 -07:00
|
|
|
_thread_id_update = _thread_id;
|
2011-09-16 02:31:47 -07:00
|
|
|
eina_condition_broadcast(&_thread_cond);
|
2011-09-23 03:47:33 -07:00
|
|
|
eina_lock_release(&_thread_mutex);
|
|
|
|
|
|
|
|
eina_lock_take(&_thread_feedback_mutex);
|
2011-09-26 23:16:11 -07:00
|
|
|
while (current_id == _thread_id && _thread_id != -1)
|
2011-09-23 03:47:33 -07:00
|
|
|
eina_condition_wait(&_thread_feedback_cond);
|
2011-09-15 04:15:46 -07:00
|
|
|
eina_lock_release(&_thread_feedback_mutex);
|
|
|
|
|
2011-08-22 02:47:17 -07:00
|
|
|
return 0;
|
2011-08-17 02:43:49 -07:00
|
|
|
}
|
|
|
|
|
2010-02-01 12:20:06 -08:00
|
|
|
EAPI void
|
2011-10-20 22:40:39 -07:00
|
|
|
ecore_print_warning(const char *function,
|
|
|
|
const char *sparam)
|
2010-02-01 12:20:06 -08:00
|
|
|
{
|
|
|
|
WRN("***** Developer Warning ***** :\n"
|
|
|
|
"\tThis program is calling:\n\n"
|
|
|
|
"\t%s();\n\n"
|
|
|
|
"\tWith the parameter:\n\n"
|
|
|
|
"\t%s\n\n"
|
|
|
|
"\tbeing NULL. Please fix your program.", function, sparam);
|
|
|
|
if (getenv("ECORE_ERROR_ABORT")) abort();
|
|
|
|
}
|
|
|
|
|
2006-01-06 10:05:08 -08:00
|
|
|
EAPI void
|
2011-10-20 22:40:39 -07:00
|
|
|
_ecore_magic_fail(const void *d,
|
|
|
|
Ecore_Magic m,
|
|
|
|
Ecore_Magic req_m,
|
|
|
|
const char *fname)
|
2003-09-23 01:09:32 -07:00
|
|
|
{
|
2009-12-21 09:32:19 -08:00
|
|
|
ERR("\n"
|
|
|
|
"*** ECORE ERROR: Ecore Magic Check Failed!!!\n"
|
|
|
|
"*** IN FUNCTION: %s()", fname);
|
2003-09-23 01:09:32 -07:00
|
|
|
if (!d)
|
2009-12-21 09:32:19 -08:00
|
|
|
ERR(" Input handle pointer is NULL!");
|
2003-09-23 01:09:32 -07:00
|
|
|
else if (m == ECORE_MAGIC_NONE)
|
2009-12-21 09:32:19 -08:00
|
|
|
ERR(" Input handle has already been freed!");
|
2003-09-23 01:09:32 -07:00
|
|
|
else if (m != req_m)
|
2009-12-21 09:32:19 -08:00
|
|
|
ERR(" Input handle is wrong type\n"
|
2010-09-29 23:09:20 -07:00
|
|
|
" Expected: %08x - %s\n"
|
|
|
|
" Supplied: %08x - %s",
|
|
|
|
(unsigned int)req_m, _ecore_magic_string_get(req_m),
|
|
|
|
(unsigned int)m, _ecore_magic_string_get(m));
|
2011-10-20 22:40:39 -07:00
|
|
|
ERR("*** NAUGHTY PROGRAMMER!!!\n"
|
|
|
|
"*** SPANK SPANK SPANK!!!\n"
|
|
|
|
"*** Now go fix your code. Tut tut tut!");
|
2003-09-23 01:09:32 -07:00
|
|
|
if (getenv("ECORE_ERROR_ABORT")) abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
_ecore_magic_string_get(Ecore_Magic m)
|
|
|
|
{
|
|
|
|
switch (m)
|
|
|
|
{
|
|
|
|
case ECORE_MAGIC_NONE:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "None (Freed Object)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
case ECORE_MAGIC_EXE:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "Ecore_Exe (Executable)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
case ECORE_MAGIC_TIMER:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "Ecore_Timer (Timer)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
case ECORE_MAGIC_IDLER:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "Ecore_Idler (Idler)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
case ECORE_MAGIC_IDLE_ENTERER:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "Ecore_Idle_Enterer (Idler Enterer)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2004-03-16 21:14:13 -08:00
|
|
|
case ECORE_MAGIC_IDLE_EXITER:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "Ecore_Idle_Exiter (Idler Exiter)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
case ECORE_MAGIC_FD_HANDLER:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "Ecore_Fd_Handler (Fd Handler)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2009-11-23 15:09:48 -08:00
|
|
|
case ECORE_MAGIC_WIN32_HANDLER:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "Ecore_Win32_Handler (Win32 Handler)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
case ECORE_MAGIC_EVENT_HANDLER:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "Ecore_Event_Handler (Event Handler)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
case ECORE_MAGIC_EVENT:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "Ecore_Event (Event)";
|
|
|
|
break;
|
2011-10-20 22:40:39 -07:00
|
|
|
|
2003-09-23 01:09:32 -07:00
|
|
|
default:
|
2010-09-29 23:09:20 -07:00
|
|
|
return "<UNKNOWN>";
|
2011-10-20 22:40:39 -07:00
|
|
|
}
|
2003-09-23 01:09:32 -07:00
|
|
|
}
|
2004-03-16 21:14:13 -08:00
|
|
|
|
|
|
|
/* fps debug calls - for debugging how much time your app actually spends */
|
|
|
|
/* "running" (and the inverse being time spent running)... this does not */
|
|
|
|
/* account for other apps and multitasking... */
|
|
|
|
|
2004-04-04 10:12:14 -07:00
|
|
|
static int _ecore_fps_debug_init_count = 0;
|
2004-03-16 21:14:13 -08:00
|
|
|
static int _ecore_fps_debug_fd = -1;
|
|
|
|
unsigned int *_ecore_fps_runtime_mmap = NULL;
|
|
|
|
|
|
|
|
void
|
|
|
|
_ecore_fps_debug_init(void)
|
|
|
|
{
|
2011-10-20 22:40:39 -07:00
|
|
|
char buf[PATH_MAX];
|
2010-01-21 23:03:04 -08:00
|
|
|
const char *tmp;
|
2011-10-20 22:40:39 -07:00
|
|
|
int pid;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2004-03-16 21:14:13 -08:00
|
|
|
_ecore_fps_debug_init_count++;
|
|
|
|
if (_ecore_fps_debug_init_count > 1) return;
|
2007-10-27 03:58:00 -07:00
|
|
|
|
2008-05-25 22:16:34 -07:00
|
|
|
#ifndef HAVE_EVIL
|
|
|
|
tmp = "/tmp";
|
|
|
|
#else
|
2011-06-17 14:45:21 -07:00
|
|
|
tmp = evil_tmpdir_get ();
|
2008-05-25 22:16:34 -07:00
|
|
|
#endif /* HAVE_EVIL */
|
|
|
|
pid = (int)getpid();
|
|
|
|
snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid);
|
2007-08-18 07:26:49 -07:00
|
|
|
_ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
|
2004-03-16 21:14:13 -08:00
|
|
|
if (_ecore_fps_debug_fd < 0)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
unlink(buf);
|
|
|
|
_ecore_fps_debug_fd = open(buf, O_CREAT | O_TRUNC | O_RDWR, 0644);
|
2004-03-16 21:14:13 -08:00
|
|
|
}
|
|
|
|
if (_ecore_fps_debug_fd >= 0)
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
unsigned int zero = 0;
|
2011-08-18 00:35:12 -07:00
|
|
|
char *buf2 = (char *)&zero;
|
2010-09-29 23:09:20 -07:00
|
|
|
ssize_t todo = sizeof(unsigned int);
|
|
|
|
|
|
|
|
while (todo > 0)
|
|
|
|
{
|
2011-08-18 00:35:12 -07:00
|
|
|
ssize_t r = write(_ecore_fps_debug_fd, buf2, todo);
|
2010-09-29 23:09:20 -07:00
|
|
|
if (r > 0)
|
|
|
|
{
|
|
|
|
todo -= r;
|
2011-08-18 00:35:12 -07:00
|
|
|
buf2 += r;
|
2010-09-29 23:09:20 -07:00
|
|
|
}
|
|
|
|
else if ((r < 0) && (errno == EINTR))
|
|
|
|
continue;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ERR("could not write to file '%s' fd %d: %s",
|
|
|
|
tmp, _ecore_fps_debug_fd, strerror(errno));
|
|
|
|
close(_ecore_fps_debug_fd);
|
|
|
|
_ecore_fps_debug_fd = -1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ecore_fps_runtime_mmap = mmap(NULL, sizeof(unsigned int),
|
|
|
|
PROT_READ | PROT_WRITE,
|
|
|
|
MAP_SHARED,
|
|
|
|
_ecore_fps_debug_fd, 0);
|
|
|
|
if (_ecore_fps_runtime_mmap == MAP_FAILED)
|
|
|
|
_ecore_fps_runtime_mmap = NULL;
|
2004-03-16 21:14:13 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_ecore_fps_debug_shutdown(void)
|
|
|
|
{
|
|
|
|
_ecore_fps_debug_init_count--;
|
|
|
|
if (_ecore_fps_debug_init_count > 0) return;
|
|
|
|
if (_ecore_fps_debug_fd >= 0)
|
|
|
|
{
|
2010-01-21 23:03:04 -08:00
|
|
|
char buf[4096];
|
|
|
|
const char *tmp;
|
2011-10-20 22:40:39 -07:00
|
|
|
int pid;
|
2007-08-26 04:17:21 -07:00
|
|
|
|
2008-05-25 22:16:34 -07:00
|
|
|
#ifndef HAVE_EVIL
|
2011-10-20 22:40:39 -07:00
|
|
|
tmp = "/tmp";
|
2007-10-27 03:58:00 -07:00
|
|
|
#else
|
2011-10-20 22:40:39 -07:00
|
|
|
tmp = (char *)evil_tmpdir_get ();
|
2008-05-25 22:16:34 -07:00
|
|
|
#endif /* HAVE_EVIL */
|
2011-10-20 22:40:39 -07:00
|
|
|
pid = (int)getpid();
|
2010-09-29 23:09:20 -07:00
|
|
|
snprintf(buf, sizeof(buf), "%s/.ecore_fps_debug-%i", tmp, pid);
|
|
|
|
unlink(buf);
|
|
|
|
if (_ecore_fps_runtime_mmap)
|
|
|
|
{
|
|
|
|
munmap(_ecore_fps_runtime_mmap, sizeof(int));
|
|
|
|
_ecore_fps_runtime_mmap = NULL;
|
|
|
|
}
|
|
|
|
close(_ecore_fps_debug_fd);
|
|
|
|
_ecore_fps_debug_fd = -1;
|
2004-03-16 21:14:13 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_ecore_fps_debug_runtime_add(double t)
|
|
|
|
{
|
2007-08-26 04:17:21 -07:00
|
|
|
if ((_ecore_fps_debug_fd >= 0) &&
|
2004-03-16 21:14:13 -08:00
|
|
|
(_ecore_fps_runtime_mmap))
|
|
|
|
{
|
2010-09-29 23:09:20 -07:00
|
|
|
unsigned int tm;
|
|
|
|
|
|
|
|
tm = (unsigned int)(t * 1000000.0);
|
|
|
|
/* i know its not 100% theoretically guaranteed, but i'd say a write */
|
|
|
|
/* of an int could be considered atomic for all practical purposes */
|
|
|
|
/* oh and since this is cumulative, 1 second = 1,000,000 ticks, so */
|
|
|
|
/* this can run for about 4294 seconds becore looping. if you are */
|
|
|
|
/* doing performance testing in one run for over an hour... well */
|
|
|
|
/* time to restart or handle a loop condition :) */
|
|
|
|
*(_ecore_fps_runtime_mmap) += tm;
|
2004-03-16 21:14:13 -08:00
|
|
|
}
|
|
|
|
}
|
2010-03-18 07:43:39 -07:00
|
|
|
|
|
|
|
#if HAVE_MALLINFO
|
2010-06-24 09:15:56 -07:00
|
|
|
static Eina_Bool
|
2010-03-18 07:43:39 -07:00
|
|
|
_ecore_memory_statistic(__UNUSED__ void *data)
|
|
|
|
{
|
|
|
|
struct mallinfo mi;
|
|
|
|
static int uordblks = 0;
|
|
|
|
static int fordblks = 0;
|
|
|
|
Eina_Bool changed = EINA_FALSE;
|
|
|
|
|
|
|
|
mi = mallinfo();
|
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
#define HAS_CHANGED(Global, Local) \
|
|
|
|
if (Global != Local) \
|
|
|
|
{ \
|
|
|
|
Global = Local; \
|
|
|
|
changed = EINA_TRUE; \
|
|
|
|
}
|
2010-03-18 07:43:39 -07:00
|
|
|
|
|
|
|
HAS_CHANGED(uordblks, mi.uordblks);
|
|
|
|
HAS_CHANGED(fordblks, mi.fordblks);
|
|
|
|
|
|
|
|
if (changed)
|
|
|
|
ERR("[%i] Memory total: %i, free: %i",
|
2010-09-29 23:09:20 -07:00
|
|
|
_ecore_memory_pid,
|
|
|
|
mi.uordblks,
|
|
|
|
mi.fordblks);
|
2010-03-18 07:43:39 -07:00
|
|
|
|
|
|
|
KEEP_MAX(_ecore_memory_max_total, mi.uordblks);
|
|
|
|
KEEP_MAX(_ecore_memory_max_free, mi.fordblks);
|
|
|
|
|
2010-06-24 09:15:56 -07:00
|
|
|
return ECORE_CALLBACK_RENEW;
|
2010-03-18 07:43:39 -07:00
|
|
|
}
|
2010-10-17 00:03:28 -07:00
|
|
|
|
2010-03-18 07:43:39 -07:00
|
|
|
#endif
|
2011-07-28 06:33:14 -07:00
|
|
|
|
2011-08-16 07:35:00 -07:00
|
|
|
static void
|
|
|
|
_ecore_main_loop_thread_safe_call(Ecore_Safe_Call *order)
|
|
|
|
{
|
|
|
|
Eina_Bool count;
|
|
|
|
|
|
|
|
eina_lock_take(&_thread_safety);
|
|
|
|
|
|
|
|
count = _thread_cb ? 0 : 1;
|
|
|
|
_thread_cb = eina_list_append(_thread_cb, order);
|
|
|
|
if (count) ecore_pipe_write(_thread_call, &wakeup, sizeof (int));
|
|
|
|
|
|
|
|
eina_lock_release(&_thread_safety);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_thread_safe_cleanup(void *data)
|
|
|
|
{
|
|
|
|
Ecore_Safe_Call *call = data;
|
|
|
|
|
|
|
|
eina_condition_free(&call->c);
|
|
|
|
eina_lock_free(&call->m);
|
|
|
|
}
|
|
|
|
|
2011-07-28 06:33:14 -07:00
|
|
|
static void
|
2011-10-20 22:40:39 -07:00
|
|
|
_thread_callback(void *data __UNUSED__,
|
|
|
|
void *buffer __UNUSED__,
|
2011-08-01 05:16:39 -07:00
|
|
|
unsigned int nbyte __UNUSED__)
|
2011-07-28 06:33:14 -07:00
|
|
|
{
|
2011-08-01 05:16:39 -07:00
|
|
|
Ecore_Safe_Call *call;
|
|
|
|
Eina_List *callback;
|
|
|
|
|
|
|
|
eina_lock_take(&_thread_safety);
|
|
|
|
callback = _thread_cb;
|
|
|
|
_thread_cb = NULL;
|
|
|
|
eina_lock_release(&_thread_safety);
|
2011-07-28 06:33:14 -07:00
|
|
|
|
2011-08-01 05:16:39 -07:00
|
|
|
EINA_LIST_FREE(callback, call)
|
2011-07-28 06:33:14 -07:00
|
|
|
{
|
2011-08-17 02:43:49 -07:00
|
|
|
if (call->suspend)
|
|
|
|
{
|
2011-09-15 04:15:46 -07:00
|
|
|
eina_lock_take(&_thread_mutex);
|
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
eina_lock_take(&call->m);
|
|
|
|
_thread_id = call->current_id;
|
2011-08-17 02:43:49 -07:00
|
|
|
eina_condition_broadcast(&call->c);
|
2011-10-20 22:40:39 -07:00
|
|
|
eina_lock_release(&call->m);
|
2011-08-17 02:43:49 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
while (_thread_id_update != _thread_id)
|
|
|
|
eina_condition_wait(&_thread_cond);
|
2011-08-17 02:43:49 -07:00
|
|
|
eina_lock_release(&_thread_mutex);
|
|
|
|
|
|
|
|
eina_main_loop_define();
|
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
eina_lock_take(&_thread_feedback_mutex);
|
2011-09-26 23:16:11 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
_thread_id = -1;
|
2011-09-26 23:16:11 -07:00
|
|
|
|
2011-10-20 22:40:39 -07:00
|
|
|
eina_condition_broadcast(&_thread_feedback_cond);
|
|
|
|
eina_lock_release(&_thread_feedback_mutex);
|
2011-09-15 04:15:46 -07:00
|
|
|
|
2011-08-17 02:43:49 -07:00
|
|
|
_thread_safe_cleanup(call);
|
|
|
|
free(call);
|
|
|
|
}
|
|
|
|
else if (call->sync)
|
2011-08-16 07:35:00 -07:00
|
|
|
{
|
|
|
|
call->data = call->cb.sync(call->data);
|
|
|
|
eina_condition_broadcast(&call->c);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
call->cb.async(call->data);
|
|
|
|
free(call);
|
|
|
|
}
|
2011-07-28 06:33:14 -07:00
|
|
|
}
|
|
|
|
}
|
2011-10-20 22:40:39 -07:00
|
|
|
|