Thread should wait for commplete the device reques

2020-05-04 19:15发布

问题:

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.