locking in a device driver

Sergey Babkin babkin at verizon.net
Thu Nov 3 04:57:43 PST 2005

>From: "M. Warner Losh" <imp at bsdimp.com>
>            Scott Long <scottl at samsco.org> writes:
>: Dinesh Nair wrote:
>: > 
>: > 
>: > On 11/03/05 03:12 Warner Losh said the following:
>: > 
>: >> Yes.  if you tsleep with signals enabled, the periodic timer will go
>: >> off, and you'll return early.  This typically isn't what you want
>: >> either.
>: > 
>: > 
>: > looks like i've got a lot of work to do, poring thru all the ioctls for 
>: > the device and trying to use another method to wait instead of tsleep().
>: Note that a thread can block on select/poll in 4.x and still allow other
>: threads to run.  I used this to solve a very similar problem to your in
>: a 4.x app of mine.  I have the app thread wait on select() on the device
>: node for the driver.  When the driver gets to a state when an ioctl
>: won't block (like data being available to read), then it does the
>: appropriate magic in it's d_poll method.  select in userland sees this,
>: allows the thread to resume running, and the thread then calls ioctl.
>: Of course you have to be careful that you don't have multiple threads
>: competing for the same data or that the data won't somehow disappear
>: before the ioctl call runs.  But it does work.  Look at the aac(4)
>: driver for my example of this.
>Yes.  If you have the ability to know that an ioctl won't block before
>you call it, that would work too.  This method is a little trickier,
>like you say, but can be made to work.  I've also seen ioctls that

Maybe it can be fixed in the kernel without
too much trouble. Basically, the trick would be 
to start another kernel thread  when the first 
one blocks. Then the original one can be left 
executing the ioctl while the new one continues 
the work. Then of cours ethere should be some 
notification mechanism that the ioctl has 

The new thread can start in a signal handler,
kind of like what UnixWare does (and I believe
Solaris too): they have an M:N model where M
user threads are scheduled on N kernel threads.
When all the kernel threads of a process get 
blocked, a signal is sent thread which handler
then starts a new kernel thread if there
are any runnable user threads.

Hm, suppose we have a per-process property "is 
threaded" that would be set by the threads library. Any
blocking calls (tsleep() and such) would check it,
and if it's set than immediately post this "all
threads are blocked" signal. Then the library can
catch it and handle in some useful way, maybe
doing an rfork() or just running another user thread
and returning to this one later.


More information about the freebsd-hackers mailing list