-
커널 동기화Linux/Linux Kernel 2020. 8. 16. 17:03
스핀락
스핀락 특징
preempt_enable() 함수와 preempt_disable() 함수가 존재해 스핀락 획득시 선점을 할 수 없다.
CPU 아키텍처별로 스핀락의 구현부가 다르다.
임계영역에서 인터럽트를 허용한다면
spin_lock() 함수와 spin_unlock() 함수를 사용한다.
임계영역에서 인터럽트를 허용하고 싶지 않다면
spin_lock_irq() 함수와 spin_unlock_irq() 함수를 사용한다.
임계영역에서 인터럽트 상태를 확인하기 하고 싶다면
spin_lock_irqsave() 함수와 spin_unlock_restore() 함수를 사용한다.
spin_lock_irq() 함수와 spin_unlock_irq() 함수를 사용하는 경우(임계영역에서 인터럽트를 허용하고 싶지 않을 경우)
- 정확한 순서로 데이터 시트에 언급된 순서로 특정 메모리 구간에 어떤 값을 써야 할 경우
- 각 디바이스 드라이버가 Suspend/Resume과 같은 슬립에 진입하거나 깨어나는 동작일 경우
- 코드의 실행 순서를 반드시 지켜야 하는 코드인 경우
spin_lock_irqsave() 함수와 spin_unlock_restore() 함수를 사용 하는 경우
- spin_lock_irq() 함수를 호출한 후 인터럽트를 비활성화하다 보니 현재 인터럽트 상태를 확인하기 어려운 경우
- 함수 호출 깊이가 깊어지면서 인터럽트의 상태를 확인하기 어려운 경우
뮤텍스
스핀락 사용 예제
스핀락을 획득할때는
spin_lock() 함수
스핀락을 해제할때는
spin_unlock() 함수를 사용한다.
이 함수는 선언부는 static __always_inline void spin_lock(spinlock_t *lock);
__always_inline 매크로로 선언했으니 커널 함수 내에서 자주 호출되는 함수임을 알 수 있다.
임계 영역에 한개의 프로세스만 접근하려면 임계 영역의 코드 구간을 보호해야한다. 이 코드 구간을 spin_lock() 함수와 spin_unlock() 함수로 감싸는 것이다.
함수안에서 새로운 변수를 선언을 한다면 그 변수는 프로세스별 스택 공간에 저장이되기 때문에 동기화 할 필요가 없다.
하지만 프로세스들이 공용으로 사용하는 전역변수는 동기화 처리를 해줘야한다.
스핀락 처리 흐름
스핀락 획득 시도
1.spin_lock()에서는 spin_lock() 함수의 매개변수인 스핀락 인스턴스의 값을 spin_lock() 함수에서 생성되는 지역변수에 값을 복사한다.
2. 스핀락 인스턴스의 next값을 1증가시킨다.
3. 스핀락 인스턴스의 owner값과 스핀락 지역변수의 next값을 비교하여 같으면 스핀락을 획득한다.
2.