1. thread_sleep()
// pintos project - alarm clock
void
thread_sleep (int64_t ticks) {
struct thread *this;
this = thread_current();
if (this == idle_thread) //idle_thread는 sleep 되어서는 안되므로
{
ASSERT(0);
}
else
{
enum intr_level old_level;
old_level = intr_disable(); //interrupt off
update_next_tick_to_awake(this->wakeup_tick = ticks); // 일어날 시간(ticks) 저장
list_push_back(&sleep_list, &this->elem); //push to sleep_list
thread_block(); // block 상태로 만들어주기
intr_set_level(old_level); //interrupt on
}
}
2. timer_sleep()
// running 상태인 어떤 스레드에 대해, runnung 된지 일정 시간이 지난 경우 thread_yield를 실행
// assert : 지정한 조건식이 False면, 프로그램을 중단하고 True면, 프로그램 계속 실행
// timer_elapse(start)가 ticks보다 작으면 thread_yield()를 계속 실행
void
timer_sleep (int64_t ticks) {
int64_t start = timer_ticks ();
ASSERT (intr_get_level () == INTR_ON); //interrupt on
// 기존
// start 이후 경과된 시간이 ticks 보다 커질 때까지
// thread_yield()를 호출하여, ready list의 맨 뒤로 이동하기를 반복
// while (timer_elapsed (start) < ticks)
// thread_yield ();
// pintos project - alarm clock
thread_sleep(start + ticks); // 일어날 시간 정보를 인자로 넣어줌
}
3. thread_awake()
// pintos project - alarm clock
// wakeup_tick 값이 ticks 보다 작거나 같은 스레드를 깨움
// 현재 대기중인 스레드의 wakeup_tick 변수 중 가장 작은 값을
// next_tick_to_awake 전역 변수에 저장
void
thread_awake (int64_t wakeup_tick) {
next_tick_to_awake = INT64_MAX; // next_tick_to_awake 변수 초기화
struct list_elem *sleeping;
sleeping = list_begin(&sleep_list); // sleep_list의 head에 있는 스레드를 sleeping 변수로 설정
// for all sleeping threads
// sleep_list의 모든 entry를 순회하면서
// 현재 tick이 깨워야 할 tick 보다 크거나 같을 경우, 리스트에서 제거하고 unblock
// 작을 경우, update_next_tick_to_awake() 호출
while(sleeping != list_end(&sleep_list))
//sleeping list의 마지막 위치에 있는 스레드가 sleeping 변수가 될 때까지
{
struct thread *th = list_entry(sleeping, struct thread, elem);
if (wakeup_tick >= th->wakeup_tick) { //스레드가 일어날 시간이 되었는지 확인
sleeping = list_remove(&th -> elem); //스레드 삭제
thread_unblock(th); //스레드 unblock 으로 설정
}
else {
sleeping = list_next(sleeping);
update_next_tick_to_awake(th -> wakeup_tick);
}
}
}
4. update_next_tick_to_awake(), get_next_tick_to_awake()
// pintos project - alarm clock
// 다음으로 깨어나야 할 스레드의 tick 값을 최소값으로 갱신하도록 하는 함수
// 현재 ticks 값과 비교하여 더 작은 값을 가질 수 있도록 함
// 즉, next_tick_to_awake 변수를 업데이트
// next_tick_to_awake가 깨워야 할 스레드 중 가장 작은 tick을 가지도록 업데이트
void
update_next_tick_to_awake(int64_t ticks) {
next_tick_to_awake = (next_tick_to_awake > ticks) ? ticks :
next_tick_to_awake;
}
// pintos project - alarm clock
// 현재 next_tick_to_awake 값을 리턴
int64_t
get_next_tick_to_awake(void) {
return next_tick_to_awake;
}
5. timer_interrupt()
/* Timer interrupt handler. */
static void
timer_interrupt (struct intr_frame *args UNUSED) {
ticks++;
thread_tick ();
//pintos project - alarm clock
// 매 tick 마다 sleep_list에서 깨어날 스레드가 있는지 확인하여,
// thread_awake() 호출
if (get_next_tick_to_awake() <= ticks) {
thread_awake(ticks);
}
}