Alarm clock은 프로세스나 스레드를 재우거나 깨우는 역할을 합니다. 일정 시간 동안 스레드를 일시 정지 시킨 후에 프로세스, 스레드를 다시 깨워 실행을 재개합니다.
스레드를 재우고 깨우는 데에 timer-interrupt를 사용합니다.
PintOS는 현재 busy-waiting 방식으로 alarm clock을 구현하고 있습니다.
이번 과제는 busy-waiting 방식으로 구현 된 alarm clock을 sleep awake 방식으로 바꾸는 것이 목표입니다.
busy waiting 방식은 cpu 에게는 그다지 효율적인 방법이 아닙니다. busy-waiting방식에서 스레드는 ready state와 running state를 반복해서 왔다갔다하기 때문입니다.


sleep/awake 방식은 스레드에 block state를 별도로 만들어서 잠든 스레드를 스케줄링하지 않고 별도의 sleep list에 보관해둡니다. cpu는 스레드를 실행할 지 여부를 결정하기 위해서 일일이 스레드를 확인하지 않아도 되어서 전력과 성능을 아낄 수 있습니다.

아래는 busy-waiting 방식으로 구현된 코드 모음입니다.
/* devices/timer.c */
void timer_sleep (int64_t ticks) {
int64_t start = timer_ticks ();
while (timer_elapsed (start) < ticks)
thread_yield ();
}
/* devices/timer.c */
int64_t timer_elapsed (int64_t then) {
return timer_ticks () - then;
}
struct thread/* thread/thread.h */
struct thread{
...
int64_t wakeup; // 깨어나야 하는 ticks 값
...
}
threads/thread.c/* thread/thread.c */
static struct list sleep_list;
void
thread_init (void)
{
...
list_init (&ready_list);
list_init (&all_list);
list_init (&sleep_list);
...
}
sleep_list: block 상태의 스레드 정보 보관합니다.thread_init()ready_list: ready 상태의 스레드 리스트all_list: 모든 상태의 스레드를 담은 리스트sleep_list: block 상태의 스레드를 담은 리스트thread_sleep()/* thread/thread.c */
void
thread_sleep (int64_t ticks)
{
struct thread *cur;
enum intr_level old_level;
old_level = intr_disable (); // 인터럽트 off
cur = thread_current ();
ASSERT (cur != idle_thread);
cur->wakeup = ticks; // 일어날 시간을 저장
list_push_back (&sleep_list, &cur->elem); // sleep_list 에 추가
thread_block (); // block 상태로 변경
intr_set_level (old_level); // 인터럽트 on
}
timer_sleep()/* devices/timer.c */
void
timer_sleep (int64_t ticks)
{
int64_t start = timer_ticks ();
thread_sleep (start + ticks);
}
thread_awake()/* thread/thread.c */
void
thread_awake (int64_t ticks)
{
struct list_elem *e = list_begin (&sleep_list);
while (e != list_end (&sleep_list)){
struct thread *t = list_entry (e, struct thread, elem);
if (t->wakeup <= ticks){ // 스레드가 일어날 시간이 되었는지 확인
e = list_remove (e); // sleep list 에서 제거
thread_unblock (t); // 스레드 unblock
}
else
e = list_next (e);
}
}
/* thread/thread.h */
...
void thread_sleep(int64_t ticks);
void thread_awake(int64_t ticks);
...
timer_interrupt() 수정/* devices/timer.c */
static void
timer_interrupt (struct intr_frame *args UNUSED)
{
ticks++;
thread_tick ();
thread_awake (ticks); // ticks 가 증가할때마다 awake 작업 수행
}
