Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 05 Mar 2003 13:55:43 -0500 (EST)
From:      John Baldwin <jhb@FreeBSD.org>
To:        Nate Lawson <nate@root.org>
Cc:        src-committers@FreeBSD.org, cvs-src@FreeBSD.org, cvs-all@FreeBSD.org
Subject:   Re: cvs commit: src/sys/kern kern_mutex.c
Message-ID:  <XFMail.20030305135543.jhb@FreeBSD.org>
In-Reply-To: <Pine.BSF.4.21.0303051002540.82805-100000@root.org>

next in thread | previous in thread | raw e-mail | index | archive | help

On 05-Mar-2003 Nate Lawson wrote:
> On Wed, 5 Mar 2003, John Baldwin wrote:
>> If they want to block on a lock they should use mtx_lock().  Cases
>> where one might use mtx_trylock() that I can think of is for
>> optional optimizations for cases that might otherwise be a lock
>> order violation.  I.e., if I can lock two X objects, then I can
>> bypass having to lock one, stick it on a queue so that some other
>> thread can connect it to the other.  The only time I have used it
>> is in the OOM killer where I need to be able to lock a process I
>> am checking while keeping the current target process locked for
>> the whole loop.  Really, I want the programmer to think carefully
>> when they use mtx_trylock() and blindly recursing on a lock might
>> result in some hard to track down bugs.
> 
> I have a situation where I am not quite sure if mtx_trylock() is the right
> answer.  There is a single-phase process for SCSI target instances where
> you create a named endpoint and then enable traffic to it.  On the disable
> route, it is 2-phase where you disable traffic and abort all outstanding
> commands.  Later, you close the device and the endpoint is freed.  The
> endpoint needs to stay allocated to accept freed resources as they are
> released by aborted commands.
> 
> My issue is with contention for a named endpoint.  If one thread enables
> traffic to an endpoint and then disables it, it still has the endpoint
> allocated.  If another thread tries to enable the same endpoint, it needs
> to lock the OTHER endpoint, check if it's disabled (freeing it if it is),
> and then unlock it.  My current locking approach is to lock my own softc,
> lock the driver global mtx, and then lock the OTHER thread's softc before
> checking if it is enabled.

This last bit is a reversal.  What if your two threads each have two
different endpoints and contend against each other, how would you prevent
the deadlock?  (i.e. thread A locks A softc, global, block on B softc, while
thread B locks B softc and blocks on global).  My lack of CAM is probably
going to show in this next question, but it seems that you have this endpoint
object that both the thread has a pointer to, and CAM has a name table with
a pointer to.  Why can't you just tell CAM to change its pointer for the
given name to yours and leave the old endpoint alone if it's disabled?
The old thread can free the data structure later when the device is
closed.  I suppose you need to be able to read the flag to see if it is
disabled or not.  One trick you can do that for case is to require that
both the softc lock of the owning thread and the global lock be held when
that flag is set and then either lock alone is sufficient to test the state
of the flag.  I'm not sure I have a firm understanding of what exactly you
are trying to accomplish though.  I wonder why you can't leave the state
of enabled/disabled in the actual periph and just move the single periph
around between threads.

-- 

John Baldwin <jhb@FreeBSD.org>  <><  http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve!"  -  http://www.FreeBSD.org/

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




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