2025. 5. 25. 13:05ㆍ개발
Pintos에서 Condition Variable(condvar)의 동작 방식과 구조
Condvar란 무엇인가?
Condition Variable(조건 변수)는 멀티스레드 환경에서 자주 사용되는 동기화 도구 중 하나다. 일반적으로 어떤 특정 조건이 만족될 때까지 스레드를 대기 상태로 만들고, 그 조건이 충족되었을 때 다시 깨어나게 하기 위한 메커니즘이다.
흔히 cond_wait(), cond_signal(), cond_broadcast()의 세 가지 주요 함수로 사용된다.
예시로 이해하기: 생산자-소비자 문제
Condition Variable이 필요한 이유를 이해하기 위해 가장 대표적인 예시인 생산자-소비자 문제를 살펴보자.
- 생산자는 버퍼가 가득 찬 상태에서는 데이터를 더 넣을 수 없기 때문에, 버퍼에 공간이 생길 때까지 기다려야 한다.
- 소비자는 버퍼가 비어 있는 상태에서는 데이터를 꺼낼 수 없기 때문에, 데이터가 들어올 때까지 기다려야 한다.
이때 단순히 lock을 이용한 상호배제만으로는 "조건이 만족되었는지"를 제대로 처리할 수 없다. 그래서 조건 자체를 기다릴 수 있도록 도와주는 Condition Variable이 필요한 것이다.
Condition Variable의 역할
Condition Variable은 "조건이 만족되기 전까지 스레드를 block 상태로 만들고", "조건이 만족되면 해당 스레드를 다시 깨우기 위한 도구"다.
단순한 lock은 동시에 접근하는 것을 막을 수는 있지만, 조건 자체를 기다리는 기능은 없다. 즉, 어떤 상태(state)가 만족되기를 기다리는 스레드를 명확하게 관리하기 위해 condvar가 필요하다.
Pintos의 condvar는 조금 다르다
실제 운영체제에서는 보통 조건 변수를 다음과 같이 사용한다:
lock_acquire(&lock);
while (!조건) {
cond_wait(&cond, &lock);
}
lock_release(&lock);
하지만 Pintos의 condvar는 조건을 직접 검사하지 않는다.
예를 들어, priority-condvar 테스트에서는 단순히 스레드들이 cond_wait()로 잠들고, 우선순위(priority) 순서대로 잘 깨어나는지를 검증하는 구조로 되어 있다.
그럼 cond->waiters 리스트는 왜 따로 관리할까?
- 만약
ready_list에 넣는다면, 이 스레드가 어떤 조건을 기다리는지 알 수 없다. ready_list는 CPU 실행을 기다리는 스레드들을 위한 큐다. 조건을 기다리는 것과는 다르다.- 따라서
cond->waiters라는 별도의 리스트로 관리하여 조건 대기 스레드들을 구분한다.
Condvar의 동작 흐름
cond_wait()을 호출하면struct semaphore_elem을 하나 생성하여cond->waiters에 추가한다.- 그 후, 현재 스레드는 락을
release하고,sema_down()을 호출하여 블록된다. cond_signal()이 호출되면,cond->waiters리스트에서 우선순위가 가장 높은 세마포어를 선택한다.- 선택된 세마포어에 대해
sema_up()을 호출하여 대기 중인 스레드를 깨운다. - 스레드는 깨어나면서 다시 락을 획득하고 나머지 작업을 계속 수행한다.
구조 요약
cond->waiters는struct semaphore_elem타입의 리스트다.- 각
semaphore_elem은struct semaphore를 포함한다. - 스레드는 대기 시, 자신 전용 세마포어에 블록되고
waiters리스트에 추가된다. cond_signal()은sema_priority_compare()를 통해 우선순위 높은 세마포어를 선택해 깨운다.
// cond_signal 구현 예시
void cond_signal(struct condition *cond, struct lock *lock) {
if (!list_empty(&cond->waiters)) {
list_sort(&cond->waiters, sema_priority_compare, NULL);
struct semaphore_elem *sema_elem =
list_entry(list_pop_front(&cond->waiters), struct semaphore_elem, elem);
sema_up(&sema_elem->semaphore);
}
}
핵심 비교: ready_list vs cond->waiters
Condition Variable과 ready_list의 역할을 혼동하지 않아야 한다.
| 구분 | ready_list | cond->waiters |
|---|---|---|
| 의미 | 실행 준비가 완료된 스레드들 | 특정 조건을 기다리는 스레드들 |
| 상태 | 바로 스케줄링 가능 | 조건 충족 전까지는 block 상태 |
| 목적 | CPU 자원 요청 | 조건 만족 대기 |
결론 정리
- Condition Variable은 조건을 기다리는 스레드를 블록시키고, 조건이 충족될 때 깨우는 동기화 도구다.
- Pintos에서는 조건 검사는 생략되어 있고, condvar 구조가 우선순위 기반 스레드 깨어남을 검증하는 데에 집중되어 있다.
cond->waiters는 단순히 깨어날 준비가 된 것이 아니라, 특정 조건을 기다리는 스레드의 모음이다.
'개발' 카테고리의 다른 글
| [Pintos] 타이머 인터럽트 때문에 랜덤 커널 패닉이 터진 이유와 해결 방법 (0) | 2025.05.29 |
|---|---|
| [Pintos] userprog- exec 개발하면서 겪었던 문제 (0) | 2025.05.27 |
| pintos project 1 threads (0) | 2025.05.25 |
| pintos 프로젝트 시작하기 (0) | 2025.05.25 |
| 프록시 서버에서 캐시 최신화 방법들 (0) | 2025.05.15 |