1. [UP System] 프로세스 컨텍스트 간의 동기화
semaphore, preempt_disable
semaphore는 CS(Critical Section)를 공유하는 프로세스 컨텍스트들을 휴면 시켜서 동기화를 달성한다. preempt_disable은 CS를 공유하는 프로세스 컨텍스트들은 물론이고 다른 모든 프로세스 컨텍스트들 또한 선점을 금지시켜 동기화를 달성한다. CS 구간이 긴 경우 semaphore를 짧은 경우 preempt_disable을 사용한다.
local_irq_disable을 사용할 수도 있겠지만 인터럽트 컨텍스트가 없기 때문에 불필요하다. 프로세스 컨텍스트는 휴먼 가능 하므로 spin_lock은 사용 불가능하다.
2. [UP System] 프로세스 컨텍스트와 인터럽트 컨텍스트 간의 동기화
local_irq_disable
local_irq_disable은 모든 인터럽트를 금지 시키기 때문에(심지어 타이머 인터럽트에 기반한 스케줄러까지) CS를 공유하는 프로세스 컨텍스트와 인터럽트 컨텍스트 간 동기화를 달성한다.
인터럽트는 스케줄링 대상이 아니므로 semaphore, preempt_disable로는 프로세스 컨텍스트와 동기화를 달성할 수 없다. 또한 semaphore는 휴면 가능하므로 인터럽트 컨텍스트에서는 아예 사용이 불가능하다. 인터럽트 컨텍스트는 항상 프로세스 컨텍스트에 우선 하므로 spin_lock은 사용 불가능하다.
3. [UP System] 인터럽트 컨텍스트 간의 동기화
local_irq_diisable
인터럽트 컨텍스트는 스케줄링 대상이 아니므로 local_irq_disable로 동기화를 달성한다.
인터럽트는 우선순위에 따라 중첩이 가능하므로 spin_lock 사용 불가능하다.
semaphore, preempt_disable는 인터럽트 컨텍스트 간의 동기화에 아무런 역할을 하지 못하며 semaphore는 휴면 가능하므로 인터럽트에서는 아예 사용이 불가능하다.
4. [SMP System] 프로세스 컨텍스트 간의 동기화
spin_lock
프로세스 컨텍스트가 하나의 프로세서에서 유사 동시성을 가짐과 동시에 다수의 프로세서에서 진정한 동시성을 가지게 된다. CS가 다수의 프로세서에 의해 공유 되므로 spin_lock을 사용해야 다수의 프로세서 간에 동기화가 달성 된다.
preempt_disable
preempt_disable 은 특정 프로세서에서의 선점을 금지 한다. 예를 들어 A, B 두 개의 프로세서가 있다. 그리고 CS를 공유하는 1, 2, 3, 4 네 개의 태스크가 있다. 어떠한 원인인지는 몰라도(로드 밸런싱을 포함한 다수의 경우가 있을 수 있음) 태스크 1, 2는 A 프로세서에서 실행되고 있고, 태스크 3, 4는 B 프로세서에서 실행 된다고 가정한다. 프로세서 A의 태스크 1, 2 든 프로세서 B의 태스크 3, 4든 CS 진입 시에 preempt_disable을 호출하면 프로세서 A의 태스크 1, 2 간의 유사 동시성에 의한 동기화가 달성되고 프로세서 B의 태스크 3, 4 간의 유사 동시성에 의한 동기화도 달성 될 것이다. 하지만 이것만으로는 프로세서 간의 진정한 동시성에 의한 동기화는 달성할 수 없으므로 태스크(1, 2)와 (3, 4)간의 동기화는 spin_lock으로 달성 될 것이다.
preempt_disable은 유사 동시성에서의 동기화를 위해서만 사용되는 것이다.
SMP에서 프로세서 컨텍스트 간의 완벽한 동기화를 위해서는 다음과 같은 코드 모양이 될 것이다.
preempt_disable --> 유사 동시성 동기화
spin_lock --> 진정한 동시성 동기화
.....
CS
.....
spin_unlock
preempt_enable
이렇게 코드가 작성 된다면 SMP에서 UP로 갈 경우 spin_lock만 걷어내면 될 것이다.
5. [SMP System] 프로세스 컨텍스트와 인터럽트 컨텍스트 간의 동기화
local_irq_disable + spin_lock
local_irq_disable은 로컨 프로세서의 모든 인터럽트를 금지 하므로 유사 동시성에서의 프로세스 컨텍스트 간의 동기화를 달성함과 동시에 프로세스 컨텍스트와 인터럽트 컨텍스트 간의 동기화를 달성할 수 있다. 하지만 인터럽트는 다른 프로세서에 의해 핸들링 될 수 있으므로 반드시 spin_lock을 더해줘야 한다. 이 조합을 하나의 함수로 처리한 것이 spin_lock_irqsave(), spin_lock_irqstore()이다. UP에서와 마찬가지로 유사 동시성에서의 데드락을 방지하기 위해 반드시 인터럽트를 먼저 금지하고 락을 잡아야 한다.
물론 preempt_disalbe을 사용해 프로세스 컨텍스트 간의 동기화를 해결할 수 있겠지만, local_irq_disable이 이를 해결해주므로 사용할 필요가 없다. 또한 semaphore는 휴면 가능하므로 인터럽트 컨텍스트에서는 아예 사용이 불가능하다.
preempt_disable --> 프로세스 컨텍스트 간의 동기화 (유사 동시성) => 불필요
locak_irq_disable --> 프로세스 컨텍스트 간의 동기화 + 프로세스 컨텍스트와 인터럽트 컨텍스트 간 동기화(유사 동시성)
spin_lock --> 진정한 동시성 동기화
.....
CS
.....
spin_unlock
local_irq_enable
preempt_enable
6. [SMP System] 인터럽트 컨텍스트 간의 동기화
local_irq_disable + spinlock
locak_irq_disable은 유사 동시성에서의 동기화를 위해 사용하는 것이며 (단일 프로세서에서의 인터럽트 컨텍스트 간의 동기화), 진정한 동시성에서의 동기화는 spin_lock을 통해 달성 된다. 또한 유사 동시성에서의 데드락을 방지하기 위해 반드시 인터럽트를 먼저 금지하고 락을 잡아야 한다. semaphore, preempt_disable는 인터럽트 컨텍스트 간의 동기화에 아무런 영할을 하지 못하며, semaphore는 휴면 가능하므로 인터럽트 컨텍스트에서는 아예 사용할 수 없다.
spin_lock
spin_lock은 두 개 이상의 프로세서가 실제로 동일한 시간에 같은 CS 구간에 접근할 때만 사용을 한다. 하나의 프로세서만을 사용하는 시스템에서는 시분할에 의한 유사 동시성만을 가지므로 spin_lock이 필요 없다. SMP 시스템에서는 두 개 이상의 프로세서에 의한 진정한 동시성과 하나의 프로세서에 의한 유사 동시성을 가진다. 즉, SMP 시스템에서는 두가지 종류의 동시성을 모드 가지는 것이다. 이때 spin_lock이 의미가 있는 경우는 두 개 이상의 프로세서에 의한 진정한 동시성을 가질때 이다. 그러므로 spin_lock을 생각할 때 SMP냐 UP냐, 선점이냐 비선점이냐를 생각하며 고민할 필요가 없다.
출 처 : http://blog.naver.com/redcultuer?Redirect=Log&logNo=130109621698