IOLockWakeup 和 IOLockSleep

IOLockWakeup and IOLockSleep

我很好奇传递给 IOLockWakeupIOLockSleep{Deadline} 的事件参数。

我知道事件是传递给两个函数的地址。我假设这个地址基本上是用来通知线程的。

所以我的问题是:假设 i 是一个 int,并且我们正在使用它的地址,这些函数如何知道何时休眠和唤醒?

假设:

当我们继续调用这些函数(在工作循环上下文中)时,事件参数的内容会在调用 iolocksleep* 时(以及唤醒时)自动设置为零,因为 iolockwakeup 可能会将其更改为非零值?

您会注意到 event 参数是 void* 类型,而不是 int*:

int IOLockSleep( IOLock * lock, void *event, UInt32 interType);

事件参数是一个任意指针,它永远不会被取消引用,并且存储在那里的内容无关紧要,它纯粹用于识别目的:所以例如不要传递 NULL,因为那不是一个独特的价值。

IOLockSleep 总是挂起 运行 线程,IOLockWakeup 唤醒任何在该地址上休眠的线程。如果没有这样的线程在等待,则什么也不会发生。这就是为什么您通常希望将 sleep/wakeup 与某些受锁保护的条件配对,并在持有锁的同时发送唤醒 - 要避免的事情是在发送唤醒后进入睡眠状态,其中万一您的休眠线程可能永远休眠。

因此,您将有一些条件来决定是否睡眠,并且您将在调用唤醒之前更新该条件,同时持有锁:

IOLock* myLock;
bool shouldSleep;

…

    // sleep code:
    IOLockLock(myLock);
    while (shouldSleep)
    {
        IOLockSleep(myLock, &shouldSleep, THREAD_UNINT);
    }
    IOLockUnlock(myLock);

…

    // wakeup code:
    IOLockLock(myLock);
    shouldSleep = false;
    IOLockWakeup(myLock, &shouldSleep, true /* or false, if we want to wake up multiple sleeping threads */);
    IOLockUnlock(myLock);

在这里,我使用了 shouldSleep 的地址作为事件参数,但这可以是任何东西,使用它很方便,因为我知道没有其他 kext 会使用该指针,因为没有其他 kext 可以访问该变量。