mtx_init/lock_init and uninitialized struct mtx

Dmitry Krivenok krivenok.dmitry at gmail.com
Thu Feb 24 20:43:55 UTC 2011


Thanks a lot for your answers!

I'll always explicitly zero stack variables before calling actual
*_init() functions.
Also, it would be great to document this "zeroing" requirement in a
man page for mtx_init()
or simply add a comment in the source.

Dmitry


On Thu, Feb 24, 2011 at 10:02 PM, John Baldwin <jhb at freebsd.org> wrote:
> On Thursday, February 24, 2011 10:47:27 am Dmitry Krivenok wrote:
>> Hello Hackers,
>>
>> Is it allowed to call mtx_init on a mutex defined as an auto variable
>> and not initialized explicitly, i.e.:
>
> It does expect you to zero it first.  I've considered adding a MTX_NEW flag to
> disable this check for places where the developer knows it is safe.  Most
> mutexes are allocated in an already-zero'd structure or BSS as Patrick noted,
> so they are already correct.  It is a trade off between catching double
> initializations and requiring extra M_ZERO flags or bzero() calls in various
> places.
>
>> static int foo()
>> {
>>    struct mtx m;  // Uninitialized auto variable, so it's value is
> undefined.
>>    mtx_init(&m, "my_mutex", NULL, MTX_DEF);
>>    …
>>    // Do something
>>    ...
>>    mtx_destroy(&m);
>>    return 0;
>> }
>>
>> I encountered a problem with such code on a kernel compiled with
>> INVARIANTS option.
>> The problem is that mtx_init calls lock_init(&m->lock_object) and
>> lock_init, in turn, calls:
>>
>>  79         /* Check for double-init and zero object. */
>>  80         KASSERT(!lock_initalized(lock), ("lock \"%s\" %p already
>> initialized",
>>  81             name, lock));
>>
>> lock_initialized() just checks that a bit is set in lo_flags field of
>> struct lock_object:
>>
>> 178 #define lock_initalized(lo)     ((lo)->lo_flags & LO_INITIALIZED)
>>
>> However, the structure containing this field is never initialized
>> (neither in mtx_init nor in lock_init).
>> So, assuming that the mutex was defined as auto variable, the content
>> of lock_object field of struct mtx
>> is also undefined:
>>
>>  37 struct mtx {
>>  38         struct lock_object      lock_object;    /* Common lock
>> properties. */
>>  39         volatile uintptr_t      mtx_lock;       /* Owner and flags. */
>>  40 };
>>
>> In some cases, the initial value of lo_flags _may_ have the
>> "initialized" bit set and KASSERT will call panic.
>>
>> Is it user's responsibility to properly (how exactly?) initialize
>> struct mtx, e.g.
>> memset(&m, '\0', sizeof(struct mtx));
>>
>> Or should mtx_init() explicitly initialize all fields of struct mtx?
>>
>> Thanks in advance!
>>
>> --
>> Sincerely yours, Dmitry V. Krivenok
>> e-mail: krivenok.dmitry at gmail.com
>> skype: krivenok_dmitry
>> jabber: krivenok_dmitry at jabber.ru
>> icq: 242-526-443
>> _______________________________________________
>> freebsd-hackers at freebsd.org mailing list
>> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
>> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe at freebsd.org"
>>
>
> --
> John Baldwin
>



-- 
Sincerely yours, Dmitry V. Krivenok
e-mail: krivenok.dmitry at gmail.com
skype: krivenok_dmitry
jabber: krivenok_dmitry at jabber.ru
icq: 242-526-443


More information about the freebsd-hackers mailing list