Busy wait 상태의 next tick 을 기다리는 쓰레드를 단순히 sleep 상태로 변경하여 Kernel ticks 와 idle ticks 변화를 확인합니다.
현재 위와 같이 yield가 지속적으로 일어나 CPU를 낭비하고 있다.
따라서, 위와 같이 ticks 만큼 sleep 상태에 놓음으로써 간단하게 해결할 수 있습니다.
따라서, sleep_list 구조체를 하나 선언한 뒤, thread_wakeup() 과 thread_sleep()을 통해 ready_list와 sleep_list를 관리해주면 됩니다!
위와 같이 550 idle ticks를 확인할 수 있다.
void
thread_sleep(int64_t howLong) {
struct thread *curr;
enum intr_level old_level;
ASSERT(!intr_context());
// 1) intr disable
old_level = intr_disable();
curr = thread_current();
ASSERT(curr != idle_thread);
curr->local_ticks = howLong;
// list_push_back(&sleep_list, &curr->elem);
list_insert_ordered(&sleep_list, &curr->elem, ticks_less ,&curr->local_ticks);
set_global_ticks();
thread_block(); // hread_block() 과 do_schedule 뭘 써야하지?
// 2) intr able
intr_set_level(old_level);
}
void
thread_wakeup(int64_t ticks) { // OS ticks from timer!
struct list_elem *e = list_begin (&sleep_list);
struct thread *cur;
struct list_elem *next;
ASSERT (intr_context ());
// ticks와 동일한 시간에 깨어나야 하는 쓰레드가 여러개 있을 수 있으니까 반복문으로 체크합니다.
while (!list_empty(&sleep_list)) // incr 'e' inside of the loop by doing e = list_next;
{
e = list_begin(&sleep_list);
cur = list_entry (e, struct thread, elem); // iterate the sleep list !
// Time to wake up
if (cur->local_ticks > ticks) break;
// e == &cur->elem
list_remove(e); // e 갱신, //fix
// next = list_pop_front(&sleep_list);
thread_unblock(cur); // 이미 만들어진 함수에서 다 처리
// list_push_back(&ready_list, next);
}
set_global_ticks();
}
void set_global_ticks() {
struct thread *tmp = list_min(&sleep_list,ticks_less,NULL);
global_ticks = MIN(tmp->local_ticks,global_ticks);
}
int64_t get_global_ticks(void) {
return global_ticks;
}
static void
timer_interrupt (struct intr_frame *args UNUSED) {
ticks++;
thread_tick ();
int64_t next = get_global_ticks();
if (next <= ticks) {
thread_wakeup(ticks);
}
/*
code to add :
check sleep list and the global tick.
find any threads to wake up,
move them to the ready list if needed
update the global tick.
*/
}
-> 천천히 할 예정입니다...