Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Apr 2011 09:42:03 -0400
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-hackers@freebsd.org
Cc:        Bartosz Fabianowski <freebsd@chillt.de>
Subject:   Re: Is there some implicit locking of device methods?
Message-ID:  <201104260942.03543.jhb@freebsd.org>
In-Reply-To: <4DB695DB.1080505@chillt.de>
References:  <4DB695DB.1080505@chillt.de>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tuesday, April 26, 2011 5:52:27 am Bartosz Fabianowski wrote:
> Hi list
> 
> I am trying to move a device driver out from under Giant on 8-STABLE. 
> The driver has the usual probe/attach/detach and 
> open/close/read/ioctl/poll/purge methods. So far, all were protected by 
> each other by Giant. With that disabled, I am wondering whether I need 
> to guard against scenarios like the following:
> 
> 1. attach() is running and executes make_dev(). Before attach() has 
> finished, someone calls open() on the newly created device node and 
> tries to read from a device that is not fully instantiated.
> 
> 2. read() is running when the device is suddenly pulled (this is a USB 
> device) so that detach() gets run. Thus, detach() starts tearing down 
> data structures that read() may still be accessing.
> 
> 3. attach() is running when the device is pulled again, triggering 
> detach(). Now, attach() and detach() are running concurrently, the first 
> one initializing data structures and the second one tearing them down again.
> 
> Obviously, I can avoid races under these conditions by protecting each 
> of the above functions with a mutex. What puzzles is me is that no other 
> device seems to be doing this. There never is a mutex involved in any 
> attach(), detach(), open() methods... Is there some kind of implicit 
> locking going on that I am not aware of? Are DEVMETHODs automatically 
> protected from each other and the world? Are methods referenced by a 
> struct cdevsw similarly protected from each other somehow?

The probe/attach/detach stuff is still under Giant.  However, you will have to 
do your own locking to handle races.  Many of these races can be handled 
without locks however:

 - Don't call make_dev() until your device is fully ready in attach() (e.g.
   at the end.. NIC drivers tend to call ether_ifattach() as the very last
   thing for this same reason).
 - Call destroy_dev() as the first thing in detach.  destroy_dev() will block
   until any calls to your cdevsw routines return (so if a thread is in read()
   when detach happens, destroy_dev() will hang until your read() call
   returns).  Note that if you need to wake up waiting threads when
   destroy_dev() is called, you can provide a d_purge method in your cdevsw.
   This function is called from destroy_dev() every 100 milliseconds in a loop
   while there are waiting threads.
 - The Giant protection for new-bus should prevent attach/detach from running
   concurrently I believe (either that or the USB bus itself should ensure
   that the two instances of your device have seperate device_t instances with
   separate softc's, so current attach/detach should not matter except that
   they may both try to talk to the same hardware perhaps?  In that case that
   is something the USB bus driver should fix by prevent a device from
   attaching at an existing address until any existing device at that address
   is fully detached).

-- 
John Baldwin



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