Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 23 Jun 2000 18:45:32 +1000 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Matthew Dillon <dillon@apollo.backplane.com>
Cc:        Jason Evans <jasone@canonware.com>, Greg Lehey <grog@lemis.com>, Warner Losh <imp@village.org>, The Hermit Hacker <scrappy@hub.org>, freebsd-smp@FreeBSD.ORG
Subject:   Re: SP Patchset #1 up
Message-ID:  <Pine.BSF.4.21.0006231737460.1626-100000@besplex.bde.org>
In-Reply-To: <200006221558.IAA03062@apollo.backplane.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 22 Jun 2000, Matthew Dillon wrote:

> :You now have deadlock when the low level console i/o routines are
> :reentered for ddb i/o, since task switching is either impossible or
> :undesireable while ddb is active (it's essentially impossible if ddb
> :was entered via a breakpoint in the middle of task switching code).
> :
> :When task switching is possible to avoid deadlock on console i/o
> :resources, it may still be undesirable.  A printf from a high priority
> :interrupt task shouldn't have to wait for a printf from a low priority
> :task to complete.
> 
>     I don't follow.  Why do I have a deadlock?  This is SchedMutex I'm
>     talking about here, not GiantMutex.

mtx_enter_sched_quick() is mtx_enter(&SchedMutex, MTX_SPIN).

| /*
|  * mtx_enter()
|  * ...
|  *	WARNING: DO NOT PUT KERNEL PRINTFS IN THE SPIN CODE!, you may
|  *	create a recursion.
|  */

This warning gives another reason why ddb can't call locking functions.
Putting a breakpoint at a locking functions or wandering into a locking
function while single stepping will cause console i/o.

| static __inline void
| mtx_enter(struct mtx *mtp, int type)
| {
| 	u_int32_t newv;
| 
| 	newv = (u_int32_t)curproc | MTF_HELD;
| 	if ((mtp->mtx_lock & ~MTF_CONTESTED) == newv) {

Here is another reason why ddb can't call locking functions.  curproc
may be in the middle of being switched when a debugger trap occurs, so
ddb can't call anything that depends on it being valid.  SchedMutex may
be invalid for the same reason.

| 		++mtp->mtx_recurse;	/* bump recursion */

I'm not sure if this code is reached.  If it is, then we don't have
deadlock but we have the same bugs as for spltty() -- recursion is not
prevented recursion although some console i/o routines don't support it.
Many levels of recursion are possible:

  printf in process context
    --> interrupt ... printf in interrupt context
      --> higher priority interrupt ... printf in interrupt context
        ... even higher priority interrupts
          --> debugger trap ... debugger printf
	    --> fatal trap for bug in printf ... bogus printfs (should longjmp)
	      --> double fault for bug in fatal trap handler ... final printfs

If switching from a high priority interrupt task to a low priority one is
allowed, then the first few levels don't need to be supported.

| 	} else {
| 		if (atomic_cmpexg_int(&mtp->mtx_lock, 0, newv) != 0) {
| 			if (type & MTX_SPIN) {
| 				_mtx_enter_spin(mtp, newv);

If this code is reached, then it should spin for ever, since other tasks
should not run, even if there is another CPU for it to run on.

| 			} else {
| 				_mtx_enter_blocking(mtp, newv);
| 			}
| 		}
| 		mtp->mtx_type = type;	/* set the type after obtaining */
| 	}
| }

Bruce



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?Pine.BSF.4.21.0006231737460.1626-100000>