[DDK] Using rules of SpinLock

스핀 락은 참 오묘한 문제이다. 하지만 알고 보면 간단한 로직으로 해결할 수 있다!!

 일단 동기화 문제에 직면하게 되면, ( 멀티 프로세서 )

우리가 익히 알고 있는 세마포어(Semaphore)같은 방법을 사용해서 락킹(Locking)을 해야한다.

이것을 제대로 해주지 않는다면 데드락(DeadLock)에 빠지게된다.

 데드락은 운영체제때 들었을 것이다.

여러 스레드가 임계영역(Critical Section)에 들어가기 위해서,

경쟁을 할 것이다.

 하나의 스레드가 스핀락을 사용하고 있을 경우 스핀 락을 사용하고자 하는 다른 스레드가

스핀 락을 사용하기 위해 스핀 락을 소유하고 있는 스레드가 해제할 때까지 어떤 동작도 실행하지 않는 것을

비지 웨이팅(Busy-Waiting) 상태라 한다.

 네트워크에서 Selecting 이나 Polling 방식도 Busywaiting에 속한다. while loop가 Cpu를 점유하게 된다.

나중에 어플리케이션과 드라이버가 시그널을 주고 받을때, 다시 Busy waiting에 대해서 알아볼 것이다.

 이제 정확한 사용 규칙을 알아 보자,!

 일단 스핀 락은 반드시 디스패치 레벨(DISPATCH_LEVEL)이나 그 아래(PASSIVE_LEVEL, APC_LEVEL)

의 IRQL에서만 요청
할 수 있다.

 다음번에는 IRQL에 대해서 알아볼 것인데, 순서가 뒤바낀 감도 있긴하다,,;

 그리고 모든 스핀 락은 자신의 IRQL을 가지고 있고, 이 IRQL은 적어도 디스패치 레벨보다 높지 않아야 하기

때문에 디스패치 레벨이 스핀 락을 얻기 위한 가장 높은 IRQL에 해당한다.
 
 이때 그 IRQL을 높여 주는 방법이 있을 수가 있다. 디스패치 레벨로 올려주면서 실행할 수 도있는데,
 
KeAcquireInterruptSpinLock() 함수를 사용해서 IRQL을 증가 시킬 수 있다.

KeAcquireInterruptSpinLock

The KeAcquireInterruptSpinLock routine acquires the spin lock associated with an interrupt object.

NTKERNELAPI
KIRQL
  KeAcquireInterruptSpinLock (
    IN PKINTERRUPT  Interrupt
    );

Comments

Drivers use the interrupt spin lock to synchronize access to memory shared with the interrupt's ISR. The driver can release the spin lock by calling KeReleaseInterruptSpinLock.

Any code that executes while the interrupt spin lock is held does so at IRQL = DIRQL for the specified Interrupt, so it must execute very quickly. For more information, see Using Critical Sections.

It is generally faster to use KeSynchronizeExecution to synchronize access than to use KeAcquireInterruptSpinLock and KeReleaseInterruptSpinLock.

Callers must be running at IRQL <= DIRQL for Interrupt. (This is the value the driver passed as the SynchronizeIrql parameter of IoConnectInterrupt when Interrupt is created.)

Requirements

IRQL: <=DIRQL (see Comments section)

Headers: Declared in wdm.h. Include wdm.h, ntddk.h, or ntifs.h.


 IRQL을 증가 시키는 이유에 대해서는 다음에 같이 알아볼 것이다,

그리고 스핀 락을 사용할 때는 페이징을 하면 안된다, 디스패치 레벨에서 페이징이 된다면, 오류를 발생

시키게 된다, 그리고 스핀 락 코드 내에서 다른 함수 호출시에 그 피호출 함수는 페이징을 하지 않아야한다.

 그리고 스핀 락의 시간을 최대한 줄이는 것이 좋다. 25 micro second정도로 MS가 권장하고 있다.

 

출처 : http://ssmhz.tistory.com


위로 스크롤