2016-03-07 7 views
1

Это смущает меня в течение длительного времени. В моем драйвере 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?

ответ

1

Вы правы, в обоих случаях ваше действие будет выполняться в контексте текущей темы, не поток IOWorkLoop. Гарантируется, что IOWorkLoop не будет запускать никаких действий (вторичные обработчики прерываний и т. Д.) В своем потоке, пока ваше действие работает.

Различие между этими двумя, как вы можете видеть, заключается в том, что IOCommandGate можно отключить и повторно включить, чтобы приостановить выполнение действий. Я не нуждался в этом на практике, но, возможно, иногда это бывает полезным.

Для выполнения действия на самом IOWorkLoop потока, IOEventSource подкласса должен переопределить виртуальный метод checkForWork(), и уведомить IOWorkLoop новой работы через signalWorkAvailable() метод IOEventSource «s.

Я не знаю об источниках общего назначения, которые вы можете использовать, что позволяет вам заказывать произвольные задания для работы в потоке IOWorkLoop, кроме IOCommandQueue, который устарел много лет. (так что вы не должны этого использовать)

+0

так, они почти одинаковы. Достаточно слышать, что иногда я использую IOTimerEventSource для реализации отложенного вызова на потоке workloop. зарегистрируйте func для экземпляра IOTimerEventSource, addEventSource для workloop и установите значение тайм-аута, – Song

 Смежные вопросы

  • Нет связанных вопросов^_^