[PINTOS_PROJECT1] ALARM CLOCK

zeo·2021년 10월 4일
0

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);
	}
}

0개의 댓글