ERESOURCE 사용법 및 내부

동기화에 대해서는 많은 분들이 고민을 많이 해보셨을 것이고 단순히Spinlock 을 사용해서 동기화를 구현한 분들도 계실 것입니다.

Spinlock 을 사용하면 어떤 문제가 있을까요? 한번에 하나의 Thread 만 접근이 가능하다는 것인데 다수의 Thread 가 공용 Buffer 를 Read 만 하는 것이라면 동시에 접근을 해도 문제가 없을 것입니다. Buffer 를 변경하는 경우에만 동시에 접근이 안되도록 하려면 어떻게 해야 할까요?

Executive Resource (ERESOURCE) 를 이용하여 동기화를 구현 하면 됩니다.
사용법은 다음과 같습니다.

// 선언
ERESOURCE  rResourceLock;
// 초기화
ExInitializeResourceLite( &rResourceLock );

// 배타적 lock
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite( &rResourceLock, TRUE );

// 공유 lock
KeEnterCriticalRegion();
ExAcquireResourceSharedLite( &rResourceLock, TRUE );

// lock 해제
ExReleaseResourceLite( &rResourceLock );
KeLeaveCriticalRegion();

// 정리
ExDeleteResourceLite( &rResourceLock );

내부 동작이 어떻게 되는지 살펴 보았더니 다음과 같습니다.

Exclusive lock 이 어떤 Thread 에 의해 소유 되거나 요청되어 있는 상태에서 Share lock 요청이 호출되게 되면 내부적으로 semaphore 를 가지고 Exclusive lock 이 끝나기를 기다리게 됩니다.
Exclusive lock 을 호출했던 Thread 가 Release 를 호출하면 Semaphore 에서 대기하던 Thread 들이 깨어나서 작업을 하게 됩니다.

Share lock 을 가지고 있는 상태에서 Exclusive lock 요청이 호출되면 내부적으로 Event 를가지고 Share lock 들이 모두 끝나기를 기다리게 됩니다. 모든 Share lock 이 Release 되면 Event 를 대기하던 Thread 들이 깨어나게 됩니다.

 

내부적으로 Spinlock 을 사용해서 ERESOURCE 내부 Data 의 동기화를 보장 합니다.

감사합니다.