미새문지

Pintos-kaist Guide - PROJECT 1: THREADS - Alarm Clock, Priority Scheduling 본문

Pintos-Kaist Guide Gitbook

Pintos-kaist Guide - PROJECT 1: THREADS - Alarm Clock, Priority Scheduling

문미새 2024. 3. 24. 22:08
728x90

Alarm Clock

devices/timer.c에 정의된 timer_sleep()을 다시 구현합니다.

작동하는 구현이 제공되지만 busy waits, 즉 현재 시간을 확인하고 충분한 시간이 경과할 때까지 thread_yield()를 호출하는 루프에서 회전합니다. busy waits를 피하려면 다시 구현하세요.

void timer_sleep (int64_t ticks);

 

호출 스레드의 실행을 최소한 x 타이머 틱 만큼 시간이 지날 때까지 일시 중지합니다. 시스템이 유휴 상태가 아닌 경우에는 정확히 x 틱이 지난 후에 스레드를 깨울 필요는 없습니다. 대신 적절한 시간 동안 대기한 후에 준비 큐에 해당 스레드를 넣어주면 됩니다.

 

timer_sleep()은 초당 한 번씩 커서를 깜박이는 등 실시간으로 동작하는 스레드에 유용합니다. timer_sleep()의 인수는 밀리초나 다른 단위가 아닌 타이머 틱 단위로 표현됩니다. devices/timer.h에 정의된 TIMER_FREQ 매크로 값이 초당 타이머 틱 수를 나타내며, 기본값은 100입니다. 이 값을 변경하는 것은 권장하지 않습니다. 변경 시 많은 테스트가 실패할 가능성이 높기 때문입니다.

 

밀리초, 마이크로초, 나노초 단위로 특정 시간동안 Sleep하기 위한 timer_msleep(), timer_usleep(), timer_nsleep() 함수도 있지만, 필요한 경우 자동으로 timer_sleep()을 호출합니다. 이들 함수를 직접 수정할 필요는 없습니다. 알람 클럭 구현은 후속 프로젝트에서는 필요하지 않지만, 프로젝트 4에서는 유용할 수 있습니다.

 

Priority Scheduling

핀토스에서 우선 예약 및 우선 기부 기능을 구현하세요

현재 실행 중인 스레드보다 높은 우선순위의 스레드가 준비 목록에 추가되면, 현재 스레드는 즉시 프로세서를 새 스레드에 양보해야 합니다. 마찬가지로 스레드가 잠금, 세마포어 또는 조건 변수를 기다릴 때, 가장 높은 우선순위의 대기 중인 스레드를 먼저 깨워야 합니다. 스레드는 언제든 자신의 우선순위를 높이거나 낮출 수 있지만, 최고 우선순위가 아닐 정도로 우선순위를 낮추면 즉시 CPU를 양보해야 합니다.

 

스레드 우선순위 범위는 PRI_MIN (0)부터 PRI_MAX (63)까지입니다. 숫자가 낮을수록 우선순위가 낮으므로, 0이 가장 낮고 63이 가장 높은 우선순위입니다. 초기 스레드 우선순위는 thread_create() 함수의 인수로 전달됩니다. 다른 우선순위를 선택할 이유가 없다면 PRI_DEFAULT (31)를 사용하세요. PRI_ 매크로는 threads/thread.h에 정의되어 있으며, 이 값을 변경해서는 안 됩니다.

 

우선순위 스케줄링의 한 가지 문제는 "우선순위 역전"입니다. 높은 우선순위 스레드 H, 중간 우선순위 스레드 M, 낮은 우선순위 스레드 L을 가정해봅시다. H가 L(예: L이 보유한 잠금)를 기다려야 하고 M이 준비 목록에 있다면, 낮은 우선순위 스레드 L은 CPU 시간을 얻지 못하므로 H는 결코 CPU를 얻을 수 없습니다. 이 문제의 부분적인 해결책은 L이 잠금을 보유하는 동안 H가 자신의 우선순위를 L에게 "기부"하고, L이 잠금을 해제(따라서 H가 잠금을 획득)한 후에 기부를 철회하는 것입니다.

 

우선순위 기부를 구현하세요. 우선순위 기부가 필요한 모든 상황을 고려해야 합니다. 여러 우선순위가 단일 스레드에 기부되는 다중 기부 상황과, H가 M이 보유한 잠금을 기다리고 M이 L이 보유한 잠금을 기다리는 등의 중첩 기부 상황도 처리해야 합니다. 이 경우 M과 L 모두 H의 우선순위로 높여져야 합니다. 필요하다면 중첩 우선순위 기부 깊이에 합리적인 제한(예: 8레벨)을 둘 수 있습니다.

 

잠금에 대해서는 우선순위 기부를 반드시 구현해야 하지만, 다른 Pintos 동기화 구조에 대해서는 구현할 필요가 없습니다. 그러나 모든 경우에 우선순위 스케줄링은 구현해야 합니다.

 

마지막으로 스레드가 자신의 우선순위를 검사하고 변경할 수 있도록 threads/thread.c에 제공된 함수 스켈레톤을 구현하세요.

void thread_set_priority (int new_priority);
현재 스레드의 우선순위를 새 우선순위로 설정합니다. 현재 스레드의 우선순위가 더 이상 높지 않으면 양보합니다.

 

int thread_get_priority (void);
현재 스레드의 우선순위를 반환합니다. 우선순위 기부가 있는 경우, 더 높은(기부된) 우선순위를 반환합니다.

 

스레드가 다른 스레드의 우선순위를 직접 변경할 수 있는 인터페이스는 제공하지 않아도 되며, 우선순위 스케줄러는 이후 프로젝트에서는 사용되지 않습니다.

728x90