공유 메모리 동기화

공유자원은 동시다발적인 접근 요청으로부터 의도하지 않은 변경이 일어나지 않도록 보호되어야 한다. 공유자원은 대게 공유 메모리이거나 주변장치이고, 접근 요청은 프로세서로부터 이루어진다.

동기화를 실현하기 위해서는 기본적으로 메모리 접근에 대한 원자적 실행이 보장되어야 한다. 즉, 일련의 실행이 완료되기까지 다른 마스터(프로세서)로부터 방해받지 않기 위해 시스템 버스를 배타적으로 확보해야 한다. 따라서 메모리 요청이 일어나면 프로세서는 시스템 버스를 먼저 확보한다.

 -----------             -----------
|processor 1|           |processor 2|
 -----------             -----------
      |                       |
 -----------------------------------
|               bus                 |
 -----------------------------------
          |
   ---------------
  | shared memory |
   ---------------

ARMv6 아키텍처에서 이러한 원자적 실행을 실현하기 위한 새로운 메커니즘이 추가되었다, ldrexstrex. 이전 버전에서는 swp 명령을 제공한다. swp 명령은 한벌의 메모리 읽기/쓰기 연산이 원자적으로 실행되는 것을 보장한다(레지스터와 메모리사이의 스왑이 원자적으로 실행된다). swp 수행 중에는 인터럽트가 허용되지 않고, 다른 버스 마스터들은 버스를 사용할 수 없기 때문에 상대적으로 비용이 큰 메모리 연산을 수행하는 swp은 병목현상을 유발하는 원인이 될 수 있다.

ldrexstrex 명령은 하나의 상태머신을 사용하는데, open과 exclusive 상태를 갖는다. ldrex 명령은 모니터 상태를 exclusive로 갱신하고, strex명령은 모니터 상태가 exclusive일 때만 성공할 수 있다. 멀티 프로세서 시스템에서 동기화를 지원하기 위해서는 두개의 모니터가 구현되어야 한다. Non-shareable 메모리 영역에 대한 배타적 접근(ldrex, strex)은 지역local 모니터만을 체크하는 반면, Shareable 메모리 영역에 대한 접근은 지역 모니터와 더불어 global 모니터 체크도 이루어진다. 문맥전환후 지역 모니터는 open 상태로 리셋되어야 한다, clrex(동일 프로세서에서 문맥전환으로 태스크가 뒤바뀐 상태에서의 ldrexstrex의 매칭 오류는 판독 불가능하기 때문).

곧 공유 메모리에 대한 접근은 한번에 하나의 프로세서만이 가능하다. 말하자면, 공유 메모리 동기화는 단일 프로세서이든 멀티 프로세서이든 앞선 원자적 실행 매커니즘만으로 보장된다. 하지만, 공유자원은 인터럽트와 일반 태스크 모두가 접근 가능하고 원자적 실행을 보장할 수 없는 코드상의 임계구역critical region일 수 있다. 바로 lock이라는 상호배제 기술이 필요한 지점이다.

단일 프로세서 시스템에서 동기화는 단순히 임계구역 진입시 인터럽트를 금지하는 것으로 해결할 수 있지만, 인터럽트 금지는 프로세서를 독점하는 고비용 방법이다. 반면, 원자적 실행 매커니즘으로 lock이라는 상호배제 기술을 구현할 수 있다. lock으로 잠겨진 임계구역은 해당 키를 얻어야만 진입할 수 있으므로 의도한 동기화가 실현된다(인터럽트 문맥에서도 접근하는 임계구역이라면, 또는 문맥전환이 일어난다면, 교착상태deadlock가 발생할 수 있지만, 교착상태에 대해서는 여기서 논하지 않는다). 멀티 프로세서에서 동기화도 동일한 방법으로 이루어진다. 다만, 인터럽트 및 일반 태스크 모두가 접근 가능한 공유 메모리에 대해서는 인터럽트 금지 후(지역local적 일관성을 확보한 후) lock을(전체global적 일관성을) 얻어야 한다.

아래 그림에서 세마포어(뮤텍스)는 sleep 가능한 long term waiting, 스핀락은 sleep 불가능한 short term waiting 으로 가정한다:

                           ---- 인터럽트 금지 ---
 --- 세마포어(뮤텍스) ---      |   --- 스핀락 ---   |
|                   |     |  |    선점     |  |
|    일반 공유자원     |     |  |   불가능    |  |
|                   |     |  |   공유자원   |  |
 -------------------      |   ------------   |
                           ------------------

 ---------------------------------------------------------------------
|           | 일반 태스크 간의 공유 메모리 동기화 | 인터럽트 개입이 고려된 공유 메모리 동기화 |
|-----------|--------------------------|------------------------------|
| 단일 프로세서 | 원자적 실행 매커니즘으로 구현된  | 인터럽트 금지                   |
|           | lock 사용                 | (e.g. preempt_disable())     |
|           | (e.g. mutex_lock())      |                              |
|-----------|--------------------------|------------------------------|
| 멀티 프로세서 | 동일                      | 인터럽트 금지 후 lock 사용        |
|           |                          | (e.g. spinlock_irqsave())    |
 ---------------------------------------------------------------------

이 모두를 가능케 한 하드웨어 기술자들에게 감사의 마음을..