흐름을 정리한 이유?
간단하다
⌜다 끝냈으니까⌟
정글 pintos 프로젝트 1 완(完)
의외로 많이 안건드렸다
사실상 thread.c에서 다 해결봄
기존에 있던 lock_acquire
함수에서
우선순위 양보하고 뭐하고 하는 거 전부
if (thread_mlfqs != true) {
...
}
로 묶어서 처리했다
이게 끝이다
다음
thread.c의 헤더 파일이다
새로 쓰는 변수들만 선언해줬다
전역에 하나
구조체에 하나 x 3
struct thread {
...
int recent_cpu; // 최근 cpu
int nice; // 매너온도
struct list_elem allelem; // 모든 스레드 순환용 리스트
...
}
extern int load_avg; // 1분 부하 평균
그럼 끝이다
다음
부동소수점 계산이 필요하기에 관련 함수는 따로 빼주었다
이건 그냥 단순 계산만이라 로직이고 뭐고 없다
그냥 알아서 해라
각자 입맛에 맞춰 매크로 제작하면 된다
다음
크게 바꾼건 없고
조금 살만 붙여준 느낌으로 건드렸다
thread_init
에다가
thread.h
에서 만든 것들 초기화하고 세팅하는 거 넣어주고
init_thread
도 초기화 넣어준다
/* 걍 전부 초기화 */
void
thread_init (void) {
...
list_init (&all_list); // 순회 리스트 초기화
load_avg = 0; // 부하 평균 초기화
/* ------ initial_thread 등으로 초기 스레드 설정 ------ */
/* . . . */
/* -------------------------------------------------- */
// 초기 스레드 리스트에 삽입
list_push_back(&all_list, &initial_thread->allelem);
// mlfqs on일 때에 설정 값들
if (thread_mlfqs) {
initial_thread->nice = 0; // nice 값 초기화
initial_thread->recent_cpu = 0; // 최근 cpu 초기화
int p = PRI_MAX - (initial_thread->nice * 2); // 우선순위 계산
if (p < PRI_MIN) p = PRI_MIN; // 최솟값 이하일시 올려줌
if (p > PRI_MAX) p = PRI_MAX; // 최댓값 이상일시 내려줌
initial_thread->priority = p; // 우선순위 설정
}
}
/* 스레드 하나만 초기화 */
static void
init_thread (struct thread *t, const char *name, int priority) {
...
t->nice = 0; // nice 초기화
t->recent_cpu = 0; // recent_cpu 초기화
...
}
thread_create
에다가도 그 값들 세팅하는 거 넣어주고
// 걍 thread_create에 위에랑 똑같은 거 넣어줌 ㅇㅇ
thread_exit
로 스레드 제거할때 리스트 에서 빼는 거 넣어주고
void
thread_exit (void) {
...
intr_disable();
list_remove(&thread_current()->allelem); // <- 이거 한줄만 추가해줌
do_schedule (THREAD_DYING);
NOT_REACHED ();
}
thread_set_priority
mlfqs일때는 작동 안하게 하고…
void
thread_set_priority (int new_priority) {
if (thread_mlfqs != true) {
/* 기존 코드 */
}
}
흠… 좀 한게 많은 거 같기도 하고…
아무튼, 여기까지가 기존 꺼 좀 수정하는 거고 이 다음부턴 기능 추가다
뭐 많이 안한다
…
아님말고
thread_tick
에다가 1틱일때, 4틱일때, 1초일때 일어나는 일 넣어준다
void
thread_tick (void) {
...
if (thread_mlfqs == true) {
/* 현스레드가 idle_thread 아닐경우 recent_cpu++
* 매 틱마다 해줌
*/
/* 4틱일때
* 모든 스레드 돌며
* 우선순위 재계산
* 현재 스레드 ready일때 우선순위 반영 재삽입
* 스레드 다 돌고 우선순위 반영하여 기부
*/
/* 1초일때
* 모든 스레드 돌며
* 우선순위 재계산
* 현재 스레드 ready일때 우선순위 반영 재삽입
* 스레드 다 돌고 우선순위 반영하여 기부
*/
}
}
근데 여기 좀 개같이 짜놔서 다듬어야 한다
따로 함수 안 빼서 개더러움;;🤢🤢🤮🤮
그리고 이제부턴 nice
, load_avg
, recent_cpu
등등 관련 함수 건드려서 완성해주면 끝이다
/* 현재 스레드의 nice 값을 반환. */
int
thread_get_nice (void) {
return thread_current()->nice;
}
/* 시스템 load average * 100 값을 반환. */
int
thread_get_load_avg (void) {
struct thread *t = thread_current();
int return_avg = FP_TO_INT_NEAR(FP_MUL_INT(load_avg, 100));
return return_avg;
}
/* 현재 스레드의 recent_cpu * 100 값을 반환. */
int
thread_get_recent_cpu (void) {
struct thread *t = thread_current();
int return_cpu = FP_TO_INT_NEAR(FP_MUL_INT(t->recent_cpu, 100));
return return_cpu;
}
/* 현재 스레드의 nice 값을 NICE로 설정. */
void
thread_set_nice (int nice UNUSED) {
enum intr_level old = intr_disable();
struct thread *t = thread_current();
/* 최소, 최대 클램핑 */
if (nice < -20) nice = -20;
if (nice > 20) nice = 20;
t->nice = nice;
/* 우선순위 계산 */
int new_priority
= PRI_MAX
- FP_TO_INT_ZERO(FP_DIV_INT(t->recent_cpu, 4))
- (t->nice * 2);
/* 최소, 최대 클램핑 */
if (new_priority < PRI_MIN) new_priority = PRI_MIN;
if (new_priority > PRI_MAX) new_priority = PRI_MAX;
/* 우선순위 설정 */
t->priority = new_priority;
intr_set_level(old);
/* 계산후 경우에 따라 즉시 양보 */
if (!list_empty(&ready_list)) {
struct thread *top = list_entry(list_front(&ready_list), struct thread, elem);
if (top->priority > thread_current()->priority)
thread_yield();
}
}
이렇게 해주면 된다
기능은 간단한데 코드로 보니 좀 길어졌다
특히 thread_set_nice
가
아무튼, 이정도만 해주면
이제 mlfqs 클리어~
물론, 깔끔하지 못한 동작일 확률이 높으니
더 좋고 이쁜 코드도 있겠지만…
난 여기깔즤~