devices/timer.c
안에 있는timer_sleep()
을 수정하라.
프로그램에서 시간을 세는 단위. device/timer.h
에서 TIMER_FREQ
의 값이 100으로 저장되어 있는데, 이 의미는 1초당 tick이 100번 돈다는 의미이다. 즉 1 tick은 100분의 1초(10ms).
컴퓨터에 내장되어 있는 하드웨어이다. 일정 시간 단위(대부분은 tick)를 세고, 그 단위마다 CPU에 timer interrupt를 날린다.
thread.c/thread_tick()
매 tick 마다 timer interrupt handler에 의해 불러와진다.
현재 TIME_SLICE
는 4 tick으로 설정되어 있다. 해당 TIME_SLICE
가 지나면 그 다음 스레드에 CPU 주도권을 넘긴다.
/* Called by the timer interrupt handler at each timer tick.
Thus, this function runs in an external interrupt context. */
void thread_tick (void) {
struct thread *t = thread_current ();
/* Update statistics. */
if (t == idle_thread)
idle_ticks++;
#ifdef USERPROG
else if (t->pml4 != NULL)
user_ticks++;
#endif
else
kernel_ticks++;
/* Enforce preemption. */
if (++thread_ticks >= TIME_SLICE) // thread_ticks는 맨 처음 schedule()에서 0으로 만들어줌.
intr_yield_on_return ();
}
인자로 넣어준
ticks
tick 동안 스레드를 잠자게 한다.
잠을 자야 하는 이유는 여러 가지가 있을 수 있다. Round Robin 방식에서 정해져 있는 time slice가 지나면 다른 스레드로 context switching해야 하는 경우가 있을 것이고(이런 경우 바로 block되는지, 아니면 ready list로 들어가는지 잘 모르겠음), 아니면 다른 I/O의 실행을 기다리느라 block이 된 경우도 있을 것이다.
sleeper 스레드(test/alarm-wait.c)
/* Sleeper thread. */
static void
sleeper (void *t_)
{
struct sleep_thread *t = t_;
struct sleep_test *test = t->test;
int i;
for (i = 1; i <= test->iterations; i++)
{
int64_t sleep_until = test->start + i * t->duration;
timer_sleep (sleep_until - timer_ticks ());
// 인자로 넣어 준 tick 동안 여기서 움직이지 않는다.
lock_acquire (&test->output_lock);
*test->output_pos++ = t->id;
lock_release (&test->output_lock);
}
}
매번 ready list를 돌면서 자기가 CPU를 사용해야 하는 타이밍이 되었을 때마다
time_elapsed
로 시간을 체크하고 다른 스레드로yield
한다.
sleep 시켜줄 스레드 A를 대상으로 인자로 넣어준 ticks만큼 시간이 지났는지 체크한다. A가 CPU 주도권을 잡아 코드를 매 줄 실행시킬 때마다 이를 확인해 주어야 한다. 따라서 효율성 면에서 굉장히 떨어진다.
timer_sleep() 함수