need for another mutex type/flag?
Robert Watson
rwatson at FreeBSD.org
Tue Jan 27 12:09:22 PST 2009
On Tue, 27 Jan 2009, Julian Elischer wrote:
> Robert Watson wrote:
>> On Sun, 25 Jan 2009, Julian Elischer wrote:
>>
>>> Even purely documentary would be good but given the option, I'd like it to
>>> scream when Witness is enabled and you try get another mutex....
>>>
>>> there are certain contexts (e.g. in most netgraph nodes) where we really
>>> want the authors to only take such locks and taking more unpredictable
>>> mutexes plays havoc with netgraph response times as a system as a whole,
>>> since if one node blocks, teh thread doesn't get to go off and service
>>> other nodes.
>>
>> I thought lots of Netgraph nodes liked to do things like call m_pullup()
>> and m_prepend()? Disallowing acquiring mutexes will prevent them from
>> doing that.
>
> I think I mentioned that in another mail. The problem I see is that some
> module writers are tempted to just use a mutex in their node without
> thinking about what the result will be. My understanding is that the mbuf
> allocation code has been tuned to within an inch of its life to try keep
> it's waits to a minimum. I am worried about it, but I am more worried about
> a netgraph node waiting on something that is depending on some piece of
> hardware such as what I think HPS had in his suggested patch for the
> bluetooth code..
Right, but what I'm saying is: if we have a MTX_LEAFNODE flag for mtx_init(9),
it won't work for any code that holds the lock over a call to the mbuf
routines. I am happy with us adding a MTX_LEAFNODE flag and would use it
myself, I just not sure it will work for Netgraph node mutexes.
The case you're talking about is generally problematic for mutexes anyway --
in principle we divide the world of sleeping into two categories: sleeps of
strictly "bounded" length that generall correspond to the sleeps associated
with mutex or rwlock acquire, and sleeps of potentially "unbounded" length,
such as those associated with msleep(9), cv_wait(9), sx(9), lockmgr(9), etc.
If you try to perform an unbounded sleep while holding a mutex, then WITNESS
will already complain about sleeping while holding a lock.
The tricky case is the "may sleep" case, in which case we already have a
WITNESS call you can do to say this code may sleep, even though it doesn't in
the common case, so warn if this is called with a mutex held so that we can
catch that happening". For example, mb_reclaim does this so that any attempt
to call it with a mutex held will throw up a red flag:
/*
* This is the protocol drain routine.
*
* No locks should be held when this is called. The drain routines have to
* presently acquire some locks which raises the possibility of lock order
* reversal.
*/
static void
mb_reclaim(void *junk)
{
struct domain *dp;
struct protosw *pr;
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK | WARN_PANIC, NULL,
"mb_reclaim()");
for (dp = domains; dp != NULL; dp = dp->dom_next)
for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++)
if (pr->pr_drain != NULL)
(*pr->pr_drain)();
}
If there is a common or unconditional call to msleep(9) in code called by
Netgraph with a mutex held, however, then it should already be displaying a
warning when that happens. If you want to simulate this effect without a lock
necessarily be held, you can do what the softclock() code does:
THREAD_NO_SLEEPING();
c_func(c_arg);
THREAD_SLEEPING_OK();
This causes WITNESS to complain loudly if the callout handler attempts to
perform an unbounded sleep (i.e., msleep(), cv_wait(), etc). Splitting the
world into bounded an unbounded sleeps is quite useful, and is entirely about
the sort of deadlock/cascading delay scenario you have in mind: code inside a
mutex-protected block is essentially a critical section, and should never wait
a long time, especially given that ithreads may acquire mutexes leading to
potential deadlocks if msleep() is effectively waiting on an interrupt that
will never be delivered -- if we allow ithreads to wait on msleep(), which we
don't because of the above mechanisms.
Robert N M Watson
Computer Laboratory
University of Cambridge
More information about the freebsd-arch
mailing list