몇 초만에 프로세스를 깨우는 시스템 호출
스레드를 sleep하거나, wakeup하는 함수들로 알람 시계를 만든다.
상태 주기
원래 상태
바꿔야 하는 상태
sleep 큐 데이터 구조를 초기화하는 코드 추가.
구현 전 힌트(x)
코드
threads/thread.h
int64_t wakeup_ticks; // 일어날 시각 추가(각 스레드 마다 존재)
void thread_sleep (int64_t ticks);
void thread_wakeup (int64_t global_ticks);
bool cmp_thread_ticks(const struct list_elem *a, const struct list_elem *b, void *aux);
threads/thread.c
static struct list ready_list;
static struct list sleep_list;
thread_init(void)
{
list_init(&sleep_list);
}
sleep 큐에 스레드를 삽입하는 함수 호출
구현 전 힌트(x)
코드
devices/timer.c
timer_sleep(int64_t ticks)
{
int64_t start = timer-ticks(); // 현재 시각
ASSERT(intr_get_level() == INTR_ON); // 인터럽트 레벨 검사
thread_sleep(start + ticks); // 현재 시각 + 잠들시간
}
매 틱 마다 일부 스레드가 절전 대기열에서 깨어나야하는지 확인하고 wake up 함수 호출
구현 전 힌트
코드
devices/timer.c
timer_interrupt(struct intr_frame *args UNSED)
{
ticks++;
thread_tick (); // 스레드의 우선순위를 관리, 다음 실행할 스레드를 선택하는 역할.
thread_wakeup(ticks); // 일어날 시간이 된 스레드 > ready_list로 이동시키는 함수 호출
}
스레드 상태를 차단됨으로 설정하고 절전 대기열에 삽입한 후 대기하는 함수. 스레드를 블록처리 함으로써 재우는 함수.
구현 전 힌트
코드
threads/thread.c
thread_sleep(int64_t ticks)
{
struct thread *curr;
enum intr_level old_level;
// 1. 인터럽트 비활성화
old_level = intr_disable();
// 2. 현재 스레드 가져오기
curr = thread_current();
// 3. 스레드 검사(현재 스레드가 idle이 아닐때만)
ASSERT(curr != idle_thread);
// 4. 일어날 시각 설정
curr->wakeup_ticks = ticks;
// 5. sleep_list에 스레드 추가
list_insert_ordered(&sleep_list, &curr->elem, cmp_thread_ticks, NULL); // sleep_list에 추가
// 6. 스레드 블록(재우기) - 블록 처리
thread_block(); //
// 7. 인터럽트 복원
intr_set_level(old_level);
}
절전 대기열에서 깨어날 스레드를 찾아 절전 모드를 해제하는 함수. 잠든 상태인 스레드를 깨우는 함수
구현 전 힌트(x)
코드
threads/thread.c
thread_wakeup(int64_t current_ticks)
{
enum intr_level old_level;
// 1. 인터럽트 비활성화
old_level = intr_disable();
struct list_elem *curr_elem = list_begin(&sleep_list);
// 2. 'sleep_list' 순회
while (curr_elem != list_end(&sleep_list))
{
struct thread *curr_thread = list_entry(curr_elem, struct thread, elem); // 현재 검사중인 elem의 스레드
// 3. 스레드 깨우기
if (current_ticks >= curr_thread->wakeup_ticks)
{
// 4. 순회 계속(sleep_list에서 제거, curr_elem에는 다음 elem이 담김)
curr_elem = list_remove(curr_elem);
// 3. 스레드 깨우기(ready_list로 이동)
thread_unblock(curr_thread);
}
else
break;
}
// 5. 인터럽트 복원
intr_set_level(old_level); // 인터럽트 상태를 원래 상태로 변경
}
출처 : 카이스트, 한양대 핀토스