Hi,

On Tue, Dec 18, 2012 at 7:49 AM, Stefan Schmidt <s.schm...@samsung.com> wrote:
> 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.

Well, if lk_init < 2 is false then _my_class should be set and we
return it with "if (EINA_LIKELY(!!_my_class)) return _my_class;" and
that's it. And volatile in this case just tells the compiler to fetch
the operand from memory every time which disables some optimizations
like leaving it in a register. And do we even need it to be volatile?
It might be the case we don't need this modifier as it's protected by
_eo_class_creation_lock.

> 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. :)

I do think we have this guarantee because like I said lk_init is
protected by _eo_class_creation_lock. I do think we have a false
positive and the code looks "right" regarding taking and releasing
locks. However, why do we need 2 locks? Can't we just use
_eo_class_creation_lock? It seems lk_init and _my_lock just exist to
do this "2 stage" class creation where you drop
_eo_class_creation_lock when you "don't need it anymore". Right?
Please tell me if I'm missing anything.

Thanks,

-- 
Ulisses Furquim
ProFUSION embedded systems
http://profusion.mobi
Mobile: +55 19 9250 0942
Skype: ulissesffs

------------------------------------------------------------------------------
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