Jungle

[TIL] pintos - MLFQ 스케줄링 구현하기 - 트러블 슈팅

손가든 2023. 12. 2. 21:15

MLFQS를 구현을 모두 완료했다.

 

MLFQS를 구현하면서 발생했던 Trouble Shooting에 대해서 얘기해 보자.

 


상황 1 : mlfqs-load-1 테스트에서 'kernel panic' 발생

 

 

밑에서부터 위로 시간 순으로 call stack 출력하는 상황에서

 

'pass()' 를 통해 패스하는 도중에 debug_panic이 발생했다.

 

 

 

이 상황에서는 디버깅도 의미가 없었다.

 

고민 중에 핀토스 깃북에 FAQ에 나와 똑같은 테스트의 상황에 대처하는 글을 확인했다.

 

 

글을 읽어보면 다음과 같다.

 

pass()로 테스트를 통과하는 도중 kernel_panic이 발생한 것만 같지만,

 

사실은 fail을 출력한 것이고, call stack 주소를 불러오는데 오류가 발생하여

 

fail 다음 함수인 pass의 주소를 가져온 것 뿐이었다.

 

 

 

그래서 fail이 된다면 왜 fail이 뜨는지 확인하기 위해 디버깅을 진행했다.

mlfqs-load-1 테스트 소스 파일

 

테스트 파일을 보면

 

하나의 thread가 CPU를 점유하면서  load_average가 0.5가 되는 시간이

 

38 ~ 45초 사이여야 패스가 되도록 되어있었다.

 

 

17초만에 0.5를 달성했다는 출력을 확인

 

 

하지만 17초만에 load_avg가 0.5를 달성했다는 로그가 출력되었다.

 

load_avg의 수식은 다음과 같다.

 

 

따라서 원래 원하던 시간보다 더 빨리 증가가 되었다는 것은 'ready_threads'의 수를 잘못 계산한 것이다.

 

 

내 코드에서 load_avg의 1초마다 연산하는 코드는 다음과 같았다.

 

 

"ready_threads의 수는 ready_list의 스레드 수 + CPU를 점유하고 있는 현재 스레드" 로 계산해야 한다고 생각하여 다음과 같이 연산했다.

 

 

다시 테스트 상황으로 돌아가면, 다른 스레드의 create가 진행되고 있지 않기 때문에 main 문의 스레드만 CPU를 독점하고,

ready_list는 비어있어야 하는 상황이다.

 

따라서 ready_threads_count == 1 이어야 한다.

 

???

 

근데 디버깅 해보니 ready_thread_count 가 2인 것이었다.

 

 

 

알고보니, idle_thread는 ready_thread 수에서 빼서 연산해야 되는데

 

ready_list에 우선순위가 PRI_MIN인 상태로 대기하고 있었던 것이다.

 

 

이 코드가 idle_thread가 생성되는 코드인데

 

처음 실행파일을 돌리면 thread_start를 통해 idle_thread가 생성되고

 

thread_create() 안에서 unblock을 통해 ready_list로 쓰레드가 들어간다.

 

하지만 잘 보면 thread_create()의 중간 function인 'idle()' 이

 

idle_thread를 블록하는 기능을 수행해서 ready_list에 없어야 한다.

 

idle을 생성하고 수행하는 function

 

 

하지만 이때까지만 해도 idle_thread가 ready_list에 존재하는 것이 당연한 줄 알았다.

 

idle_thread가 ready_list에 있어서 빼준 값

 

따라서 idle_thread가 ready_list에 있기에 빼주고

 

CPU를 독점하고 있는 쓰레드 수를 idle_thread가 +1한 걸로 그냥 때우고

 

idle_thread일 경우에는 ready_threads_count = 0 으로 하였다.

 

 

결과는 PASS !

 

 

상황 2  : mlfqs-recent-1 테스트에서 recent_cpu의 크기가 증가하지 않는 오류 발생

 

이번 상황은 상황 1과 반대되는 상황때문에 발생했다.

 

 

 

결론부터 말하면 모든 상황에서 ready_list에 idle_thread가 존재하는 줄 알았는데

 

mlfqs-recent-1 테스트에서는 ready_list 안에 idle_thread가 없었던 것이다.

 

 

 

그래서 다음과 같이 1 tick으로 +1 만 된 값이 영영 변하지 않고 쭉 이어간 것이 출력되었다.

 

ready_list = 0이어서 위 함수로 계산한 load_avg의 값이 증가하지 않았던 것이다.

 

 

 

 

따라서 다음과 같이 ready_list에 idle_thread가 존재하는지의 여부에 따라 연산을 다르게 하도록 예외처리했다.

 

 

결과는 PASS

 

하지만 상황 2에서 무엇때문에 idle_thread가 ready_list에 없는지는 찾지 못했다.