From owner-freebsd-smp Fri Oct 6 12:37:20 2000 Delivered-To: freebsd-smp@freebsd.org Received: from smtp05.primenet.com (smtp05.primenet.com [206.165.6.135]) by hub.freebsd.org (Postfix) with ESMTP id E4D6137B503; Fri, 6 Oct 2000 12:37:15 -0700 (PDT) Received: (from daemon@localhost) by smtp05.primenet.com (8.9.3/8.9.3) id MAA27363; Fri, 6 Oct 2000 12:37:04 -0700 (MST) Received: from usr05.primenet.com(206.165.6.205) via SMTP by smtp05.primenet.com, id smtpdAAALHaGK0; Fri Oct 6 12:34:50 2000 Received: (from tlambert@localhost) by usr05.primenet.com (8.8.5/8.8.5) id MAA20583; Fri, 6 Oct 2000 12:34:19 -0700 (MST) From: Terry Lambert Message-Id: <200010061934.MAA20583@usr05.primenet.com> Subject: Re: Problems with kthread_exit() and SMPng To: ticso@cicely5.cicely.de (Bernd Walter) Date: Fri, 6 Oct 2000 19:34:14 +0000 (GMT) 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) In-Reply-To: <20001006123053.A42012@cicely5.cicely.de> from "Bernd Walter" at Oct 06, 2000 12:30:53 PM X-Mailer: ELM [version 2.5 PL2] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: owner-freebsd-smp@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org > > 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