IOLockWakeup 和 IOLockSleep
IOLockWakeup and IOLockSleep
我很好奇传递给 IOLockWakeup
和 IOLockSleep{Deadline}
的事件参数。
我知道事件是传递给两个函数的地址。我假设这个地址基本上是用来通知线程的。
所以我的问题是:假设 i 是一个 int,并且我们正在使用它的地址,这些函数如何知道何时休眠和唤醒?
假设:
- 当调用
IOLockWakeup
时,事件的内容为 0(然后变为非零值),并且
- 调用
IOLockSleepDeadline
时,调用时事件的内容为0,将停止休眠,因为内容不为零
当我们继续调用这些函数(在工作循环上下文中)时,事件参数的内容会在调用 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 可以访问该变量。
我很好奇传递给 IOLockWakeup
和 IOLockSleep{Deadline}
的事件参数。
我知道事件是传递给两个函数的地址。我假设这个地址基本上是用来通知线程的。
所以我的问题是:假设 i 是一个 int,并且我们正在使用它的地址,这些函数如何知道何时休眠和唤醒?
假设:
- 当调用
IOLockWakeup
时,事件的内容为 0(然后变为非零值),并且 - 调用
IOLockSleepDeadline
时,调用时事件的内容为0,将停止休眠,因为内容不为零
当我们继续调用这些函数(在工作循环上下文中)时,事件参数的内容会在调用 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 可以访问该变量。