devices/timer.c 안에 있는 timer_sleep()을 수정하라.

tick

프로그램에서 시간을 세는 단위. device/timer.h에서 TIMER_FREQ의 값이 100으로 저장되어 있는데, 이 의미는 1초당 tick이 100번 돈다는 의미이다. 즉 1 tick은 100분의 1초(10ms).

timer

컴퓨터에 내장되어 있는 하드웨어이다. 일정 시간 단위(대부분은 tick)를 세고, 그 단위마다 CPU에 timer interrupt를 날린다.

thread.c/thread_tick()

매 tick 마다 timer interrupt handler에 의해 불러와진다.

현재 TIME_SLICE4 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 ();
}

timer.c/timer_sleep(ticks)

인자로 넣어준 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);
    }
}

현재 상황 : busy waiting 방식으로 구현

매번 ready list를 돌면서 자기가 CPU를 사용해야 하는 타이밍이 되었을 때마다 time_elapsed로 시간을 체크하고 다른 스레드로 yield한다.

Untitled

sleep 시켜줄 스레드 A를 대상으로 인자로 넣어준 ticks만큼 시간이 지났는지 체크한다. A가 CPU 주도권을 잡아 코드를 매 줄 실행시킬 때마다 이를 확인해 주어야 한다. 따라서 효율성 면에서 굉장히 떨어진다.

timer_sleep() 함수