1

これは長い間私を混乱させてきました。私のIOkitドライバーでは、ワークループに割り込みイベントソース、タイマーイベントソースを登録しました。ハードウェア アクセスには GetWorkLoop()->runAction(pAction) を使用します。したがって、割り込みハンドラーとタイマー ハンドラーからのすべてのハードウェア アクセスと、私の pAction はシリアル化されます。しかし、IOCommandGate から別の runAction を見つけました。2つのrunActionの違いが気になります。いくつかのiokitカーネルドキュメントを調べました.明確な答えが得られませんでした.

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) を呼び出すときを意味します。inAction は、ワークループ スレッド コンテキストではなく、スレッド コンテキストで実行されます。これは正しいです?

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 も私のスレッドコンテキストで実行されているようです。ワークループスレッドではありませんか?

4

1 に答える 1