I am developing a device driver on mac. my question is how can we make a device request asynchronous to synchronous. like i send a send encapsulated command to device and get it response using get encapsulated command after getting a notification on interrupt pipe. so how can i make my thread will wait until all above request is not completed (both send and get) .
问题:
回答1:
You'll probably have to be a bit more specific than that. But in general, if you need a thread to sleep until some function of yours is called on another thread, you can use xnu's event system. As this is a device driver, I assume you're using the I/O Kit - in that case, the IO Locks or IOCommandGates are the most appropriate.
Using explicit locks, in your driver instance, you'd have something like:
IOLock* lock;
bool cleared;
You'll initialise these somewhere:
lock = IOLockAlloc();
cleared = false;
Then, when your thread initiates some I/O:
IOLockLock(lock);
cleared = false;
startYourIO(yourCallbackFunction);
while (!cleared)
{
IOLockSleep(
lock,
&cleared, // using address of status variable as event
THREAD_UNINT);
}
IOLockUnlock(lock);
In yourCallbackFunction:
IOLockLock(lock);
cleared = true;
IOLockWakeup(
lock,
&cleared, // this must match the event pointer used in sleep
true); // flip to false to wake up all waiting threads, not just 1
IOLockUnlock(lock);
Obviously, if you have multiple simultaneous I/Os going, your status variable will need to be per-context, etc. And in the kernel, asynchronous design is often better than synchronous. But I assume you know all about this kind of general driver design and have weighed up the pros and cons.
The IOCommandGate
sleep/wake API is very similar and should be used if you're doing thread synchronisation on your IOWorkLoop
. If you're not using the I/O Kit, you may prefer to use the BSD-level lock/mutex API, which is what the IOLock is implemented on anyway.