2023. 4. 25. 21:28ใComputer Science
Alarm Clock
๐ก ์ค๋ ๋๋ฅผ ์ ์ ์ฌ์ ๋ค๊ฐ ์ผ์ ์๊ฐ์ด ์ง๋๋ฉด ๊นจ์ฐ๋ ๊ธฐ๋ฅ์ธ
Alarm Clock์ Busy-waiting ๋ฐฉ์์์ Sleep-Awake ๋ฐฉ์์ผ๋ก ๋ณ๊ฒฝํ์!
1) Busy-waiting๊ณผ Sleep-Awake์ ์ฐจ์ด
Busy waiting์ ํน์ ์กฐ๊ฑด์ด ๋งค์ฐ ๋น ๋ฅด๊ฒ ์ถฉ์กฑ๋ ๊ฒ์ผ๋ก ์์๋ ๋ ์ฌ์ฉ๋๋ ๊ฒ์ด ์ ํฉํ๋ฉฐ,
Alarm clock์ ์ผ์ ์๊ฐ ์ดํ์ ์ํํด์ผ ํ๋ ์์
์ด ์์ ๋ ์ฌ์ฉ๋๋ค.
Busy waiting
- ํ๋ก๊ทธ๋จ์ด ๋ค๋ฅธ ์์ ์ ์ํํ๋ฉฐ ๊ธฐ๋ค๋ฆฌ๋ ๋์ , ํน์ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋ ๋๊น์ง ๋ฐ๋ณต์ ์ผ๋ก ์ฒดํฌ๋ฅผ ํ๋ฉด์ ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์ ๋งํ๋ค.
- ์ด๋ฌํ ๋ฐฉ์์ CPU ์์์ ๋ญ๋นํ๊ณ , ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์คํ๋๋ ๊ธฐํ๋ฅผ ์ค์ฌ ์ฑ๋ฅ ์ ํ๋ฅผ ์ผ๊ธฐํ ์ ์๋ค.
Alarm Clock
- ํ๋ก๊ทธ๋จ์ด ์ผ์ ์๊ฐ์ด ์ง๋ ํ์ ๋ค์ ์์ ์ ์ํํ๋๋ก ์์ฝํ๋ ๊ฒ์ด๋ค.
- ์ด ๊ฒฝ์ฐ, ํ๋ก๊ทธ๋จ์ ๋๊ธฐ ์ํ์ ๋ค์ด๊ฐ ๋์ CPU ์ฌ์ดํด์ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์, Busy waiting ๋ฐฉ์์ ๋นํ์ฌ CPU ์์์ ์ ์ฝํ ์ ์๋ค.
2) Busy-waiting ๋ฐฉ์์ผ๋ก ๊ตฌํ๋ ๊ธฐ์กด์ ์ฝ๋
void timer_sleep (int64_t ticks)
{
int64_t start = timer_ticks ();
ASSERT (intr_get_level () == INTR_ON);
while (timer_elapsed (start) < ticks)
thread_yield ();
}
- timer_sleep() ํจ์๋ ์ค๋ ๋๋ฅผ ticks๋งํผ ์ผ์ ์ค์งํ๋ ํจ์์ด๋ค.
- ํ์ฌ ๊ตฌํ๋ ๋ฐฉ์์ผ๋ก๋, ํ์ฌ ํ์ด๋จธ ์๊ฐ๊ณผ ticks๋ฅผ ๋น๊ตํด์ ์์ง ticks์ ๋๋ฌํ์ง ์์์ผ๋ฉด thread_yield() ํจ์๋ฅผ ํธ์ถํ์ฌ ๋ค๋ฅธ ์ค๋ ๋์๊ฒ CPU๋ฅผ ์๋ณดํ๋ค.
- ํ์ง๋ง CPU๋ฅผ ์๋ณด ๋ฐ์ ์ค๋ ๋๋ ์์ง ticks์ ๋๋ฌํ์ง ์์ ๊ฒฝ์ฐ์๋, CPU๋ฅผ ์๋ณด ๋ฐ์๋ง์ ๋ฐ๋ก ๋ค์ ๋ค๋ฅธ ์ค๋ ๋์๊ฒ ์๋ณด๋ฅผ ํด์ผ ํ๋ค. (์ฆ, ๋ถํ์ํ Context switching์ด ๋ง์ด ์ผ์ด๋ ์ ์๋ค.)
- ๋ฐ๋ผ์ ์์ง ticks์ ๋๋ฌํ์ง ์์ ์ค๋ ๋๊ฐ ๊นจ์์ง๋ ๊ฒ์ด ํฐ ๋นํจ์จ์ ๋ฐ์์ํค๊ณ , ์ด๊ฒ์ ํด๊ฒฐํ๋ ๊ฒ์ด ์ด๋ฒ ๊ณผ์ ์ ๋ชฉ์ ์ด๋ค.
๐ค tick์ด๋?
- tick์ ์ผ์ ์๊ฐ ๊ฐ๊ฒฉ์ผ๋ก ๋ฐ์ํ๋ ์์คํ ์ ๊ธฐ๋ณธ์ ์ธ ์๊ฐ ๋จ์์ด๋ค.
- ์์คํ ํ์ด๋จธ๋ ์ด๋ฌํ ํฑ์ ์์ฑํ๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก ์ด์ ์ฒด์ ๋ ์ด๋ฌํ ํฑ์ ์ฌ์ฉํ์ฌ ์์คํ ์ํ๋ฅผ ์ ์งํ๊ณ ๋ค์ํ ์์ ์ ์ค์ผ์ค๋งํ๋ค.
- ์๋ฅผ ๋ค์ด, ์์คํ ํ์ด๋จธ๊ฐ 100๋ฒ์ ํฑ์ ์ด๋น ์์ฑํ๋ค๋ฉด, ์ด์ ์ฒด์ ๋ 1์ด๋ฅผ 100๊ฐ์ ํฑ์ผ๋ก ๋๋์ด ์์คํ ์ํ๋ฅผ ์ ๋ฐ์ดํธํ๊ณ ์์ ์ ์ค์ผ์ค๋งํ๋ค.
- ์ด๋ฌํ ๋ฐฉ์์ผ๋ก ์์คํ ์ด ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ๋์ํ ์ ์๋๋ก ํ๋ค.
tick์ ์ฌ์ฉํ๋ ์ด์
1) ํฑ์ ๊ณ ์ ๋ ๊ฐ๊ฒฉ์ผ๋ก ๋ฐ์ํ๊ธฐ ๋๋ฌธ์, ์ด์ ์ฒด์ ๊ฐ ํน์ ์์ ์ ์คํํ๊ธฐ ์ํด ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ์ ์ ํํ ๊ณ์ฐํ ์ ์๋ค.
- ์๋ฅผ ๋ค์ด, ์ด์ ์ฒด์ ๊ฐ ํน์ ์์
์ 5์ด ํ์ ์คํํ๋๋ก ์ค์ผ์ค๋งํ๋ค๋ฉด, ์ด์ ์ฒด์ ๋ ํฑ์ด ๋ฐ์ํ๋ ์๊ฐ์ ์ด์ฉํ์ฌ ์ ํํ ์๊ฐ์ ์ธก์ ํ๋ค. ์ด๋ฅผ ํตํด ์ด์ ์ฒด์ ๋ ํน์ ์์
์ด ์ ํํ 5์ด ํ์ ์คํ๋ ๊ฒ์์ ๋ณด์ฅํ ์ ์๋ค.
2) ์๊ฐ ๋จ์๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, ์์คํ ์ด ๋ค๋ฅธ ์์ ์ ์ํํ๋ฉด์ ์๊ฐ์ด ํ๋ฅผ ๋๋ง๋ค ์๊ฐ์ ์ ๋ฐ์ดํธํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ถํ๊ฐ ์ปค์ง ์ ์๋ค.
- ๋ฐ๋ผ์, ํฑ ๋จ์๋ก ์๊ฐ์ ์ถ์ ํจ์ผ๋ก์จ ์์คํ
์ ๋ถํ๋ฅผ ์ค์ด๊ณ ์ผ๊ด์ฑ์ ์ ์งํ ์ ์๋ค.
- ํฑ์ ์
๋ฐ์ดํธํ๋ ๊ฒ๋ ์ผ์ ํ ๋ถํ๋ฅผ ๋ฐ์์ํค์ง๋ง, ์ด ๋ถํ๋ ๋๋ถ๋ถ ๋ฌด์ํ ์์ค์ด๋ค. ํฑ์ ํ๋์จ์ด์์ ๋งค์ฐ ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌ๋ ์ ์๋ ๋จ์์ด๊ธฐ ๋๋ฌธ์ด๋ค.
3) ํฑ์ ์ฌ์ฉํ์ฌ CPU ์ฌ์ฉ๋ฅ ์ ์กฐ์ ํ ์ ์๋ค.
- ํฑ์ ๊ฐ๊ฒฉ์ ๋ ์๊ฒ ์กฐ์ ํ๋ฉด, ์์คํ
์ ๋ ์์ฃผ ์ธํฐ๋ฝํธ๋ฅผ ์ฒ๋ฆฌํ์ฌ ์์
์ ์ค์ผ์ค๋งํ ์ ์๊ฒ ๋๋ค.
- ์ด๋ ์ฐ์ ์์๊ฐ ๋์ ์์
์ด ๋ ๋น ๋ฅด๊ฒ ์คํ๋ ์ ์๋๋ก ํ์ฌ ์์คํ
์ ๋ฐ์์ฑ์ ํฅ์์ํค๋ ๋ฐ ๋์์ด ๋๋ค.
3) Sleep-Awake ๋ฐฉ์
๋ณ๊ฒฝ ๋ฐฉ์
ํ์ฌ
์ค๋ ๋๊ฐ ์ ๋ค๋ฉด ๋ชจ๋ ์ค์ผ์ค๋ง ๋๊ธฐ์ด์ธ ready_list์ ์ถ๊ฐํ๊ณ ์์ด์,
์์ง ๊นฐ ์๊ฐ์ด ๋์ง ์์ (ticks์ ๋๋ฌํ์ง ์์) ์ค๋ ๋๊ฐ ๊นจ์์ง๋ ์ผ์ด ๋ฐ์ํ๋ค!
๋ณ๊ฒฝ์
์๋ก์ด ๋ฐฉ์์์๋ ์ ๋ ์ค๋ ๋๊ฐ ๊นฐ ์๊ฐ(ticks์ ๋๋ฌํ ๋)๊น์ง๋ ready_list์ ์ถ๊ฐํ์ง ์๊ณ ,
๊นฐ ์๊ฐ(ticks)์ ๋๋ฌํ ๊ฒฝ์ฐ์๋ง ready_list์ ์ถ๊ฐํ๋ ๋ฐฉ์์ผ๋ก
์์ง ticks์ ๋๋ฌํ์ง ์์ ์ค๋ ๋๊ฐ ๊นจ์์ง๋ ์ผ์ ์๊ฒ ๋ง๋ค ๊ฒ์ด๋ค!
๊ตฌํ ๋ฐฉ๋ฒ
(1) sleep list ์ ์ธ & ์ด๊ธฐํ
- ticks์ ๋๋ฌํ์ง ์์ ์ค๋ ๋๋ฅผ ๋ด์ ์ฐ๊ฒฐ ๋ฆฌ์คํธ sleep_list๋ฅผ ์ ์ธํ๊ณ thread_init์์ ์ด๊ธฐํํ๋ค.
/* thread.c */
// 1. sleep_list ์ ์ธ
static struct list sleep_list;
...
// 2. sleep_list ์ด๊ธฐํ
void thread_init (void) {
...
list_init (&sleep_list);
...
}
(2) thread ๊ตฌ์กฐ์ฒด์ ํ๋ ์ถ๊ฐ
- ์ค๋ ๋ ๊ตฌ์กฐ์ฒด์ ์ผ์ด๋ ์๊ฐ์ธ ticks๋ฅผ ์ ์ฅํ wakeup_ticks ํ๋๋ฅผ ์ถ๊ฐํ๋ค.
/* thread.h */
struct thread
{
/* Owned by thread.c. */
tid_t tid; /* Thread identifier. */
enum thread_status status; /* Thread state. */
char name[16]; /* Name (for debugging purposes). */
int priority; /* Priority. */
int64_t wakeup_ticks; // ์ผ์ด๋ ์๊ฐ ์ถ๊ฐ
...
};
(3) ์ค๋ ๋ ์ฌ์ฐ๊ธฐ ๋ก์ง ๋ณ๊ฒฝ
timer_sleep
- ๊ธฐ์กด ์ฝ๋์ ์๋ thread_yield() ํจ์๋ฅผ ํธ์ถํ๋ฉด ์ ๋ ์ค๋ ๋๊ฐ ready_list์ ์ฝ์ ๋๋ค.
- ์ ๋ ์ค๋ ๋๋ ready_list๊ฐ ์๋ sleep_list์ ์ฝ์
ํ๋ thread_sleep() ํจ์๋ฅผ ํธ์ถํ๋ค.
- thread_sleep() ํจ์๋ ์๋์์ ์๋ก ์ ์ธํ๋ค.
/* timer.c */
void timer_sleep(int64_t ticks)
{
int64_t start = timer_ticks(); // ํ์ฌ ์๊ฐ
ASSERT(intr_get_level() == INTR_ON);
thread_sleep(start + ticks); // ํ์ฌ ์๊ฐ (start) + ์ ๋ค ์๊ฐ (ticks)
}
thread_sleep
- ์ ๋ ์ค๋ ๋๋ฅผ sleep_list์ ์ฝ์ ํ๋ ํจ์๋ฅผ ์๋ก ์ ์ธํ๋ค.
- ์ค๋ ๋ ๊ตฌ์กฐ์ฒด์ ์ผ์ด๋ ์๊ฐ์ธ ticks๋ฅผ ์ ์ฅํ๋ค.
- sleep_list์ ticks๊ฐ ์์ ์ค๋ ๋๊ฐ ์๋ถ๋ถ์ ์์นํ๋๋ก ์ ๋ ฌํ์ฌ ์ฝ์
ํ๋ค.
- ์ ๋ ฌ์ ํ์ฉํ cmp_thread_ticks() ํจ์๋ ์๋์์ ์๋ก ์ ์ธํ๋ค.
- ํ์ฌ ์ค๋ ๋๋ ์ ๋ค์ด์ผ ํ๋ thread_block() ํจ์๋ฅผ ํธ์ถํ๋ค.
/* thread.h */
void thread_sleep (int64_t ticks);
/* thread.c */
void thread_sleep(int64_t ticks)
{
struct thread *curr;
enum intr_level old_level;
old_level = intr_disable(); // ์ธํฐ๋ฝํธ ๋นํ์ฑ
curr = thread_current(); // ํ์ฌ ์ค๋ ๋
ASSERT(curr != idle_thread); // ํ์ฌ ์ค๋ ๋๊ฐ idle์ด ์๋ ๋๋ง
curr->wakeup_ticks = ticks; // ์ผ์ด๋ ์๊ฐ ์ ์ฅ
list_insert_ordered(&sleep_list, &curr->elem, cmp_thread_ticks, NULL); // sleep_list์ ์ถ๊ฐ
thread_block(); // ํ์ฌ ์ค๋ ๋ ์ฌ์ฐ๊ธฐ
intr_set_level(old_level); // ์ธํฐ๋ฝํธ ์ํ๋ฅผ ์๋ ์ํ๋ก ๋ณ๊ฒฝ
}
cmp_thread_ticks
- sleep_list์ ์ผ์ด๋ ์๊ฐ์ด ์ด๋ฅธ ์ค๋ ๋๊ฐ ์๋ถ๋ถ์ ์์นํ๋๋ก ์ ๋ ฌํ ๋ ์ฌ์ฉํ ์ ๋ ฌ ํจ์๋ฅผ ์๋ก ์ ์ธํ๋ค.
/* thread.h */
bool cmp_thread_ticks(const struct list_elem *a, const struct list_elem *b, void *aux);
/* thread.c */
// ๋ ์ค๋ ๋์ wakeup_ticks๋ฅผ ๋น๊ตํด์ ์์ผ๋ฉด true๋ฅผ ๋ฐํํ๋ ํจ์
bool cmp_thread_ticks(const struct list_elem *a, const struct list_elem *b, void *aux UNUSED)
{
struct thread *st_a = list_entry(a, struct thread, elem);
struct thread *st_b = list_entry(b, struct thread, elem);
return st_a->wakeup_ticks < st_b->wakeup_ticks;
}
(4) ์ค๋ ๋ ๊นจ์ฐ๊ธฐ ๋ก์ง ์ถ๊ฐ
timer_interrupt
- ๋งค tick๋ง๋ค ๋ฐ์ํ๋ ํ์ด๋จธ ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ๋ฅผ ํ์ฉํด์ ๋งค tick๋ง๋ค ๊นจ์ธ ์ค๋ ๋๊ฐ ์๋์ง ํ์ธ๋ค.
- ์ผ์ด๋ ์๊ฐ์ด ๋ ์ค๋ ๋๋ฅผ ready_list๋ก ์ด๋์ํค๋ ํจ์ thread_wakeup()์ ํธ์ถํ๋ค.
/* timer.c */
static void timer_interrupt(struct intr_frame *args UNUSED)
{
ticks++;
thread_tick();
thread_wakeup(ticks);
}
thread_wakeup
- sleep_list์ ์ค๋ ๋๋ค์ด ์ผ์ด๋ ์๊ฐ์ด ๋๋ฉด ready_list๋ก ์ด๋์ํจ๋ค.
- ํ์ฌ current_ticks๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ wakeup_ticks๋ฅผ ๊ฐ์ง ์ค๋ ๋๋ ๋ชจ๋ ๊นจ์ด๋ค.
- ์ฌ๊ธฐ์ ‘์ค๋ ๋๋ฅผ ๊นจ์ด๋ค’๋ ๊ฒ์, ๊นจ์ธ ์ค๋ ๋๋ฅผ sleep_list์์ ์ ๊ฑฐํ๊ณ ready_list์ ์ฝ์ ํ๋ ๊ฒ์ ์๋ฏธํ๋ค.
- 1) sleep_list์์ ๊นจ์ธ ์ค๋ ๋๋ฅผ ์ ๊ฑฐํ๋ค. (list_remove)
- 2) ๊นจ์ธ ์ค๋ ๋๋ฅผ ready_list์ ์ฝ์ ํ๊ณ , ์ํ๋ฅผ THREAD_READY๋ก ๋ณ๊ฒฝํ๋ค. (thread_block)
/* thread.h */
void thread_wakeup (int64_t global_ticks);
/* thread.c */
void thread_wakeup(int64_t current_ticks)
{
enum intr_level old_level;
old_level = intr_disable(); // ์ธํฐ๋ฝํธ ๋นํ์ฑ
struct list_elem *curr_elem = list_begin(&sleep_list);
while (curr_elem != list_end(&sleep_list))
{
struct thread *curr_thread = list_entry(curr_elem, struct thread, elem); // ํ์ฌ ๊ฒ์ฌ์ค์ธ elem์ ์ค๋ ๋
if (current_ticks >= curr_thread->wakeup_ticks) // ๊นฐ ์๊ฐ์ด ๋์ผ๋ฉด
{
curr_elem = list_remove(curr_elem); // sleep_list์์ ์ ๊ฑฐ, curr_elem์๋ ๋ค์ elem์ด ๋ด๊น
thread_unblock(curr_thread); // ready_list๋ก ์ด๋
}
else
break;
}
intr_set_level(old_level); // ์ธํฐ๋ฝํธ ์ํ๋ฅผ ์๋ ์ํ๋ก ๋ณ๊ฒฝ
}
Sleep-Awake ๋ฐฉ์์ Alarm Clock ๊ตฌํ ๋ ~ ๐
Test
/* Test: /threads/build์์ ์
๋ ฅ */
pintos -- -q run alarm-multiple
๐๐ป ๊ตฌํ ์
๐๐ป ๊ตฌํ ํ
0์ด์๋ idle tick์ด 550์ผ๋ก ์ฆ๊ฐํ๋ค!
'Computer Science' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Pintos-KAIST] Project 1 :: Priority Scheduling (0) | 2023.04.25 |
---|---|
Why Is Code Review Necessary? (0) | 2023.04.04 |
[CS:APP] 1-7) ์ด์์ฒด์ ์ ์ญํ (0) | 2023.03.11 |