Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 6 Oct 2000 19:34:14 +0000 (GMT)
From:      Terry Lambert <tlambert@primenet.com>
To:        ticso@cicely5.cicely.de (Bernd Walter)
Cc:        tlambert@primenet.com (Terry Lambert), jhb@FreeBSD.ORG (John Baldwin), jburkhol@home.com (Jake Burkholder), bp@butya.kz (Boris Popov), freebsd-smp@FreeBSD.ORG, mark@grondar.za (Mark Murray)
Subject:   Re: Problems with kthread_exit() and SMPng
Message-ID:  <200010061934.MAA20583@usr05.primenet.com>
In-Reply-To: <20001006123053.A42012@cicely5.cicely.de> from "Bernd Walter" at Oct 06, 2000 12:30:53 PM

next in thread | previous in thread | raw e-mail | index | archive | help
> > Holding multiple mutexes should only  ever occur when doing
> > list or other multiple pointer manipulation which needs to be
> > done in such a way as to appear atomic, so this is pretty
> > much a bogus argument.
> 
> Which I understand as:
> Don't call another driver while owning a mutex because you never
> know what it might be waiting for.

I'd say "don't call a function holding a mutex", but would
grudgingly tolerate functions whose only purpose was a common
data manipulation -- though I'd point out that they would be
better done either as inlines or as macros instead (e.g. NDINIT()).

> Giant is an exeption for this rule.

It's orthogonal.  People want to keep the giant lock, and they
want to use mutexes; the two are not in the same collision
domain.  I would pretty much say "never do this" or "do this at
your peril, and if you accept the peril, then document it for
others".


> The ugly point here is that I never thought about printf to be a call
> to another driver.

Any driver that calls printf is going to end up calling the
console driver, sooner or later.

The way to deal with this is really a mutex and a condition
variable, since debugging really wants to wait until the console
has displayed the message before going on to code that could
crash the machine.  For things you don't care about, you could
have either a different call (an async printf) or a flag you
pass as one of the arguments.  Debugging flags would override
this and synchronize the I/O despite the flag/entry point, by
making the caller wait on the condition variable, which would
indicate that the message had been successfully written to the
console.

It's pretty trivial to implement this, even with multiple
callers, since you would make the condition variable be
monotonically increasing, and wait on the queued even order
since boot, so that multiple callers could wait simultaneously
and be awakened in FIFO order.  This would mean another
counter to track the queue head next order assignment number,
since otherwise, you would only be able to support a depth of
one.  This would be incremented automatically by the caller
while the mutex was held, giving the value that the condition
variable will have after the message has been output, and the
caller should continue (increments occur in both the sync and
async cases, of course; in the async case, it merely doesn't
wait for the condition variable to catch up).

The code itself would change the printf call to XDR the
arguments to printf into queue elements, mutex protect the
queue, do the insert, release the mutex, and return (async
case; the sync case would want an atomic release the mutex and
wait on condition variable).

The kernel thread which would take over responsibility for
displaying data on the console would acquire the mutex, dequeue
an entry, release the mutex, process the output to completion,
acquire the mutex, increment and trigger the condition variable,
release the mutex.

Pretty trivial, and no recursion problems and no giant lock
problems.

The only remaining implementation details to decide would be
whether the caller allocated and printf free the queue
elements from/to main memory or a free list, if a free list
would be fixed size or grow, and what to do with a fixed
size freelist when the list was empty and a caller attempted
to queue a display request.


> > Grab the printf mutex, queue the request, release the printf
> > mutex.  A mutex protexts data structure manipulations (in this
> > example, the events queued for console display), _not_ code.
> 
> I agree but actually Giant is used to protect old code.

Irrelevent, I think, if he only legitimate entrypoint for
displaying console data was the call queue.

As I said previously, this would be very useful going forward,
if call queues could be generalized so that everyone could use
them.  It seems to me that they would be particularly useful
for communication between top and bottom drivers, and similar
situations.


					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-smp" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200010061934.MAA20583>