2-1. Argument Passing 구현 준비
어제는, project 2 를 본격적으로 시작하기 전에 깃북을 정독하여 정리하고 오늘부터 드디어 구현을 위한 준비를 시작했는데 시작하자마자 문제가 발생하였다.
project 1 의 모든 테스트 케이스를 통과했음에도, userprog
폴더에서 build
한 뒤 실행하자 아래와 같은 에러 문구와 함께 부팅조차 되지 않았다.
동기도 구글링을 통해 해결했다고 하여 검색해보니, 지금까지는 process, 즉 kernel
단에서 동작했지만 이제는 userprogram이라는 user
단에서 동작하기 때문에 동작하는 유저 프로그램, 즉 process가 없는 경우가 존재할 수 있었다. 따라서 thread
를 교체하는 과정에서 준비된 스레드가 존재하는지 확인한 뒤에 교체해줄 필요가 있었다. 따라서 아래의 코드를 추가하였다.
if (list_empty(&ready_list))
return;
Kernel panic in run:
PANIC at ../../threads/thread.c:338 in thread_yield():
assertion `!intr_context ()' failed.
그 다음 직면한 문제는, 인터럽트 핸들러가 켜져있는 상태에서 스레드 교체가 발생하여 디버깅 함수가 동작한 문제였다. 이 또한 구글링을 통해 인터럽트 핸들러가 켜져있을 경우, 스레드 교체를 하지 않도록 if
문을 추가함으로써 해결하였다.
if (!intr_context()) {
thread_yield ()
}
두 문제를 모두 해결하고 나니, 이번엔 무한루프가 발생하였다.
문제를 해결하는 과정에서, 기존의 함수를 건드리지 않는 선에서 해결하려다 보니 서순이 조금 잘못되었다는 생각이 들었다. 따라서 함수 안의 if
문의 위치와 조건 자체를 수정하였다.
/* 수정 전 */
if (curr->priority < ready->priority) {
if (list_empty(&ready_list))
return;
if (!intr_context()
thread_yield ();
}
/* 수정 후 */
if (list_empty(&ready_list))
return;
if (!intr_context() && curr->priority < ready->priority) {
thread_yield ();
}
이후 다시 project 1 의 테스트 케이스를 확인했으나 문제가 없는 것을 확인했고, userprog
에서 부팅도 정상적으로 되는 것을 확인했다.
void
thread_preemption (void) {
enum intr_level old_level;
struct thread *curr = thread_current ();
struct thread *ready = list_entry (list_begin (&ready_list), struct thread, elem);
if (list_empty(&ready_list))
return;
old_level = intr_disable ();
if (!intr_context() && curr->priority < ready->priority) {
thread_yield ();
}
intr_set_level (old_level);
}