다음을 통해 공유


WdfInterruptTryToAcquireLock 함수(wdfinterrupt.h)

[KMDF 및 UMDF에 적용]

WdfInterruptTryToAcquireLock 메서드는 인터럽트 개체의 수동 잠금을 획득하려고 시도합니다.

구문

BOOLEAN WdfInterruptTryToAcquireLock(
  [in] WDFINTERRUPT Interrupt
);

매개 변수

[in] Interrupt

프레임워크 인터럽트 개체에 대한 핸들입니다.

반환 값

WdfInterruptTryToAcquireLock 은 인터럽트의 잠금을 성공적으로 획득하면 TRUE를 반환합니다. 그렇지 않으면 메서드는 FALSE를 반환합니다.

설명

수동 수준 인터럽트 처리를 사용하는 드라이버는 WdfInterruptTryToAcquireLock을 호출하여 드라이버가 인터럽트 개체의 WDF_INTERRUPT_CONFIG 구조에 구성된 수동 수준 인터럽트 잠금을 유지하면서 IRQL = PASSIVE_LEVEL 실행되는 코드 시퀀스를 시작합니다.

WdfInterruptTryToAcquireLock 은 잠금을 획득하려고 시도한 다음 잠금을 획득했는지 여부에 관계없이 즉시 반환합니다. WdfInterruptTryToAcquireLock이 잠금을 성공적으로 획득하면 프레임워크는 일반 커널 APC를 사용하지 않도록 반환하기 전에 KeEnterCriticalRegion을 호출합니다.

수동 수준 인터럽트 개체의 경우 드라이버는 큐 개체 콜백 함수와 같은 임의의 스레드에서 실행할 때 WdfInterruptAcquireLock 대신 WdfInterruptTryToAcquireLock을 호출해야 합니다. 예를 들어 드라이버는 EvtIoRead에서 WdfInterruptTryToAcquireLock을 호출할 수 있습니다. 이렇게 하면 WdfInterruptAcquireLock의 설명 섹션에 설명된 대로 교착 상태가 발생할 수 있습니다.

작업 항목과 같은 임의가 아닌 스레드에서 실행하는 경우 드라이버는 WdfInterruptAcquireLock을 사용해야 합니다.

드라이버가 WdfInterruptReleaseLock을 호출하면 프레임워크는 인터럽트 잠금을 해제합니다.

예제

다음 코드 예제에서는 임의 컨텍스트에서 실행되는 EvtIoRead 콜백 함수가 인터럽트 관련 작업을 수행하기 전에 WdfInterruptTryToAcquireLock 을 호출하는 방법을 보여줍니다. 메서드가 FALSE를 반환하는 경우 드라이버는 작업 항목을 큐에 대기하여 임의가 아닌 스레드에서 작업을 수행합니다. 또한 드라이버는 작업을 수행하기 전에 WdfInterruptAcquireLock을 호출하는 EvtWorkItem 콜백 함수를 제공합니다.

이 예제에서 드라이버는 큐에 대한 순차적 디스패치를 지정했습니다. 드라이버가 큐에 대한 다른 디스패치 메서드를 지정한 경우 드라이버는 추가 수동 큐를 사용하여 작업 항목의 처리 요청을 유지해야 합니다. 코드 주석은 이러한 지원을 추가할 위치를 설명합니다.


VOID EvtIoRead(
  __in  WDFQUEUE Queue,
  __in  WDFREQUEST Request,
  __in  size_t Length
    )
{
    DEVICE_CONTEXT    devCtx;
    devCtx = GetDeviceContext(WdfIoQueueGetDevice(Queue));
    
    //
    // Do any pre-acquiring interrupt lock work here.
    //
   

    //
    // Check if we can acquire the lock.
    //
    if (WdfInterruptTryToAcquireLock(devCtx->InterruptObject) {
        ReadFunctionLocked(Request);
        WdfInterruptReleaseLock(devCtx->InterruptObject);
        //
        // Do any post-releasing interrupt lock work here.
        // For example: complete the request, and so on.
        //
        ReadFunctionFinish(Request); 
    }
    else {
        WORK_ITEM_CONTEXT ctx;

        ctx = GetWorkItemContext(ReadWorkItem);
        ctx->Request = Request;

        // If previous queue is non-sequential, call WdfRequestForwardToIoQueue 
        // to store request in an additional manual queue.

        WdfWorkItemEnqueue(ReadWorkItem);
    }
}


VOID
EvtReadWorkItemCallback(
    WDFWORKITEM WorkItem
    )
{
    WORK_ITEM_CONTEXT wiCtx;
    DEVICE_CONTEXT    devCtx;

    wiCtx = GetWorkItemContext(ReadWorkItem);
    devCtx = GetDeviceContext(WdfWorkItemGetParentObject(WorkItem));

    // If delivery queue is non-sequential, call WdfIoQueueRetrieveNextRequest 
    // to retrieve request that we stored in EvtIoRead.

    //
    // Acquire interrupt lock.
    //
    WdfInterruptAcquireLock(devCtx->InterruptObject);
    ReadFunctionLocked(wiCtx->Request);
    WdfInterruptReleaseLock(devCtx->InterruptObject);

    //
    // Do any post-releasing interrupt lock work here.
    // For example: complete the request, and so on.
    //
    ReadFunctionFinish(wiCtx->Request); 
}

요구 사항

요구 사항
대상 플랫폼 유니버설
최소 KMDF 버전 1.11
최소 UMDF 버전 2.0
머리글 wdfinterrupt.h(Wdf.h 포함)
라이브러리 Wdf01000.sys(KMDF); WUDFx02000.dll(UMDF)
IRQL PASSIVE_LEVEL
DDI 규정 준수 규칙 DriverCreate(kmdf)

추가 정보

EvtInterruptWorkItem

WDF_INTERRUPT_CONFIG

WdfInterruptAcquireLock

WdfInterruptReleaseLock

WdfIoQueueRetrieveNextRequest

WdfRequestRequeue

WdfWaitLockAcquire