- spin lock 의 정의 보면 SMP 에서만 사용함을 알 수 있다.
- 구현에 있어 memory 관련 내용은 memory-barriers.txt 참조.
- 결국 이것은 SMP 에서 새로이 나타난 동기화를 해결 하기 위한 solution 이라는 관점으로 접근 하는것이 이해하기 좋다. 간단히 mutex 를 생각해 보면...
- semaphore 의 특수한 경우이지만 따로 보통 분리해서 다룬다.
- 효율성 때문 mutex-design.txt 참조
- Rule
- only one task can hold the mutex at a time
- only the owner can unlock the mutex
- multiple unlocks are not permitted
- recursive locking is not permitted
- a mutex object must be initialized via the API
- a mutex object must not be initialized via memset or copying
- task may not exit with mutex held
- memory areas where held locks reside must not be freed
- held mutexes must not be reinitialized
- mutexes may not be used in hardware or software interrupt contexts such as tasklets and timers
- APIs
- DEFINE_MUTEX(name);
- mutex_init(mutex);
- void mutex_lock(struct mutex *lock);
- int mutex_lock_interruptible(struct mutex *lock);
- int mutex_trylock(struct mutex *lock);
- void mutex_unlock(struct mutex *lock);
- int mutex_is_locked(struct mutex *lock);
- void mutex_lock_nested(struct mutex *lock, unsigned int subclass);
- int mutex_lock_interruptible_nested(struct mutex *lock, unsigned int subclass);
- int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock);
UP 에서 mutex 를 구현 한다는 것은 결국 atomic 하게 exchange 를 할 수 있으면 되는 거다.
보통 관련한 instruction 이 있지.
SMP 환경이라면, 아무리 atomic exchange instruction 이 있어도 다른 코어 가 동시에 접근 하는 것을 막을 수는 없지.
즉, mutex 의 구현안에 spin lock 을 이용한 SMP 보호 구역이 있어야 겠지.
물론 실제로도 그러하다.
spinlock 사용 되는 경우 보면...
code sample 1>
static DEFINE_SPINLOCK(xxx_lock);
unsigned long flags;
spin_lock_irqsave(&xxx_lock, flags);
... critical section here ..
spin_unlock_irqrestore(&xxx_lock, flags);
언제나 안전하다. irq 를 막기 때문에 아무도 침범 불가.
code sample 2>
rwlock_t xxx_lock = __RW_LOCK_UNLOCKED(xxx_lock);
unsigned long flags;
read_lock_irqsave(&xxx_lock, flags);
.. critical section that only reads the info ...
read_unlock_irqrestore(&xxx_lock, flags);
write_lock_irqsave(&xxx_lock, flags);
.. read and write exclusive access to the info ...
write_unlock_irqrestore(&xxx_lock, flags);
이것은 RCU 로 대체 되었고, 제거 중이다.
- 참조 rcu.txt, listRCU.txt
code sample 3>
spin_lock(&lock);
...
spin_unlock(&lock)
irq 안막았기 때문에 아래와 같은 deadlock 가능.
spin_lock(&lock);
...
<- interrupt comes in:
spin_lock(&lock);
같은 걸 동일 cpu 에서 lock 해 버리면 deadlock 이 된다.
spinlock 의 사용시 irq 도 막을지 말지는 보호하려는 critical section 이 ISR 에서 참조 하는지 유무에 따라 결정 하면 된다.