Это смущает меня в течение длительного времени. В моем драйвере IOkit я зарегистрировал источник события прерывания, источник событий таймера, чтобы работать на компьютере. и я использую GetWorkLoop() -> runAction (pAction) для доступа к аппаратным средствам. Таким образом, весь доступ к аппаратным средствам от обработчика прерываний и обработчика таймера и моего pAction сериализуется. Но я нашел еще один runAction от IOCommandGate. Интересно, какая разница между двумя runAction. Я заглянул в ядро iokit docs.didn't получить четкий ответ.Разница между GetWorkLoop() -> runAction и GetCommandGate() -> runAction?
В источнике XNU:
IOReturn IOWorkLoop::runAction(Action inAction, OSObject *target,
void *arg0, void *arg1,
void *arg2, void *arg3)
{
IOReturn res;
// closeGate is recursive so don't worry if we already hold the lock.
closeGate();
res = (*inAction)(target, arg0, arg1, arg2, arg3);
openGate();
return res;
}
I означает, что, когда я называю GetWorkLoop() -> runAction (бездействием). inAction запускается в моем контексте потока, а не в контексте потока workloop. это верно?
IOReturn IOCommandGate::runAction(Action inAction,
void *arg0, void *arg1,
void *arg2, void *arg3)
{
if (!inAction)
return kIOReturnBadArgument;
// closeGate is recursive needn't worry if we already hold the lock.
closeGate();
// If the command gate is disabled and we aren't on the workloop thread
// itself then sleep until we get enabled.
IOReturn res;
if (!workLoop->onThread()) {
while (!enabled) {
uintptr_t *sleepersP = (uintptr_t *) &reserved;
*sleepersP += 2;
IOReturn res = sleepGate(&enabled, THREAD_ABORTSAFE);
*sleepersP -= 2;
bool wakeupTearDown = (*sleepersP & 1);
if (res || wakeupTearDown) {
openGate();
if (wakeupTearDown)
commandWakeup(sleepersP); // No further resources used
return kIOReturnAborted;
}
}
}
bool trace = (gIOKitTrace & kIOTraceCommandGates) ? true : false;
if (trace)
IOTimeStampStartConstant(IODBG_CMDQ(IOCMDQ_ACTION),
VM_KERNEL_UNSLIDE(inAction), (uintptr_t) owner);
IOStatisticsActionCall();
// Must be gated and on the work loop or enabled
res = (*inAction)(owner, arg0, arg1, arg2, arg3);
if (trace)
IOTimeStampEndConstant(IODBG_CMDQ(IOCMDQ_ACTION),
VM_KERNEL_UNSLIDE(inAction), (uintptr_t) owner);
openGate();
return res;
}
код кажется GetCommandGate() -> runAction также запускается в контексте потока. не workloop thread?
так, они почти одинаковы. Достаточно слышать, что иногда я использую IOTimerEventSource для реализации отложенного вызова на потоке workloop. зарегистрируйте func для экземпляра IOTimerEventSource, addEventSource для workloop и установите значение тайм-аута, – Song