모든 위험구역(critical region)을 하나의 변수를 늘리는 것과 같은 같은 간단한 동작으로 항상 보존할 수 없다. 이러한 경우에 충분한 보호를 제공할 필요가 있으며 이를 위해 록(lock)이 필요하다.
리눅스 커널에서는 이를 위해 가장 많이 사용하는 것이 스핀록(spin lock)이다.
스핀록은 최대한 하나의 스레드에 의해 잠길 수 있는 록을 말한다. 만약 어떤 스레드가 이미 잠겨진 스핀록을 다시 잠그려 시도한다면 그 스레드는 루프(busy loop)를 돌면서(spin) 록을 잠글 수 있을 때까지 기다린다.
스핀록은 가볍고 소유자가 하나인 록으로서 짧은 기간 동안만 소유 돼야 한다.
스핀록과 관련된 인터페이스는
<linux/spinlock.h>에 정의되어 있다.
스핀록의 기본적인 사용법은 다음과 같다.
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
spin_lock(&mr_lock);
/* critical region ... */
spin_unlock(&mr_lock);
스핀록은 SMP에서만 유효하다. UP 기기에서는 컴파일시 록이 제거되어 포함되지 않는다. 그러나 커널의 선점이 가능한가를 나타내는 표지로 사용될 수 있다. 만약 커널 선점이 비활성화 되어 있는 경우에는 컴파일 시 완전히 제거된다.
주의: 스핀록은 재귀적이지 않다.
스핀록은
인터럽트 핸들러에서도 사용 가능하다. 인터럽트 핸들러에서 록을 사용할 경우에, 커널 내의 데이터를 인터럽트 핸들러에서 공유하는 경우 록을 얻기 전에 반드시 로컬 인터럽트를 비활성화해야 한다.
이때 로컬 인터럽트의 활성화 여부를 알 수 없다면 다음과 같은 인터페이스를 이용해야 한다.
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
unsigned long flags;
spin_lock_irqsave(&mr_lock, flags);
/* critical region ... */
spin_unlock_irqrestore(&mr_lock, flags);
만약 인터럽트 활성화 상태임을 알고 있다면 다음의 인터페이스를 사용해도 된다.
spinlock_t mr_lock = SPIN_LOCK_UNLOCKED;
spin_lock_irq(&mr_lock);
/* critical region ... */
spin_unlock_irq(&mr_lock);
스핀록 디버깅
설정 옵션의 하나인 CONFIG_DEBUG_SPINLOCK은 스핀록 코드의 많은 디버깅 검사를 활성화시킨다.