컨텐츠 바로가기

spin_lock, spin_lock_irq, spin_lock_irqsave란 무엇인가

http://nimhaplz.egloos.com/5301468

태초에 multi thread 프로그래밍이 존재했고, 여러 thread간의 교통정리(synchronization)를 위해
lock이라는 메커니즘이 등장한다.
태초에 존재했던 lock은 mutex(MUTually EXclusive lock)이었을 것이다.
mutex는 만약 다른 쓰레드(a)가 lock을 잡고 있는 경우, 현재 쓰레드(b)가 sleep하도록 했다.
그렇게 쓰다 보니, critical section이 매우 짧은 경우 퍼포먼스 낭비가 있었다.
lock을 잡지 못해서 thread(b)가 sleep하는 경우, sleep을 하기 위한 작업을 하는 시간 안에
lock이 풀리기 때문이다.

그래서 spinlock이 등장하게 된다. spinlock은 lock을 잡을 수 없을 때,
mutex처럼 sleep에 들어가는게 아니라, loop을 돌며 busy-waiting을 하는 것이다.
critical section이 짧은 경우에는 굳이 mutex가 아니라 spinlock을 쓰면 더
빠르게 동작할 수 있다.

이렇게 해서 모두 행복하게 이야기가 끝날 줄 알았으나...
인터럽트가 발생하는 경우 또 다른 문제가 야기되었다.

thread가 spinlock을 잡고 일을 하고 있는데, 인터럽트가 발생하고
그 인터럽트 핸들러가 spinlock을 잡으려 하는 상황이다.
이렇게 되는 경우, 원래 thread가 spinlock을 잡고 있는데, 그 thread가
더이상 돌지 못하게 되므로, deadlock이 발생한다.

그래서 등장한 것이 spin_lock_irq함수이다. 이 함수는 spinlock을 잡으면서
인터럽트를 disable시켜주는 것이다.(물론 차후에 interrupt enable하면 그동안 떴던 인터럽트가 처리된다)
spin_lock_irq를 쓰면 spinlock 구간에서 인터럽트 자체가
처리되지 않으므로, 앞에서 언급한 deadlock이 발생하지 않는다.

하지만 함수의 call path가 깊어지거나, spin_lock_irq가 nesting돼서 사용되는 경우, spin_lock_irq함수를 쓰기가 어려워진다.
interrupt disable을 몇번 했든지간에, enable은 한번만 해 주면 결국 인터럽트가 다시 복구되는데,
spin_lock_irq을 하려는 함수에 들어왔을 때
인터럽트가 enable상태인지, disable상태인지 모르면,
spin_unlock을 할 때 enable을 해야 할지 말아야 할지 모르겠는거다.

이런 경우에 사용하는게 spin_lock_irqsave함수이다. 이 함수는 irq를 disable함과 동시에,
irq가 이전에 enable인지 disable인지를 변수에 저장한다.
그래서 이 함수는 저장할 변수를 인자로 받는 것이다.

call path가 깊은 곳이나, spin_lock_irq를 nesting해서 사용할 때에는 이 함수를 이용하는것이 편하다.
다만, 단순히 disable만 하는게 아니라 상태를 메모리에 저장도 하기 때문에,
퍼포먼스 오버헤드는 spin_lock_irq보다 살짝 크다.

정리하자면 이렇다.

* spin_lock  (spinlock)
  기본이 spinlock. 다른걸 이용할 필요가 없다면 이걸 쓴다.
  가장 퍼포먼스 오버헤드가 적다.

* spin_lock_irq (spin lock irq disable)
  모든 인터럽트를 disable시키기 때문에, interactivity등 시스템의 퍼포먼스에 영향이 크다.
  interrupt handler와 일반 thread가 spinlock을 공유하는 경우에 사용한다.
  spinunlock irq enable로 unlock을 해 주면, 인터럽트가 몇번 disable됐는지 상관 않고
  enable돼 버리므로 주의한다.

* spin_lock_irqsave (spin lock irq save)
  spin_lock_irq과 같지만, irq disable하기 직전의 interrupt enable여부를 변수에 저장한다.
  spinlock을 이용하는 시점에서 interrupt enable여부를 확신할 수 없는 경우에 쓴다.
  메모리에 상태를 저장하게 되므로, disable만 하는 함수에 비해서는 느리다.
 

2010. 4. 24
티맥스소프트 김||


트랙백

덧글|덧글 쓰기|신고