
| ํ ์คํธ ์ด๋ฆ | ๋ชฉ์ |
|---|---|
| alarm-single | ์ฌ๋ฌ ์ค๋ ๋๊ฐ 1๋ฒ์ฉ ์๊ณ ์ ํํ ๊นจ์ด๋๋๊ฐ |
| alarm-multiple | ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์ฌ๋ฌ ๋ฒ ๋ฐ๋ณตํด์ sleep/wakeup ํ๋๊ฐ |
| alarm-simultaneous | ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ๊ฐ์ tick์ ๊นจ์ด๋๋๊ฐ |
| alarm-priority | sleep ์ค์๋ ์ฐ์ ์์ ์ค์ผ์ค๋ง์ด ์ง์ผ์ง๋๊ฐ |
| alarm-zero | timer_sleep(0)์ด ์ฆ์ ๋ฐํ๋๋๊ฐ |
| alarm-negative | ์์ ticks์๋ ์์คํ ์ด ์์ ์ ์ผ๋ก ์๋ํ๋๊ฐ |
timer_sleep() ์์ (timer.c)// ํ์ฌ ์ค๋ ๋๋ฅผ ์ฃผ์ด์ง tick ์๋งํผ ์ ๋ค๊ฒ ๋ง๋๋ ํจ์
void timer_sleep(int64_t ticks) {
// ๋ง์ฝ ticks๊ฐ 0 ์ดํ๋ผ๋ฉด, ๋ฐ๋ก ๋ฆฌํด (์ฆ, ์ ๋ค ํ์ ์์)
// ์: timer_sleep(0), timer_sleep(-1) ๋ฑ โ ๊ทธ๋ฅ ๋ฌด
์
if (ticks <= 0) return;
// ํ์ฌ ์๊ฐ์ ๊ฐ์ ธ์์, ์ธ์ ๊นจ์ด๋์ผ ํ ์ง๋ฅผ ๊ณ์ฐ
// ์ง๊ธ ์๊ฐ + ticks ๋งํผ์ด ๊นจ์ด๋์ผ ํ ์์
int64_t wakeup_tick = timer_ticks() + ticks;
// ํ์ฌ ์ค๋ ๋๋ฅผ sleep_list์ ๋ฃ๊ณ BLOCK ์ํ๋ก ์ ํ
// ๊นจ์ด๋์ผ ํ ์๊ฐ์ธ wakeup_tick์ ์ ์ฅํ๊ณ ์ ๋ ฌ ์ฝ์
thread_sleep(wakeup_tick);
}
โ ๋ฐ์ ๋๊ธฐ(busy wait)๋ฅผ ์์ ๊ณ , BLOCK ๋ฐฉ์์ผ๋ก sleep ์์ฒญ์ ์ฒ๋ฆฌํ๋๋ก ์์ ํจ.
thread_sleep() ๊ตฌํ (thread.c)// ํ์ฌ ์ค๋ ๋๋ฅผ ๊นจ์ด๋์ผ ํ ์์ (wakeup_tick)๊น์ง BLOCK ์ํ๋ก ๋ง๋ค๊ณ sleep_list์ ์ถ๊ฐํ๋ ํจ์
void thread_sleep(int64_t wakeup_tick) {
// ํ์ฌ ์คํ ์ค์ธ ์ค๋ ๋์ ํฌ์ธํฐ๋ฅผ ๊ฐ์ ธ์ด
struct thread *curr = thread_current();
// sleep_list๋ ๊ณต์ ์์์ด๊ธฐ ๋๋ฌธ์, ์ธํฐ๋ฝํธ๋ฅผ ์ ์ ๋นํ์ฑํํ์ฌ ์ถฉ๋ ๋ฐฉ์ง
enum intr_level old = intr_disable();
// ํ์ฌ ์ค๋ ๋๊ฐ ๊นจ์ด๋์ผ ํ ์๊ฐ์ ์ค๋ ๋ ๊ตฌ์กฐ์ฒด์ ๊ธฐ๋ก
curr->wakeup_tick = wakeup_tick;
// sleep_list์ ํ์ฌ ์ค๋ ๋๋ฅผ ๊นฐ ์๊ฐ ์์๋ก ์ ๋ ฌ ์ฝ์
// ์ด๋ ๋น๊ต ๊ธฐ์ค ํจ์๋ wakeup_compare()
list_insert_ordered(&sleep_list, &curr->elem, wakeup_compare, NULL);
// ํ์ฌ ์ค๋ ๋๋ฅผ BLOCK ์ํ๋ก ์ ํ โ ์ค์ผ์ค๋ฌ์ ์ํด ์คํ ์ค์ง๋จ
thread_block();
// ์ธํฐ๋ฝํธ ์ํ๋ฅผ ์๋๋๋ก ๋ณต์ (์์ ํ๊ฒ ๋ค์ ์ผ์ค)
intr_set_level(old);
}
โ ํ์ฌ ์ค๋ ๋๋ฅผ BLOCK ์ํค๊ณ , sleep_list์ ์ ๋ ฌ๋ ์ํ๋ก ์ฝ์
.
thread_awake() ๊ตฌํ (thread.c)// ํ์ฌ ์๊ฐ(now_tick)๋ณด๋ค ๋จผ์ ๊นจ์์ผ ํ ์ค๋ ๋๋ค์ sleep_list์์ ๊บผ๋ด READY ์ํ๋ก ๋ง๋๋ ํจ์
void thread_awake(int64_t now_tick) {
// sleep_list๊ฐ ๋น์ด์์ง ์์ ๋์ ๊ณ์ ๋ฐ๋ณต
while (!list_empty(&sleep_list)) {
// ๋ฆฌ์คํธ ๋งจ ์์ ์์๋ฅผ ๊ฐ์ ธ์์, ํด๋น ์ค๋ ๋ ํฌ์ธํฐ๋ก ๋ณํ
struct thread *t = list_entry(list_front(&sleep_list), struct thread, elem);
// ํด๋น ์ค๋ ๋์ wakeup_tick์ด ํ์ฌ ์๊ฐ๋ณด๋ค ๊ฐ๊ฑฐ๋ ์์ผ๋ฉด โ ๊นจ์ด๋ ์๊ฐ ๋๋ฌ
if (t->wakeup_tick <= now_tick) {
// ๋ฆฌ์คํธ์์ ํด๋น ์ค๋ ๋๋ฅผ ์ ๊ฑฐ
list_pop_front(&sleep_list);
// ํด๋น ์ค๋ ๋๋ฅผ READY ์ํ๋ก ์ ํ (๋ค์ ์คํ๋ ์ ์๊ฒ)
thread_unblock(t);
}
// ์์ง ๊นฐ ์๊ฐ์ด ๋์ง ์์ ์ค๋ ๋๊ฐ ๋งจ ์์ ์์ผ๋ฉด โ ๊ทธ ๋ค ์ค๋ ๋๋ค๋ ๋ชจ๋ later โ ์ ์ง
else break;
}
}
โ ๋งค tick๋ง๋ค ๊นฐ ์๊ฐ์ด ๋ ์ค๋ ๋๋ค์ READY ์ํ๋ก ๋ฐ๊ฟ.
wakeup_compare() ๊ตฌํ (thread.c)// sleep_list์ ์ค๋ ๋๋ฅผ ์ฝ์
ํ ๋ ์ฌ์ฉ๋๋ ๋น๊ต ํจ์
// wakeup_tick ๊ฐ์ ๊ธฐ์ค์ผ๋ก ์ค๋ฆ์ฐจ์ ์ ๋ ฌ๋๋๋ก ํ๋ค
static bool wakeup_compare(const struct list_elem *a, const struct list_elem *b, void *aux UNUSED) {
// a์ b๋ sleep_list ์์ ์์๋ค์ธ๋ฐ, list_elem ํ์
์ด๋ฏ๋ก
// ์ค์ ๋ก๋ struct thread ์์ ํฌํจ๋ elem ํ๋์
// ๋ฐ๋ผ์ list_entry ๋งคํฌ๋ก๋ฅผ ์ด์ฉํด ์๋ ๊ตฌ์กฐ์ฒด(= struct thread)๋ก ๋๋๋ฆผ
// a๊ฐ ๊ฐ๋ฆฌํค๋ thread์ wakeup_tick ๊ฐ์ด b๋ณด๋ค ์์ผ๋ฉด true ๋ฐํ
return list_entry(a, struct thread, elem)->wakeup_tick
< list_entry(b, struct thread, elem)->wakeup_tick;
}
โ sleep_list๋ฅผ ๊นฐ ์๊ฐ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌํ๊ธฐ ์ํ ๋น๊ต ํจ์.
timer_interrupt() ์์ (timer.c)// ํ์ด๋จธ ์ธํฐ๋ฝํธ๊ฐ ๋ฐ์ํ ๋๋ง๋ค ํธ์ถ๋๋ ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ
// 1์ด์ TIMER_FREQ(๊ธฐ๋ณธ 100ํ) ๋งํผ ์คํ๋จ
void timer_interrupt(struct intr_frame *args UNUSED) {
// ์์คํ
์ด ๋ถํ
๋ ์ดํ ํ๋ฅธ ์ ์ฒด tick ์๋ฅผ 1 ์ฆ๊ฐ์ํด
// โ tick์ PintOS์ ๊ธฐ๋ณธ์ ์ธ ์๊ฐ ๋จ์
ticks++;
// ํ์ฌ ์ค๋ ๋๊ฐ ํ tick ๋์ ์คํ๋์์์ ์ปค๋์ ์๋ฆผ
// โ ์ค์ผ์ค๋ง, CPU ์ ์ ์๊ฐ ๋ฑ ๋ด๋ถ ๊ด๋ฆฌ์ ์ฌ์ฉ๋จ
thread_tick();
// ์ง๊ธ tick๊น์ง ๋๋ฌํ ์ค๋ ๋๊ฐ ์๋ค๋ฉด ๊นจ์ฐ๊ธฐ
// โ sleep_list์ ์๋ ์ค๋ ๋๋ค์ ํ์ธํ๊ณ ,
// wakeup_tick์ด ํ์ฌ tick๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ ์ค๋ ๋๋ค์ READY๋ก ์ ํ
thread_awake(ticks);
}
โ ํ์ด๋จธ ์ธํฐ๋ฝํธ ๋ฐ์ ์๋ง๋ค ๊นฐ ์ค๋ ๋๋ฅผ ์ฒดํฌํด์ ๊นจ์ฐ๋ ํ๋ฆ ์ถ๊ฐ.
thread.h์ thread_sleep, thread_awake ํจ์ ์ ์ธ ์ถ๊ฐ (๊ฒฝ๊ณ ์ ๊ฑฐ ๋ชฉ์ )list_insert_ordered()๋ PintOS์์ ๊ธฐ๋ณธ ์ ๊ณต๋๋ ์ ๋ ฌ ์ฝ์
ํจ์ โ ์ง์ ์ฌ์ฉlist_entry()๋ฅผ ํตํด list_elem โ struct thread ํฌ์ธํฐ ๋ณํmake check TEST=alarm-single ๋ช
๋ น์ alarm ๊ณ์ด ํ
์คํธ๋ค์ ์ฐ์ ์คํํ๊ธฐ ๋๋ฌธ์,.output ํ์ผ(alarm-single.output, alarm-multiple.output ๋ฑ)์ ์๋์ผ๋ก ์์ฑํ๊ณ ,tests/threads/ ๋๋ ํ ๋ฆฌ์ ๋ณต์ฌํ์ฌ ์๋ ์ฑ์ ์ด ๊ฐ๋ฅํ๊ฒ ๊ตฌ์ฑ| ํค์๋ | ์๋ฏธ |
|---|---|
| BLOCK / READY ์ํ | ์ค๋ ๋๊ฐ CPU๋ฅผ ์ ์ ๊ฐ๋ฅํ์ง ์ฌ๋ถ |
| sleep_list | ์ ๋ ์ค๋ ๋๋ค์ ๋ณด๊ดํ๋ ์ ์ญ ๋ฆฌ์คํธ |
| wakeup_tick | ์ค๋ ๋๊ฐ ๊นจ์ด๋์ผ ํ ์์ (tick) |
| list_insert_ordered | ๋ฆฌ์คํธ์ ์ ๋ ฌ ์ฝ์ ํ๋ ํจ์ |
| list_entry | list_elem* โ ๊ตฌ์กฐ์ฒด ํฌ์ธํฐ๋ก ๋ณํํ๋ ๋งคํฌ๋ก |
| interrupt_disable/enable | ๋ฆฌ์คํธ ์กฐ์ ์ ์ธํฐ๋ฝํธ ์ถฉ๋ ๋ฐฉ์ง์ฉ |
๊ธฐ์กด
timer_sleep()์ busy wait ๋ฐฉ์์ด๋ผ ๋นํจ์จ์ ์ด์๊ณ ,
thread_sleep()๊ณผthread_awake()๋ฅผ ๊ตฌํํด BLOCK ์ํ ๊ธฐ๋ฐ ์ฌ๋ฆฝ/์จ์ดํฌ์ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด์ผํจ
๊ทธ๊ฑธtimer_interrupt()์ ์ฐ๊ฒฐํด์ ๋งค tick๋ง๋ค sleep_list๋ฅผ ์ํํ๋ฉฐ ๊นฐ ์ค๋ ๋๋ฅผ READY๋ก ๋ง๋ฌ
์ต๊ณ