์ค๋ ๋(Thread)
โ ์คํ ๊ฐ๋ฅํ ์ต์ ๋จ์์
๋๋ค. PintOS์์ ๊ฐ๊ฐ์ ์ค๋ ๋๋ struct thread ๊ตฌ์กฐ์ฒด๋ก ํํ๋ฉ๋๋ค.
์ฐ์ ์์(Priority)
โ ์ซ์๊ฐ ํด์๋ก ์ฐ์ ์์๊ฐ ๋์ต๋๋ค.
priority ํ๋๊ฐ ์ค๋ ๋์ ์ฐ์ ์์๋ฅผ ๋ํ๋
๋๋ค. ์ด ๊ฐ์ ์ค์ผ์ค๋ฌ๊ฐ ๋๊ตฌ์๊ฒ CPU๋ฅผ ์ค์ง ๊ฒฐ์ ํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
์ด์์ฒด์ ๋ ready_list ์์ ์๋ ์ค๋ ๋๋ค ์ค ๊ฐ์ฅ ๋์ priority๋ฅผ ๊ฐ์ง ์ค๋ ๋๋ฅผ ๊ณจ๋ผ CPU๋ฅผ ํ ๋นํฉ๋๋ค.
list_insert_ordered(&ready_list, &t->elem, priority_cmp, NULL);
์ด ์ ๋ ฌ์ด ์ ๋์ด ์์ผ๋ฉด ๋ฎ์ priority๊ฐ ๋จผ์ ์คํ๋๋ ์ด์ํ ์ํฉ์ด ์๊น๋๋ค.
ํ์ฌ ์คํ ์ค์ธ ์ค๋ ๋๋ณด๋ค ๋ ๋์ priority์ ์ค๋ ๋๊ฐ ๊นจ๊ฑฐ๋ ์์ฑ๋๋ฉด,
ํ์ฌ ์ค๋ ๋๋ CPU๋ฅผ ์๋ณดํด์ผ ํฉ๋๋ค.
if (!intr_context() && thread_current()->priority < max_priority)
thread_yield();
intr_context()๋ ์ธํฐ๋ฝํธ ์ฒ๋ฆฌ ์ค์ธ์ง ํ์ธํฉ๋๋ค.thread_yield()๋ ํ์ฌ ์ค๋ ๋๋ฅผ ready_list๋ก ๋ณด๋ด๊ณ ์ค์ผ์ค๋ง์ ๋ค์ ํฉ๋๋ค.๋ฎ์ priority์ ์ค๋ ๋๊ฐ ๋ฝ์ ์ฅ๊ณ ์๊ณ , ๋์ priority์ ์ค๋ ๋๊ฐ ๊ทธ ๋ฝ์ ๊ธฐ๋ค๋ฆฌ๋ ์ํฉ์ด ์ค๋ฉด?
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด Priority Donation ๊ฐ๋ ์ด ๋ฑ์ฅํฉ๋๋ค.
๋์ priority์ ์ค๋ ๋๊ฐ ๋ฝ์ ์ฅ๊ณ ์๋ ๋ฎ์ priority์ ์ค๋ ๋๋ฅผ ๊ธฐ๋ค๋ฆด ๋,
์์ ์ priority๋ฅผ ์์๋ก ๊ธฐ๋ถํฉ๋๋ค.
lock_acquire() ๋์ค lock์ด ์ด๋ฏธ ๋ค๋ฅธ ์ค๋ ๋์ ์ํด ์ฌ์ฉ ์ค์ผ ๋waiting_lock ํ๋๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉฐ holder์๊ฒ priority๋ฅผ ์ ๋ฌint original_priority; // ๊ธฐ๋ถ๋ฐ๊ธฐ ์ ์ฐ์ ์์ ์ ์ฅ
struct lock *waiting_lock; // ๋ด๊ฐ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ ๋ฝ
struct list donations; // ๋์๊ฒ ์ฐ์ ์์๋ฅผ ๊ธฐ๋ถํ ์ค๋ ๋๋ค
ํ๋์ ์ค๋ ๋๊ฐ ๋ ๋ค๋ฅธ ๋ฝ์ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ค๋ฉด?
Thread C (priority 50) โ ๋๊ธฐ ์ค: lock2
Thread B (priority 20) โ lock2 holder, ๋๊ธฐ ์ค: lock1
Thread A (priority 10) โ lock1 holder
์ด๋ ๊ฒ ์ฐ๊ฒฐ๋ ์ํฉ์์, Thread C๋ B์๊ฒ, B๋ A์๊ฒ priority๋ฅผ ์์ฐจ์ ์ผ๋ก ๊ธฐ๋ถํด์ผ ํฉ๋๋ค.
โ ๋๋ค์ด์ ์ ์ฌ๊ท์ ์ผ๋ก ์ ๋ฌ๋์ด์ผ ํฉ๋๋ค.
while (lock && lock->holder && lock->holder->priority < t->priority)
{
lock->holder->priority = t->priority;
lock = lock->holder->waiting_lock;
}
๋ฝ์ ํด์ ํ ๋๋ ํด๋น ๋ฝ์ ํตํด ๋ฐ์ donation์ ๋๋๋ ค์ผ ํฉ๋๋ค.
remove_with_lock(lock); // ํด๋น ๋ฝ ๊ด๋ จ donation ์ ๊ฑฐ
refresh_priority(); // ๊ฐ์ฅ ๋์ donation์ผ๋ก priority ๋ณต์
ready_list, sema->waiters, condvar->waiters ๋ฑ ๋ชจ๋ ๋๊ธฐ ํ๋ priority ์์๋๋ก ์ ๋ ฌ๋์ด์ผ ํฉ๋๋ค.
bool priority_cmp(const struct list_elem *a, const struct list_elem *b, void *aux UNUSED)
{
return list_entry(a, struct thread, elem)->priority
> list_entry(b, struct thread, elem)->priority;
}
๋ฝ(lock): ํ ๋ฒ์ ํ๋์ ์ค๋ ๋๋ง ์์์ ์ฌ์ฉํ๋๋ก ์ ์ด
โ lock_acquire(), lock_release()์์ donation ์ฒ๋ฆฌ ํ์
์ธ๋งํฌ์ด(semaphore): ๋๊ธฐ ํ์ signal ๊ฐ๋
์ผ๋ก ์์์ ์ ์ด
โ sema_down()์์ priority ์์๋ก ๋๊ธฐ ํ ์ฝ์
์กฐ๊ฑด๋ณ์(condvar): ์ด๋ค ์กฐ๊ฑด์ด ๋ง์กฑ๋ ๋๋ง ๊นจ์ฐ๊ธฐ
โ cond_signal()์์ ๊ฐ์ฅ ๋์ priority ์ค๋ ๋๋ฅผ ๊นจ์์ผ ํจ
| ๊ตฌํ ํญ๋ชฉ | ์ค๋ช | ๊ด๋ จ ํ ์คํธ |
|---|---|---|
ready_list ์ ๋ ฌ | ๋์ priority๊ฐ ์์ | priority-fifo, priority-preempt |
donate_priority() | ๊ธฐ๋ถ ๋ก์ง | priority-donate-one, -multiple, -nest, -chain |
remove_with_lock() | donation ์ ๊ฑฐ | priority-donate-multiple2, -lower |
thread_set_priority() | ์ฐ์ ์์ ์๋ ๋ณ๊ฒฝ | priority-change |
sema/cond ์ ๋ ฌ | ์ธ๋งํฌ์ด / ์กฐ๊ฑด๋ณ์ ๋๊ธฐ ์์ ์ ๋ ฌ | priority-sema, priority-condvar |
| ์ฉ์ด | ์ค๋ช |
|---|---|
| Thread (์ค๋ ๋) | CPU์์ ์คํ ๊ฐ๋ฅํ ์์ ๋จ์ |
| Priority (์ฐ์ ์์) | ์ค๋ ๋์ ์คํ ์ฐ์ ๋ |
| Preemption (์ ์ ) | ๋ ๋์ priority๊ฐ ๋ํ๋ ๋ CPU๋ฅผ ์๋ณดํ๋ ๊ฒ |
| Priority Inversion | ๋ฎ์ priority๊ฐ ๋์ priority๋ฅผ ๋ง๋ ํ์ |
| Donation | ๋์ priority๊ฐ ๋ฎ์ priority์๊ฒ ์ฐ์ ๊ถ์ ์ผ์์ ์ผ๋ก ๋๊ฒจ์ฃผ๋ ๊ฒ |
| Chain Donation | ๋๋ค์ด์ ์ด ์ฌ๋ฌ ์ค๋ ๋์ ๊ฑธ์ณ ์ฐ์์ ์ผ๋ก ์ผ์ด๋๋ ๊ฒ |
| Rollback | ๋ฝ ํด์ ์ ๋๋ค์ด์ ์ ํ์ํ๊ณ ์๋ priority ๋ณต์ |
| Lock | ์์์ ๋ํ ์ ๊ทผ์ ์ ํํ๋ ๋๊ธฐํ ๊ธฐ๋ฒ |
| Semaphore | ๋๊ธฐ ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ณ ์ ์ ๋๊ธฐํ ๊ธฐ๋ฒ |
| Condvar | ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋๊น์ง ๋๊ธฐํ๋ ๊ตฌ์กฐ |
PintOS Project 1์ priority-* ๊ด๋ จ ๊ธฐ๋ฅ๋ค์ ์๋ก ๊ฐํ๊ฒ ์ฐ๊ฒฐ๋์ด ์์ต๋๋ค.
๋จ์ํ ์์๋๋ก ๊ตฌํํ๋ ๊ฒ ์๋๋ผ, ๊ธฐ๋ฅ ๊ฐ ์์กด์ฑ์ ๊ณ ๋ คํด์ ์์๋ฅผ ์ ํด์ผ ํ
์คํธ๊ฐ ์ ๋๋ก ํต๊ณผ๋ฉ๋๋ค.
| ๋จ๊ณ | ๊ตฌํ ํญ๋ชฉ | ์์กด ์ด์ |
|---|---|---|
| 1๏ธโฃ | ready_list ์ ๋ ฌ | ๋ชจ๋ priority ์ค์ผ์ค๋ง ๋ก์ง์ ๊ธฐ๋ฐ. ์ค๋ ๋๊ฐ ๊นจ์ด๋ ๋ ์ฌ๋ฐ๋ฅธ ์์๋ก ์ ๋ ฌ๋์ด ์์ด์ผ ์ดํ donation๋ ์๋ฏธ ์์. |
| 2๏ธโฃ | donate_priority() | ๋๋ค์ด์ ๋ก์ง ๊ตฌํ. ์ญ์ ํ์ ํด๊ฒฐ์ ํต์ฌ์ด๋ฉฐ, ready_list ์ ๋ ฌ์ด ๋์ด์ผ๋ง donation์ด ํจ๊ณผ์ ์ผ๋ก ๋ฐ์๋จ. |
| 3๏ธโฃ | remove_with_lock() & refresh_priority() | ๋ฝ ํด์ ์ ๋๋ค์ด์ ํ์. donation์ด ๊ตฌํ๋ ํ์์ผ ํ์ํ๋ฉฐ, rollback ๋ก์ง์ผ๋ก ๋ฐ๋์ ์ด์ด์ ธ์ผ ํจ. |
| 4๏ธโฃ | thread_set_priority() | ์ฌ์ฉ์๊ฐ ์๋์ผ๋ก priority๋ฅผ ๋ฐ๊ฟ ๋, donation ์ฌ๋ถ์ ๋ฐ๋ผ ์ด๋ค ๊ฐ์ ๋ฐ์ํ ์ง ๊ฒฐ์ ํด์ผ ํจ. donation ๋ก์ง์ด ์ ํ๋์ด์ผ ์๋ฏธ ์์. |
| 5๏ธโฃ | sema_down() / cond_signal() ์ ๋ ฌ | ์ธ๋งํฌ์ด/์กฐ๊ฑด๋ณ์ waiters ๋ฆฌ์คํธ๋ priority ๊ธฐ๋ฐ ์ ๋ ฌ์ด ํ์. ๋ฝ ๊ธฐ๋ฐ donation ๋ก์ง์ด ๋ชจ๋ ๋์ํ ์ดํ ๊ตฌํํ๋ ๊ฒ ์์ . |
์ ๋ ฌ ๋จผ์ โ donation ๋์ค
๋๋ค์ด์
์ ํด๋ ready_list๊ฐ FIFO ๋ฐฉ์์ด๋ผ๋ฉด ๋์ priority ์ค๋ ๋๋ ์คํ๋์ง ๋ชปํจ โ ํ
์คํธ ์คํจ
rollback์ donation ์์ด๋ ์๋ฏธ ์์
๋๋ค์ด์
์ด ์๋๋ฐ rollback ๋จผ์ ๊ตฌํํ๋ฉด ์ฝ๋๋ง ๋ณต์กํด์ง๊ณ ํ
์คํธ์ ์ํฅ ์์
์ธ๋งํฌ์ด ์ ๋ ฌ์ ๋ง์ง๋ง์
๊ธฐ๋ณธ์ ์ธ ๋ฝ ๊ธฐ๋ฐ donation์ด ์์ ํ ์๋ํ ํ์, ๋๋จธ์ง ๋๊ธฐํ ๊ตฌ์กฐ์ priority-aware ๋์์ ํ์ฅํ๋ฉด ๋๋ค