Subject: Re: sysmon vs mutexes
To: Andrew Doran <>
From: Bill Studenmund <>
List: tech-kern
Date: 02/19/2007 13:49:22
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Mon, Feb 19, 2007 at 08:45:34PM +0000, Andrew Doran wrote:
> On Mon, Feb 19, 2007 at 07:38:52PM +0100, Juan RP wrote:
> > But this way seems not the correct way to initialize the mutexes,
> > because right now I'm using a function for initialization and I run
> > it in the functions that were having errors.
> >=20
> > I would like to know if there's a better way to make them work
> > correctly... do you have any suggestion or comment?
> Basically, the problem here is that we want to replace the static
> initializers (SIMPLELOCK_INITIALIZER and friends) with dynamic
> initialization, so calls to mutex_init().
> mutex_init() needs to be done at run time so that when the kernel is built
> with the LOCKDEBUG option, we can allocate a unique ID for every lock in =
> system. The basic idea is that the size of a kmutex_t or krwlock_t will
> never change, regardless of what options the kernel was compiled with.
> That's useful for LKMs and for kernel grovellers like vmstat.
> There is no one clear place in this code where the locks can be initializ=
> dynamically. There are a few ways around it that have been suggested:
> o Provide static initializers. This is a problem where lock init needs to=
>   something more complicated than just setting up the structure, as is the
>   case now.
> o Provide static initializers, but set in dummy values, and have the first
>   call to mutex_enter() or similar set up the lock. I don't think this one
>   is possible, because mutex_init() may need to allocate memory, and so m=
>   need to sleep or take other locks.

Ok. I've been thinking about this. Sleeping isn't a problem. If the lock=20
call could have slept to get the lock, I think it's fine to sleep to init=
the mutex.

I'm not sure if we have a try-lock equivalent or not. If we do, we can=20
just report that it doesn't succeed on an uninitialized lock. Usually code=
that does a try-lock tries, and if it has to do the slow path, it then=20
does things so that it can sleep (and so it can cope w/ sleeping to get a=

This all may be moot though, depending on what locks have to be taken.=20
Simply put, you should only be able to auto-init a lock if locking is such=
that it's ok to allocate while aquiring.

However as long as we aren't holding any higher-priority locks while=20
trying the init, we should be ok iff we don't use auto-init in either the=
scheduler code or the vm code. Put another way, as long as we don't=20
auto-init (static initialize that triggers dynamic initialization) when we=
can't allocate memory, we're ok.

> o Use linksets. I don't like linksets; I think that they are somewhat LKM
>   unfriendly, and make providing a stable kernel API harder. I much prefer
>   that we have defined entry points for each LKM / code module and e.g.
>   device instance where we set things up at runtime.
> o Use RUN_ONCE() (from sys/once.h), and call an init function on every
>   entry into the sysmon driver. I'm not fond of this one; it seems
>   like a lot of unnecessary overhead.
> o Figure out a way to provide an initialization function for envsys that
>   gets called at boot/attach time. It's a character device, so there shou=
>   be a common attach point we can use where we rely on autoconf to provide
>   the necessary serialization, until the device/module has it's own lock(=
>   set up. I'm of the opinion that this the best way to handle it. I'll ha=
>   a look for a place where we can provide such a function.
> What do people think about the general issues involved? Any other suggest=
> about the problem at hand (envsys)?

The last option may well be the best one for now. But I think we may want=
to look at static init options. I think it's fine for us to have=20
restrictions on when static-init locks aren't ok.

Take care,


Content-Type: application/pgp-signature
Content-Disposition: inline

Version: GnuPG v1.4.3 (NetBSD)