thread_mlfqs
parse_options
이 true 일때 고급 스케줄러
thread_create
우선순위 인자 무시
thread_set_priority
역시 무시
thread_get_priority는
현재 우선순위 반환
4.4BSD 스케줄러 구현시
데이터 갱신은 일반 커널 스레드 실행 전에
우선순위 기부 없음
나이스 값
thread_get_nice
nice값 반환
thread_set_nice
nice값 재설정 후 우선순위 재계산 하고 최고 우선순위 아닐시 즉시 양보
우선순위 계산
-20 ~ 20 nice값 4틱마다 재계산
priority = PRI_MAX - (recent_cpu / 4) - (nice * 2)
recent_cpu
최근에 받은 cpu시간 측정 1틱마다 1증가하고
1초마다 다음 공식 계산
recent_cpu = (2 * load_avg) / (2 * load_avg + 1) * recent_cpu + nice
load_avg
는 지난 1분간 실행 준비 스레드 평균개수
0에서 시작해 초당 1회 다음 공식으로 갱신
load_avg = (59/60) * load_avg + (1/60) * ready_threads
ready_threads
는 실행 또는 준비 상태인 스레드 수 (idle 제외)
기존 코드와 고급 스케줄러 고를수 있게 설계
nice값을 비롯한 필요 숫자들을 위한 공식 함수 설계
일단 get_priority
랑 set_priority
를 손 볼 생각이다
if (thread_mlfqs)
로 관리하려 한다
get
은 솔직히 건드릴 게 없어 보여 스킵하겠다
생각해보니 그 이전에 준비 큐 만들어야 겠다
64개 준비 큐 있어야 한다는데
이걸 어캐 만드냐…
잘 모르겠으니 지금은 스킵하겠다
priority 관련 먼저 구현하면 되지 않을까 싶다
초단위 계산부터 넣어야한다
ticks % 100 이 0이어야 한다
pintos 기본값으로 초당 100틱 발생시키니 말이다
TIMER_FREQ 쓰란다 초당 몇틱인지 나타내는 매크로가 존재하니 하드코딩 괜히 하지 말고 말이다
thread_tick이 매 틱마다 호출되니 여기서 하면 된다
void
thread_tick (void) {
struct thread *t = thread_current ();
/* Update statistics. */
if (t == idle_thread)
idle_ticks++;
#ifdef USERPROG
else if (t->pml4 != NULL)
user_ticks++;
#endif
else
kernel_ticks++;
/* Enforce preemption. */
if (++thread_ticks >= TIME_SLICE)
intr_yield_on_return ();
}
기본은 이렇게 생겼다
어떻게 코딩했고 뭘 넣었는지는 비밀로 하겠다
알아서 하도록
공식 구현하려면 일단
priority 구하는거 만들어야 하고
이거 만들려면 nice랑 recent_cpu 필요하다
recent_cpu 만드려면 load_avg가 필요하다
load_avg 만드려면 ready_threads가 필요하다
ready_threads 얻으려면…
1초마다 스레드 돌아 확인하면 된다!
emoji2
그치만 그전에 recent_cpu 만져야 한다
공식 말고 기본적으로 매 틱마다 1 늘려줘야함 ㅇㅇ
idele_thread
일 떄 뺴고는 현재 스레드 1씩 늘려주면 되니 간단하다
/* 틱 계산 */
if (t != idle_thread) {
t->recent_cpu += 1;
}
이게 끝이다
이제 다음으로 가자
timer_ticks()
함수로 현재 틱 불러 올 수 있다
그리고 1초는 100틱이다
그렇다,
if ((timer_ticks() % 100) == 0)
으로 1초마다 함수 돌릴 수 있다
그리고 100대신 4넣으면 4틱마다 하는 것도 해결 가능하다
이제 여기 안에 load_avg
를 구하는 공식을 넣어주자
load_avg = (59/60) * load_avg + (1/60) * ready_threads
참고로 thread.h
에 전역변수 int load_avg;
로 선언하고
thread_init
에 0으로 초기화하것도 넣어주고 오는 길이다
/* load avg */
int cur;
if (t != idle_thread) cur = 1; else cur = 0;
load_avg = FP_ADD(FP_MUL(FP_59_60, load_avg), FP_MUL(FP_1_60, (len(ready_list) + cur)));
t는 현재 스레드다 그리고 load_avg에 1더해주는 건 idle_thread가 아닐때만이라 저렇게 한거다
ready_list
에는 현재 스레드 없으니까 실행중인 현제 스레드 포함해서 + 1
idle_thread
는 늘 제외니까 idle_thread
돌아갈땐 + 0
그리고 나서는 recent_cpu
에 대한 공식 재계산 해야한다
이번에는 현재 스레드 말고 idle_thread
제외 전부 돌아야 하는데
이는 불가능하다
그러니까 구조체에 새로 리스트 하나 추가해줘야한다
이름 적당히 지어 원소 하나 추가해주고
관련해서 선언해주면 끝이다
…
할게 너무 많아 잠시 TIL 스탑하다가 왔다
이번에는 전역함수 안만들고 조금씩 추가하면서 했더니…
좀 코드가 많이 더럽고 길어져 어떻게 정리해야 될지 모르겠다;;
전부 통과하고 난 뒤 따로
코드 정리하거나 전역 함수등으로 간결하게 정리한 뒤에
새로 정리해보겠다
일단 흐름만 정리한 글 올리고 코드와 함께 정리 다시해보겠다
흐름은 간단한데 코드 개판으로 짜서 힘듬;; emoji