-
Week 9 LearnedWIL 2026. 5. 1. 18:46
- What
9주차의 첫째는 Pintos Project 1 - Threads 자체였다. Jungle/Week9/README.md를 보면 이번 프로젝트의 목표는 Alarm Clock, Priority Scheduling, Priority Donation, MLFQS를 구현하고 테스트하는 것이었다.
둘째는 구현 방식 자체를 정리한 팀 학습 계획이었다. 각자가 같은 범위를 공부하고 자기 브랜치에서 직접 구현한 뒤, 하루 끝에 구현과 이해 내용을 발표하고, 가장 이해하기 쉽고 안정적인 방식만 main에 반영하는 구조였다. 즉 이번 주는 코드 한 벌을 빨리 만드는 주라기보다, 4명이 모두 같은 흐름을 설명할 수 있는 코드를 고르는 주에 가까웠다.
셋째는 작업 규칙과 발표 정리였다. Jungle/Week9/CLAUDE.md에는 DevContainer 안에서만 개발, source pintos/activate 후 명령 실행, 위험한 Git 명령 금지, 커밋 메시지 규칙 같은 작업 기준이 정리돼 있었고, presentation/readyqueue_week9_learning_speaker_notes.md와 week9_pintos_threads_mspark_slide.md에는 이번 주에 무엇을 배웠는지, 특히 priority donation의 nested/chain 전파를 어떻게 이해했는지가 발표용 문장으로 정리되어 있었다.
2. How
- 이번 주는 바로 코드를 고치기보다 thread.c, synch.c, timer.c, thread.h, synch.h를 먼저 읽고 실행 흐름을 잡는 방식으로 시작했다.
- 학습 계획에서는 0.5일차에 thread_create -> thread_unblock -> ready_list -> schedule -> next_thread_to_run 흐름을 설명할 수 있게 만드는 것을 첫 목표로 두었다.
- 구현과 검증은 반드시 DevContainer 내부에서 하고, source pintos/activate 후 make, make check, 개별 테스트 명령을 실행하는 방식으로 통일했다.
3. Approach
이번 주 접근은 "정답 코드를 빨리 얻는 것보다, 운영체제 흐름을 직접 추적해 구현 가능한 모델로 바꾸는 것"이었다.
Pintos Threads 자체는 단순 기능 추가 과제가 아니었다. timer_sleep() 하나를 고칠 때도 busy waiting이 왜 문제인지, 잠든 thread가 왜 ready_list가 아니라 별도 sleep list에 있어야 하는지, timer_interrupt() 안에서 왜 lock을 함부로 쓰면 안 되는지를 같이 이해해야 했다. 그래서 이번 주는 구현 범위를 기능 이름만으로 보지 않고, "어떤 상태 전환이 일어나는가" 기준으로 접근했다.
Priority Scheduling과 Donation에서도 같은 방식이 반복됐다. ready_list만 정렬하면 끝나는 것이 아니라, semaphore와 condition variable의 waiters까지 priority 기준으로 깨워야 전체 scheduler 정책이 맞물린다는 점을 확인했다. donation은 "높은 priority를 잠깐 올려준다" 정도로 이해하는 데서 끝나지 않고, base_priority, effective priority, wait_lock, donations가 각각 어떤 책임을 가지는지로 쪼개어 봤다.
발표 메모에서 정리된 것처럼, chain donation은 donations 리스트가 아니라 wait_lock을 따라 올라가야 한다는 점이 중요한 전환점이었다. 즉 이번 주의 접근은 "기능 설명"보다 "필드 변화와 호출 흐름"을 중심으로 생각하는 쪽이었다.
4. Learned
운영체제 코드는 main()부터 끝까지 따라가는 읽기 방식이 효과적이었다
이번 주 발표 메모에서 가장 크게 남은 포인트는 init.c의 main()부터 시작해 흐름을 한 줄씩 따라가는 방식이었다. 단순 개념 요약보다 실제 호출 순서를 따라가는 편이 기억에 오래 남고, thread 상태 변화가 많은 Pintos에서는 특히 효과적이라는 점을 체감했다.
Alarm Clock은 "시간 재기"보다 상태 전환 문제였다
timer_sleep()은 단순히 일정 시간 기다리는 함수가 아니었다. busy waiting을 제거하고, sleeping thread를 block 상태로 바꾸고, timer interrupt에서 조건이 맞을 때 다시 unblock하는 흐름 자체가 핵심이었다. 즉 Alarm 문제는 시간 API보다 scheduler 상태 관리 문제에 가까웠다.
Priority Donation은 개념보다 필드 설계가 더 어려웠다
priority inversion이라는 개념은 비교적 빨리 받아들일 수 있지만, 그걸 실제 코드의 wait_lock, donations, base_priority 변화로 옮기는 순간 난이도가 확 올라간다. 특히 nested/chain donation은 단순 donor 목록이 아니라 "누가 어떤 lock을 기다리는가"를 따라가야 한다는 점이 중요했다.
5. Keep
- 공동 범위 학습 + 개인 구현 + 매일 통합 방식은 다음 운영체제 과제에서도 계속 가져가고 싶다.
- main()부터 시작해 실행 흐름을 추적하는 읽기 방식은 이후 userprog, vm, filesys에서도 그대로 유효할 것 같다.
- 테스트를 PASS/FAIL만 보지 않고 .c와 .ck를 같이 읽는 습관은 계속 유지할 가치가 있다.
- base_priority, effective priority, wait_lock처럼 필드 책임을 먼저 정리하고 구현에 들어가는 방식은 동기화 문제에서 특히 도움이 된다.
6. Problem
- 프로젝트 목표는 "4명 모두 설명 가능"이었지만, 구현 진행 상황과 채택된 방식이 어떤 이유로 선택되었는지에 대한 일일 기록은 더 촘촘했으면 좋았을 것 같다.
- AI 사용을 개념 학습 중심으로 제한하는 방향은 분명했지만, 그러다 보니 "어디까지는 스스로 이해했고 어디부터는 아직 막혔는지"를 구분하는 기록도 더 필요했다.
- Priority Donation과 MLFQS는 개념상 이해와 구현 난이도 차이가 큰데, 이 간극을 메우기 위한 상태 변화표나 필드 변화표가 최종 문서에는 충분히 남아 있지 않았다.
- 발표 메모는 잘 정리되어 있었지만, 프로젝트 README 수준에서는 구현 완료 범위와 남은 이슈가 더 직접적으로 드러나면 좋았을 것 같다.
7. Try
- 다음에는 Day별로 읽은 함수, 바꾼 필드, 통과한 테스트, 막힌 이유를 같은 형식으로 남긴다.
- donation 같은 동기화 로직은 "개념 설명"과 "필드 변화표"를 같이 적어서, 이해와 구현 사이의 간극을 줄인다.
- MLFQS처럼 수식과 갱신 주기가 중요한 문제는 tick 단위 표를 먼저 만들어 두고 구현한다.
- README에는 목표만 적지 말고, 현재 통과 테스트와 남은 테스트를 체크리스트로 바로 보이게 정리한다.
- 발표 준비는 마지막에 한꺼번에 하지 말고, 매일 발표 형식으로 축적한 메모를 그대로 발표 자료로 연결한다.
8. Make Up For
이번 주에 가장 먼저 메꿔야 하는 부분은 "Pintos Threads 구현 상태를 검증 가능한 형식으로 남기는 것"이다.
- Alarm, Priority, Donation, MLFQS 각각에 대해 현재 통과 테스트와 남은 테스트를 표로 정리해야 한다.
- thread.c, synch.c, timer.c에서 실제로 바꾼 핵심 필드와 함수 흐름을 짧게 문서화해야 한다.
- nested/chain donation은 말로만 이해하지 말고, High -> Medium -> Low 전파 경로를 상태 변화 다이어그램으로 고정해 두는 편이 좋다.
- 다음 주에는 구현 추가 전에 "내가 현재 어디까지 이해했고 무엇이 아직 불안정한지"를 먼저 적어서, 설명 가능한 상태와 실제 구현 상태의 차이를 줄여야 한다.
'WIL' 카테고리의 다른 글
Week 10 Learned (0) 2026.05.07 Week 8 Learned (0) 2026.04.23 Week 7 Learned (1) 2026.04.16 Week 6 Learned (0) 2026.04.09 Week 5 Learned (0) 2026.04.02