Re: Wait Queues
Re: Wait Queues
- Subject: Re: Wait Queues
- From: Vivek Balasubramanyam <email@hidden>
- Date: Wed, 5 Mar 2003 12:38:11 -0800
It's a software modem driver. Most of the driver was written using
IOKit, but we have some logging and status monitoring functionality
that I was hoping not to have to rewrite. We accomplished this on
Linux by creating and feeding character devices from inside the driver,
so that a user-level script could pipe those device files to a screen
or regular file. I've taken that code, which uses wrapper functions
(prefixed by 'lkvi') around anything OS-specific, and tried to rewrite
the specific code to use BSD/mach equivalents.
When I load the driver, a status char device gets created. If I try to
do a "cat /dev/status_device", this locks the system in the device Read
function, which includes this while loop:
while (1)
{
/* synchronize with other reads */
while(lkvi_use_lock_use_when_unused(&(device->rLock)) != 0) {};
bytesAvailable = device->bufWrIdx - device->bufRdIdx;
if (bytesAvailable < 0)
bytesAvailable += device->bufSize;
if ((device->buf != NULL) &&
((bytesAvailable > 0) || (device->flags &
SMD_OUTPUT_DEVICE_FLAG_TRAILING_EOF)))
break; /* keep the lock since we'll need it anyway */
lkvi_use_lock_unuse(&(device->rLock));
/* SMD_PRINT_DEBUG_INFO (("Going to sleep")); */
lkvi_wait_queue_sleep_interruptible (&device->readQueue);
/* SMD_PRINT_DEBUG_INFO (("Woken up")); */
}
A function internal to the driver writes to device->buf. We use
separate read and write locks, although in OS X there will only be one
reader and one writer, and the circular buffer code is written so that
reads and writes don't need to be atomic (writing only modifies the
write pointer, and reading only modifies the read pointer). I also
don't know much about character devices, so I assume that the read
function must be all-or-nothing. This is why I wait in the first place.
I am definitely not giving up the CPU, although I expected that the
assert_wait() function would put my thread to sleep. Are you saying
that I need to call thread_block() in addition to assert_wait() in
order to fall asleep?
There isn't a specific need to use wait queues over any other kind of
synchronization, since only one thread is ever in the queue. But I do
need to use something that will let this thread sleep until a separate
thread sends a wakeup signal (when the buffer goes from empty to
non-empty).
Thanks for your help,
Vivek
On Wednesday, March 5, 2003, at 11:47 AM, Jim Magee wrote:
On Wednesday, March 5, 2003, at 01:37 PM, Vivek Balasubramanyam wrote:
Hi. I'm porting some driver code from Linux, and having trouble
using the wait_queue API (in kern/wait_queue.h).
I use "wq = wait_queue_alloc(SYNC_POLICY_FIFO);" to set things up,
"wait_queue_assert_wait(&wq, NO_EVENT, THREAD_INTERRUPTIBLE)" to add
my single thread to the queue, and wakeup_one to wake it up.
It looks like my driver is locking the machine in a loop containing
the assert_wait() call:
while (1)
{
..check if there's data ready to be processed..
..if so, break
..else, assert_wait
}
The waiting thread is only woken up by me when new data is ready to
be processed, and yet execution in this thread never leaves that >> loop.
I haven't been able to find much information on wait_queues. Is
there something obvious I'm missing about their initialization or >> use?
What kind of driver are you porting. Usually, higher level
synchronization is used in drivers (command gates in IOKit drivers,
tsleep is BSD drivers, etc...). The wait_queue mechanism is pretty
low-level for drivers.
Wait queues alone are not enough to provide the synchronization that
the code above needs. You must use some sort of lock to protect the
atomicity of the "check if there's data, otherwise assert_wait"
operation. Once you have firmly asserted your intention to wait, you
can unlock whatever form of lock you chose and then volunteer to give
up the CPU (when working at this low a level, that would usually be
with thread_block()).
It sounds like you aren't giving up the CPU (and therefore would only
get taken off the CPU to be preempted by a realtime thread).
--Jim
_______________________________________________
darwin-kernel mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/darwin-kernel
Do not post admin requests to the list. They will be ignored.