BLOG ARTICLE condition variable | 1 ARTICLE FOUND

  1. 2007.12.27 OS분석(3) picoKernel 1

OS분석(3) picoKernel

OS 2007. 12. 27. 16:41
2. 동기화
멀티태스킹으로 일을 처리하게 되면 둘 이상의 프로세스 혹은 스레드가 동시에 한 데이터에 접근하는 경우가 발생하는데 이럴 때 동기화 문제가 발생한다.
A와 B라는 두개의 스레드가 있고 alpha라는 공유변수가 있다고 가정할 때
두 스레드 A, B가 동시에 alpha라는 변수에 접근하여 데이터를 변경한다면 문제가 발생할 수 있다.
또한 두 스레드 A, B에서 변수 alpha에 접근하는 부분을 크리티컬 섹션 혹은 크리티컬 리젼이라고 부르며
이 섹션들 간에는 상호 배재 즉 상대방이 실행하고 있으면 다른 녀석들은 이에 접근할 수 없도록 조치해야한다.
picoKernel 에서는 이러한 상황을 해결하기 위한 동기화 방법에는 아래와 같은 방법이 있다.
뮤텍스(mutex)
세마포어(semaphore)
조건변수(condition variable)

2.1 뮤텍스
뮤텍스는 일종의 변수이고 해당 크리티컬 섹션에 대해 lock상태인지 아닌지에 대한 정보를 가지고 있다.
크리티컬 섹션에 진입할 때 해당 섹션이 lock상태이면 unlock이 될 때까지 기다리게 되는데
unlock이 될 때까지 계속 체크하는 비지 웨이팅방식이 아니라 해당 스레드 혹은 프로세스가 running상태에서
waiting상태로 넘어가게 된다. 다시 크리티컬 섹션에 진입할 때 unlock상태이면 자신이 진입했다는 표시로
lock을 걸어둔다. lock을 걸어둔 스레드 혹은 프로세스가 unlock을 할 때는 프로세스의 대기 목록에서 lock이 풀리기를 기다리는 프로세스들 중 하나를 깨워준다.

picoKernel에서는 뮤텍스로 사용할 변수를 선언하고 mutexCreate함수를 호출한다.
내부적으로 전체 뮤텍스의 엔트리를 가지고 관리하며 아직 할당하지 않은 뮤텍스의 id를 반환한다.
뮤텍스 엔트리의 구조체는 unlock을 기다리는 thread의 리스트를 가리키기 위한 thread엔트리 포인터(mHead, mTail)와 현재 lock을 걸어둔 thread의 엔트리 포인터(mOwner)를 가지고 있다.

mutexLock함수로 크리티컬 섹션에 진입할 때 내부적으로 mOwner가 null이 아니면 lock상태이고
null이면 unlock상태이다. null이 아니어서 lock상태라면 자신(thread)의 상태를 waiting상태로 바꾸고
해당 뮤텍스의 대기 리스트에 저장후 대기하고 있던 리스트안에 있는 thread를 실행하게 된다.

mutexUnlock함수는 대기중인 스레드 중에서 하나만 ready상태로 전환한다.
해당 뮤택스의 mOwner를 null로 바꾸고 내부에 해당 뮤텍스에 등록되어 있는 대기 리스트를 업데이트 한다.

2.2 세마포어
세마포어는 뮤택스보다는 조금 확장된 개념으로 볼 수 있는데 뮤택스가 해당 크리티컬 섹션에 진입할 수 있는 스레드나 프로세스의 개수가 하나라면 세마포어는 하나 이상으로 설정할 수 있다.
개념은 뮤택스와 비슷하다.
picoKernel에서는 세마포어 엔트리로 세마포어를 관리하는데 하나의 엔트리는 뮤택스와 마찬가지로 대기하고 있는 thread 엔트리 포인터(sHead, sTail)가 있고 세마포어 값으로 구성되어 있다.

세마포어를 사용하기 위해 초기에 semCreate 함수를 호출하는데 매개변수로 세마포어의 값을 입력받는다.
비어있는 세마포어 id를 리턴한다.

semWait함수는 해당 세마포어가 가진 값이 0보다 크면 해당 크리티컬 섹션에 진입이 가능하며 초기에 세마포어를 생성했던 값을 -1하게 된다. 여러 thread들이 semWait를 호출하게 되여 세마포어의 값이 0이 되면 더 이상 다른 스레드의 진입이 불가능하고 이 때 해당 스레드가 waiting상태로 넘어가게 된다.

semSignal함수는 반대로 크리티컬 섹션에서 나올 때 세마포어의 값을 1 증가시키며 대기하고 있던 스레드중에 하나를 깨우게 된다. 뮤택스와 마찬가지로 대기리스트를 업데이트한다.

2.3 조건변수
조건변수로 선언후 wait, signal로 사용하는데 해당 변수 예를 들어 a라는 조건 변수가 있을 때
a.wait()을 호출하면 다른 프로세스 혹은 다른 thread에서 a.signal()을 호출할 때까지 무조건 대기한다.

picoKernel에서는 condCreate함수로 초기화를 하고 조건변수의 id를 리턴한다.
조건변수의 엔트리는 해당 조건을 기다리고 있는 스레드의 개수와 동기화를 위한 세마포어로 구성되어 있다.

condWait함수는 id와 모니터로 사용하는 뮤텍스를 인자로 넘겨받아 조건변수 엔트리의 대기 스레드 개수를 +1 해주고 다른 스레드에서 Signal을 보낼때까지 기다릴 수 있도록 semWait하게 된다. 이 때 뮤택스로 조건변수와 semWait를 보호한다.

condSignal함수는 해당 조건변수의 대기 스레드 카운터가 0보다 크면 즉 비어있지 않으면 카운터값을 -1시키고 해당 세마포어를 semSignal하게 된다. 역시 이 부분도 뮤택스로 보호해주어야 한다.


AND