From 776dc6abe678ec3d7614bd26d438073f864e9f7d Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Tue, 29 Mar 2016 14:47:22 +0100 Subject: bla --- src/Makefile_Eo.am | 2 + src/lib/eo/Eo.h | 30 ++++++-- src/lib/eo/eo.c | 27 +++++++- src/lib/eo/eo_add_fallback.c | 160 +++++++++++++++++++++++++++++++++++++++++++ src/lib/eo/eo_add_fallback.h | 22 ++++++ 5 files changed, 233 insertions(+), 8 deletions(-) create mode 100644 src/lib/eo/eo_add_fallback.c create mode 100644 src/lib/eo/eo_add_fallback.h diff --git a/src/Makefile_Eo.am b/src/Makefile_Eo.am index e388318e8d..82fd9779ab 100644 --- a/src/Makefile_Eo.am +++ b/src/Makefile_Eo.am @@ -31,6 +31,8 @@ lib/eo/eo_ptr_indirection.c \ lib/eo/eo_ptr_indirection.h \ lib/eo/eo_base_class.c \ lib/eo/eo_class_class.c \ +lib/eo/eo_add_fallback.c \ +lib/eo/eo_add_fallback.h \ lib/eo/eo_private.h lib_eo_libeo_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @EO_CFLAGS@ diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h index 13d82836fd..0c4a61df95 100644 --- a/src/lib/eo/Eo.h +++ b/src/lib/eo/Eo.h @@ -582,7 +582,7 @@ EAPI Eina_Bool _eo_call_resolve(Eo *obj, const char *func_name, Eo_Op_Call_Data EAPI void _eo_call_end(Eo_Op_Call_Data *call); // end of the eo_add. Calls finalize among others -EAPI Eo * _eo_add_end(Eo *obj); +EAPI Eo * _eo_add_end(Eo *obj, Eina_Bool is_fallback); EAPI Eo *eo_super(const Eo *obj, const Eo_Class *cur_klass); @@ -597,15 +597,33 @@ EAPI Eo *eo_super(const Eo *obj, const Eo_Class *cur_klass); */ EAPI const Eo_Class *eo_class_get(const Eo *obj); -#define eo_self __eo_self +EAPI Eo *_eo_self_get(void); -#define _eo_add_common(klass, parent, is_ref, ...) \ +/* Check if GCC compatible (both GCC and clang define this) */ +#if defined(__GNUC__) && !defined(_EO_ADD_FALLBACK_FORCE) + +# define eo_self __eo_self + +# define _eo_add_common(klass, parent, is_ref, ...) \ ({ \ - Eo * const __eo_self = _eo_add_internal_start(__FILE__, __LINE__, klass, parent, is_ref); \ + Eo * const __eo_self = _eo_add_internal_start(__FILE__, __LINE__, klass, parent, is_ref, EINA_FALSE); \ __VA_ARGS__; \ - (Eo *) _eo_add_end(eo_self); \ + (Eo *) _eo_add_end(eo_self, EINA_FALSE); \ }) +#else + +# define eo_self _eo_self_get() + +# define _eo_add_common(klass, parent, is_ref, ...) \ + ( \ + _eo_add_internal_start(__FILE__, __LINE__, klass, parent, is_ref, EINA_TRUE), \ + , ##__VA_ARGS__, \ + (Eo *) _eo_add_end(eo_self, EINA_TRUE) \ + ) + +#endif + /** * @def eo_add * @brief Create a new object and call its constructor(If it exits). @@ -644,7 +662,7 @@ EAPI const Eo_Class *eo_class_get(const Eo *obj); */ #define eo_add_ref(klass, parent, ...) _eo_add_common(klass, parent, EINA_TRUE, ##__VA_ARGS__) -EAPI Eo * _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo *parent, Eina_Bool ref); +EAPI Eo * _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo *parent, Eina_Bool ref, Eina_Bool is_fallback); /** * @brief Get a pointer to the data of an object for a specific class. diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index ba12fbd252..03771cfdeb 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -13,6 +13,7 @@ #include "Eo.h" #include "eo_ptr_indirection.h" #include "eo_private.h" +#include "eo_add_fallback.h" #define EO_CLASS_IDS_FIRST 1 #define EO_OP_IDS_FIRST 1 @@ -615,9 +616,16 @@ _eo_class_funcs_set(_Eo_Class *klass) } EAPI Eo * -_eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo *parent_id, Eina_Bool ref) +_eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo *parent_id, Eina_Bool ref, Eina_Bool is_fallback) { _Eo_Object *obj; + Eo_Call_Stack *stack = NULL; + + if (is_fallback) + { + stack->frame_ptr++; + stack->frame_ptr->obj = NULL; + } EO_CLASS_POINTER_RETURN_VAL(klass_id, klass, NULL); @@ -680,6 +688,11 @@ _eo_add_internal_start(const char *file, int line, const Eo_Class *klass_id, Eo return NULL; } + if (is_fallback) + { + stack->frame_ptr->obj = eo_id; + } + return eo_id; } @@ -726,11 +739,17 @@ cleanup: } EAPI Eo * -_eo_add_end(Eo *eo_id) +_eo_add_end(Eo *eo_id, Eina_Bool is_fallback) { Eo *ret = eo_finalize(eo_id); ret = _eo_add_internal_end(eo_id, ret); + if (is_fallback) + { + Eo_Call_Stack *stack = _eo_add_fallback_stack_get(); + stack->frame_ptr--; + } + return ret; } @@ -1595,6 +1614,8 @@ eo_init(void) _eo_class_isa_func(NULL, NULL, NULL); #endif + _eo_add_fallback_init(); + eina_log_timing(_eo_log_dom, EINA_LOG_STATE_STOP, EINA_LOG_STATE_INIT); @@ -1618,6 +1639,8 @@ eo_shutdown(void) EINA_LOG_STATE_START, EINA_LOG_STATE_SHUTDOWN); + _eo_add_fallback_shutdown(); + for (i = 0 ; i < _eo_classes_last_id ; i++, cls_itr++) { if (*cls_itr) diff --git a/src/lib/eo/eo_add_fallback.c b/src/lib/eo/eo_add_fallback.c new file mode 100644 index 0000000000..2adc39acff --- /dev/null +++ b/src/lib/eo/eo_add_fallback.c @@ -0,0 +1,160 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + +#if defined HAVE_DLADDR && ! defined _WIN32 +# include +#endif + +#include + +#include "eo_ptr_indirection.h" +#include "eo_private.h" + +#include "eo_add_fallback.h" + +// 1024 entries == 16k or 32k (32 or 64bit) for eo call stack. that's 1023 +// imbricated/recursive calls it can handle before barfing. i'd say that's ok +#define EO_CALL_STACK_DEPTH_MIN 1024 + +#define EO_CALL_STACK_SIZE (EO_CALL_STACK_DEPTH_MIN * sizeof(Eo_Stack_Frame)) + +static Eina_TLS _eo_call_stack_key = 0; + +#define MEM_PAGE_SIZE 4096 + +static void * +_eo_call_stack_mem_alloc(size_t size) +{ +#ifdef HAVE_MMAP + // allocate eo call stack via mmped anon segment if on linux - more + // secure and safe. also gives page aligned memory allowing madvise + void *ptr; + size_t newsize; + newsize = MEM_PAGE_SIZE * ((size + MEM_PAGE_SIZE - 1) / + MEM_PAGE_SIZE); + ptr = mmap(NULL, newsize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (ptr == MAP_FAILED) + { + ERR("eo call stack mmap failed."); + return NULL; + } + return ptr; +#else + //in regular cases just use malloc + return calloc(1, size); +#endif +} + +static void +_eo_call_stack_mem_free(void *ptr, size_t size) +{ +#ifdef HAVE_MMAP + munmap(ptr, size); +#else + (void) size; + free(ptr); +#endif +} + +static Eo_Call_Stack * +_eo_call_stack_create() +{ + Eo_Call_Stack *stack; + + stack = calloc(1, sizeof(Eo_Call_Stack)); + if (!stack) + return NULL; + + stack->frames = _eo_call_stack_mem_alloc(EO_CALL_STACK_SIZE); + if (!stack->frames) + { + free(stack); + return NULL; + } + + // first frame is never used + stack->frame_ptr = stack->frames; + + return stack; +} + +static void +_eo_call_stack_free(void *ptr) +{ + Eo_Call_Stack *stack = (Eo_Call_Stack *) ptr; + + if (!stack) return; + + if (stack->frames) + _eo_call_stack_mem_free(stack->frames, EO_CALL_STACK_SIZE); + + free(stack); +} + +static Eo_Call_Stack *main_loop_stack = NULL; + +#define _EO_CALL_STACK_GET() ((EINA_LIKELY(eina_main_loop_is())) ? main_loop_stack : _eo_call_stack_get_thread()) + +static inline Eo_Call_Stack * +_eo_call_stack_get_thread(void) +{ + Eo_Call_Stack *stack = eina_tls_get(_eo_call_stack_key); + + if (stack) return stack; + + stack = _eo_call_stack_create(); + eina_tls_set(_eo_call_stack_key, stack); + + return stack; +} + +Eo_Call_Stack * +_eo_add_fallback_stack_get(void) +{ + return _EO_CALL_STACK_GET(); +} + +EAPI Eo * +_eo_self_get(void) +{ + return _EO_CALL_STACK_GET()->frame_ptr->obj; +} + +Eina_Bool +_eo_add_fallback_init(void) +{ + if (_eo_call_stack_key != 0) + WRN("_eo_call_stack_key already set, this should not happen."); + else + { + if (!eina_tls_cb_new(&_eo_call_stack_key, _eo_call_stack_free)) + { + EINA_LOG_ERR("Could not create TLS key for call stack."); + return EINA_FALSE; + + } + } + + main_loop_stack = _eo_call_stack_create(); + if (!main_loop_stack) + { + EINA_LOG_ERR("Could not alloc eo call stack."); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +Eina_Bool +_eo_add_fallback_shutdown(void) +{ + if (_eo_call_stack_key != 0) + { + eina_tls_free(_eo_call_stack_key); + _eo_call_stack_key = 0; + } + + return EINA_TRUE; +} diff --git a/src/lib/eo/eo_add_fallback.h b/src/lib/eo/eo_add_fallback.h new file mode 100644 index 0000000000..976fc66b41 --- /dev/null +++ b/src/lib/eo/eo_add_fallback.h @@ -0,0 +1,22 @@ +#ifndef _EO_ADD_FALLBACK_H +#define _EO_ADD_FALLBACK_H + +#include +#include + +typedef struct _Eo_Stack_Frame +{ + Eo *obj; +} Eo_Stack_Frame; + +typedef struct _Eo_Call_Stack { + Eo_Stack_Frame *frames; + Eo_Stack_Frame *frame_ptr; +} Eo_Call_Stack; + +Eina_Bool _eo_add_fallback_init(void); +Eina_Bool _eo_add_fallback_shutdown(void); + +Eo_Call_Stack *_eo_add_fallback_stack_get(void); + +#endif -- cgit v1.2.1