mtx_init/lock_init and uninitialized struct mtx
Patrick Mahan
PMahan at adaranet.com
Thu Feb 24 17:51:47 UTC 2011
> -----Original Message-----
> From: owner-freebsd-hackers at freebsd.org [mailto:owner-freebsd-
> hackers at freebsd.org] On Behalf Of Dmitry Krivenok
> Sent: Thursday, February 24, 2011 7:47 AM
> To: freebsd-hackers at freebsd.org
> Subject: mtx_init/lock_init and uninitialized struct mtx
>
> Hello Hackers,
>
> Is it allowed to call mtx_init on a mutex defined as an auto variable
> and not initialized explicitly, i.e.:
>
> 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!
>
When dealing with stack variables, I always initialize them to a known state,
(mostly doing as you do above, with memset() though in the kernel I then to
use bzero())
Given that if it is global then it is either in .bss or in .data if it has
been initialized. If it is part of a structure then most often you zero out
the structure right after allocation. So there is an implicit assumption
that the structure will be zero'd before calling mtx_init().
Patrick
----------------------------------------------------
Patrick Mahan
Lead Technical Kernel Engineer
Adara Networks
Disclaimer: The opinions expressed here are solely the responsibility of the author and are not to be
construed as an official opinion of Adara Networks.
> --
> 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"
More information about the freebsd-hackers
mailing list