2016-03-07 71 views
1

这一直困扰着我很长一段时间。 在我的IOkit驱动程序中,我将中断事件源,定时器事件源注册到workloop。我使用GetWorkLoop() - > runAction(pAction)进行硬件访问。因此,来自中断处理程序和定时器处理程序以及我的pAction的所有硬件访问都被序列化。 但是,我从IOCommandGate发现了另一个runAction。我不知道两个runAction的区别。 我查看了一些iokit内核文档,但没有得到明确的答案。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; 
} 

我指当我打电话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线程?

回答

1

你是对的,在这两种情况下,你的动作都将在当前线程的上下文中运行,而不是 IOWorkLoop线程。确保IOWorkLoop不会在您的操作正在运行时在其线程上运行任何操作(辅助中断处理程序等)。

正如您所看到的,两者之间的区别在于IOCommandGate可以被禁用并重新启用以暂停动作。我在实践中并不需要这样做,但有时候它可能有用。

要在IOWorkLoop线程本身执行的动作,一个IOEventSource子类必须覆盖checkForWork()虚方法,并通过IOEventSourcesignalWorkAvailable()方法通知新的工作IOWorkLoop

我不知道您可以使用的通用事件源,它允许您排列任意作业以在IOWorkLoop线程上运行,而IOCommandQueue已被弃用多年。 (所以你不应该使用它)

+0

所以,他们几乎是相同的。很好听,有时我使用IOTimerEventSource来实现workloop线程上的延迟调用。将函数注册到IOTimerEventSource实例,将addEventSource注册到workloop并设置超时值, – Song

相关问题