[Pintos] 1. Alarm System

0

pintos-project

목록 보기
2/8

기존 Pintos의 알람 기능은 Busy Waiting으로 구현되어있는데, 프로세스(pintos에서 스레드와 프로세스는 동일한 개념이다)가 잠을 잘때, 일정한 시간마다 일어나서 아침이 됐는지 확인하는 방식이다. 따로 block 시키지 않고 yield하여 ready list의 맨 뒤로 보내는 것이다.
이 방식은 cpu가 busy하게 매 tick마다 확인하기 때문에, 하려고 하는 일을 못하여 많은 시스템 자원을 낭비하는 비효율적인 방법이므로
Alarm System Call 과제를 통해 시스템 자원 낭비를 최소화 하고자 한다.

기존 Busy Waiting 살펴보기

/* device/timer.c */
void timer_sleep (int64_t ticks) {
	int64_t start = timer_ticks (); // start : 시작시 시간(tick)
	ASSERT (intr_get_level () == INTR_ON); //인터럽트가 들어왔을때만 실행
	while (timer_elapsed (start) < ticks) //start로부터 tick만큼 시간이 지나기 전까지
		thread_yield (); //cpu를 양보한다.
}

tick = 컴퓨터가 켜지고 10ms에 1씩 증가하는 값
timer_elapsed(start) = timer_sleep이 호출된 시점에서 몇 tick이 지났는지 반환함

이 함수의 반환값이 timer_sleep의 인자인 ticks값보다 작으면 thread_yield()를 호출하여 ready list에 있는 다른 스레드를 위해 CPU를 반환하고 ready list 가장 뒤로 이동.
이 과정은 ticks동안 반복되고 이러한 방식으로 핀토스는 timer_sleep을 구현
자야 할 프로세스들을 READY상태로 두어 while문 반복하는것임

아이디어

잠을 자야할 프로세스들을 Block 상태로 만들어 list에 넣어둔 뒤, 깰 시간이 되면 다시 Ready상태로 바꿔주는 것.

Sleep-Awake

간단하게 설명하자면, 자는 thread를 한 list에 모아놓고, 인터럽트(인터럽트가 발생할때마다 1 tick이 올라간다) 때마다 깨어나야할 thread를 찾아서 깨워준다.

1. 자는 thread를 관리할 sleep_list를 만들고 일어날 시간을 thread 구조체 안에 기록한다.

/* thread/thread.h */
struct thread{
    ...
    int64_t wakeup; // 깨어나야 하는 ticks 값
    ...
}
/* thread/thread.c */
static struct list sleep_list;

void thread_init(void){
	...
    list_init(&ready_list);
    list_init(&all_list);
    list_init(&sleep_list);
    ...
}

2. thread를 ticks까지 재우는 함수를 따로 만들어준다.

/* thread를 ticks시각까지 깨우는 함수 */ 
void thread_sleep(int64_t ticks){
	// 인터럽트를 금지하고 이전 인터럽트 레벨을 저장함.
	enum intr_level old_level = intr_disable();
    
    //cur은 idle이 아니어야 하는데, idle은 sleep 하지말아야 한다 (sleep되면 cpu가 꺼져버림)
    struct thread *cur = thread_current();
	ASSERT(cur != idle_thread); 
    
    //awake함수가 실행되어야할 tick값을 update
	update_next_tick_to_wake(cur->wakeup = ticks); 
	list_push_back(&sleep_list, &cur->elem);
    
	//이 thread를 block하고 다시 scheedule 될때 까지 blocked상태로 wait
	thread_block(); //interrupt를 꺼줘야만 작동함
    
	// 인터럽트를 다시 받아들이도록 수정
	intr_set_level(old_level);
}

4. sleep list를 탐색하여 일어날 thread를 찾는 함수를 만든다.

/* thread/thread.c */
/* 푹 자고 있는 thread 중에 깨어날 시각이 ticks 시각이 지난 애들을 모조리 깨우는 함수 */
void thread_awake(int64_t wakeup_tick){
	struct list_elem *e = list_begin(&sleep_list);
	enum intr_level old_level = intr_disable();
	next_tick_to_awake = INT64_MAX;
	while (e!=list_end(&sleep_list)){
		struct thread *t = list_entry(e, struct thread, elem);
		if(wakeup_tick >= t->wakeup){ //thread가 일어날 시간이 되었는지 확인
			e = list_remove(&t->elem); //sleep list에서 제거
			thread_unblock(t); //스레드 unblock
		}else{
			e = list_next(e);
		}
	}
	intr_set_level(old_level);
}

/* devices/timer.c */
static void
timer_interrupt (struct intr_frame *args UNUSED)
{
  ticks++;
  thread_tick ();
  thread_awake (ticks);	// ticks 가 증가할때마다 awake 작업 수행
}

0개의 댓글