Hello.

On 17/12/12 10:07, Tom Hacohen wrote:
> Well. The code creates a lock per class and uses a global lock to handle
> the lock per class creation. It's needed because classes are actually
> created on the fly. Just reading through the code and seeing where it
> returns and when it's released and looks that it's just fine.
>
> I would recommend you to use a tool that actually shows the path of
> execution leading to the proclaimed error.

It actually does that. :) Here is an example trace:

ecore_anim.c:634: __builtin_expect( ( !!_my_class), 1) is false
ecore_anim.c:634: lk_init<2 is true
ecore_anim.c:634: !lk_init is false
ecore_anim.c:634: lk_init<2 is false
ecore_anim.c:634: Variable '_my_lock.mutex' is locked.
ecore_anim.c:634: Variable '_my_lock.mutex' was locked.

ecore_anim.c at line 634 contains the macro:
EO_DEFINE_CLASS(ecore_animator_class_get, &class_desc, EO_BASE_CLASS, NULL)

If we now look at the macro again with the trace in mind:
#define EO_DEFINE_CLASS(class_get_func_name, class_desc, parent_class, 
...) \
EAPI const Eo_Class * \
class_get_func_name(void) \
{ \
    const Eo_Class *_tmp_parent_class; \
    static volatile char lk_init = 0; \
    static Eina_Lock _my_lock; \
    static const Eo_Class * volatile _my_class = NULL; \
    if (EINA_LIKELY(!!_my_class)) return _my_class; \
    \
    eina_lock_take(&_eo_class_creation_lock); \
    if (!lk_init) \
       eina_lock_new(&_my_lock); \
    if (lk_init < 2) eina_lock_take(&_my_lock); \
    if (!lk_init) \
       lk_init = 1; \
    else \
      { \
         if (lk_init < 2) eina_lock_release(&_my_lock); \
         eina_lock_release(&_eo_class_creation_lock); \
         return _my_class; \
      } \
    eina_lock_release(&_eo_class_creation_lock); \
    _tmp_parent_class = parent_class; \
    _my_class = eo_class_new(class_desc, _tmp_parent_class, __VA_ARGS__); \
    eina_lock_release(&_my_lock); \
    \
    eina_lock_take(&_eo_class_creation_lock); \
    eina_lock_free(&_my_lock); \
    lk_init = 2; \
    eina_lock_release(&_eo_class_creation_lock); \
    return _my_class; \
}

One can the that _my_lock will be taken with lk_init < 2 true but not 
released with lk_init < 2 false. And as lk_init has the volatile keyword 
it can be changed without our knowing. So the analyser seem to have a 
valid case here as it can't understand what will happen to lk_init.

The real question now is if we can guarantee that lk_init will be <2 
also in the unlock case. I have no idea what tricks eo is playing here 
with the volatile variable so that is where you guys come into place. :)

regards
Stefan Schmidt

------------------------------------------------------------------------------
LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
Remotely access PCs and mobile devices and provide instant support
Improve your efficiency, and focus on delivering more value-add services
Discover what IT Professionals Know. Rescue delivers
http://p.sf.net/sfu/logmein_12329d2d
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to