본문 바로가기
Programming/윈도우 드라이버

IRQL에 따른 스레드 선점 주의사항

by 유주원 2013. 1. 4.

윈도우즈 커널이나 드라이버에 대한 설명을 나온 책을 보면 항상 IRQL 에 따른 스레드 선점에 대한 얘기가 나오는데 다음과 같은 내용은 오해를 불러일으킬 소지가 있다.

"낮은 수준의 IRQL에서 실행하는 코드(스레드)는 높은 수준의 IRQL의 작업이 발생하게 되면 항상 선점된다."
"상승 된 IRQL에 코드는 상승 된 IRQL보다 낮은 레벨에 코드가 실행되는 것을 블록시킨다."

그러나 위에 사항들은 예외적일 수 있다.

예를 들어, 스레드 A가 APC_LEVEL로 실행중이고, 스레드 B는 이전에 PASSIVE_LEVEL에서 실행중이었다라고 가정하면 스레드 A가 APC_LEVEL로 실행중이기 때문에 스레드 B보다 IRQL이 높으므로 스레드A가 PASSIVE_LEVEL로 IRQL이 내려가지 않는 이상은 스레드 B에 코드는 실행되지 않을 것으로 예상 할 수 있다.

하지만 스레드 A가 APC_LEVEL로 실행중이더라도, 커널 스케쥴러에 의해 스레드 B를 스케쥴링하고 PASSIVE_LEVEL로 실행하게 된다. 즉, APC_LEVEL로 실행중이던 스레드 A는 PASSIVE_LEVEL로 실행중인 스레드 B에 선점당하게 된다.

( 위에 사항들은 멀티 CPU일 경우를 말하는것이 아니다. 싱글 CPU도 마찬가지이다. )

이렇게 되는 이유는 IRQL이 프로세서 종속적인 IRQL과 스레드 종속적인 IRQL로 나뉘어지기 때문이다.

프로세서 종속적인 IRQL은 DISPATCH_LEVEL 이상에 IRQL을 의미합니다. 이 경우에는 우리가 이미 알고 있는 IRQL에 선점 및 블록에 대한 규칙과 똑같다.

스레드 종송적인 IRQL은 DISPATCH_LEVEL 보다 낮은 IRQL을 의미한다.
APC_LEVEL, PASSIVE_LEVEL IRQL이 있다. ( 시스템 내부적으로 PASSIVE_LEVEL width critical region 이라는 가상에 IRQL도 있다. guarded region 이라고 Windows 2003 Server부터 추가 된 부분도 있는데 참고용으로 적어둔다.)

스레드 종속적이다라는 말은 현재 스레드에 한해서만 영향을 끼치는 IRQL라는 의미이다. 예를 들어, 스레드 A가 PASSIVE_LEVEL로 실행중일 때 스레드 A에 APC 루틴이 실행되어야 할 경우 스레드 A는 APC에 의해 선점 될 수 있다. 이 때 선점당한다라는 말은 다른 스레드에 선점당한다는것이 아니라 자기자신에 스레드에게 선점당한다는 의미이다. 스레드 A는 스레드 A에 APC 루틴에 의해 선점당한 상황이 발생하게 된다는 것을 의미한다.

스레드 종송적인 IRQL이 구현될 수 있는 것은 스레드 스케쥴러와 연관이 있다.

MS에 "Scheduling, Thread Context, and IRQL"라는 문서에 다음과 같은 문장이 있다.

The thread scheduler considers only thread priority, and not IRQL, when preempting a thread. If a thread running at IRQL=APC_LEVEL blocks, the scheduler might select a new thread for the processor that was previously running at PASSIVE_LEVEL.

스레드 스케쥴러는 오직 스레드에 우선순위만 고려할 뿐 IRQL은 전혀 고려하지 않는다. 어떤 스레드가 APC_LEVEL로 실행중이더라도 스케쥴러는 이전에 PASSIVE_LEVEL로 실행중인 스레드로 스케쥴링 할 수 있다.

또한 스레드 스케쥴러는 DISPATCH_LEVEL에서 동작하게 된다. ( 그래야 원하는 시점에 DISPATCH_LEVEL보다 낮은 스레드를 선점해서 다른 스레드로 스케쥴링 할 수 있다. )