ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • pintOS 에서 thread_yield() 에서 커널 패닉이 날때
    Archive/Issue Solve 2024. 5. 6. 15:36

    문제 발생

    Formatting file system...Kernel PANIC at ../../threads/thread.c:474 in thread_yield(): assertion `!intr_context()' failed.

     

    핀토스 프로젝트 2 user  program 진행중 단일 테스트를 실행하면 위와 같은 커널 패닉이 자꾸 나타났다.

    ec2를 사용하는 동료는 해당 패닉이 발생하지 않고 wsl 을 사용하는 나에게 만 발생했다.

     

    추적

    패닉에 적힌대로 thread.c 파일로 찾아가 474라인의 thread_yield()를 불렀는데 assert 문의 !intr_context() 에서 false 가 걸리는 것을 해결해야한다.

     

    intr_context() 함수는 현재 외부 인터럽트를 처리중이었다면(인터럽트 핸들러가 실행중이라면) True 아니라면 False 를 내 뱉는 함수이다.

     

    내 코드에서 인터럽트를 끄지 않은 곳에서 해당 thread_yield() 를 호출하는 곳을 찾아보기로 했고 해당 위치는

    test_max_priority() 함수였다.

    // 우선순위 스케줄링 하는 함수
    void test_max_priority(void) {
        struct thread *curr = thread_current();
        struct list_elem *highest_elem = list_begin(&ready_list);
        if (list_end(&ready_list) == (highest_elem)) {
            return;
        }
    
        if (less_priority(&curr->elem, highest_elem, NULL)) {
            thread_yield();
        }
    }
    콜 스택에서 적힌 주소를 활용해 backtrace 를 이용해 역 추적해도 되고 ctrl + f 로 thread_yield() 를 부르는 곳을 찾아보았다.

     

    생각해보니 인터럽트 실행중에 thread_yield() 가 호출되면 안되는데 여기서 호출이 되었던 것이다. 그래서 아래와 같이 수정했다.

     

    // 우선순위 스케줄링 하는 함수
    void test_max_priority(void) {
        struct thread *curr = thread_current();
        struct list_elem *highest_elem = list_begin(&ready_list);
        if (list_end(&ready_list) == (highest_elem)) {
            return;
        }
    
        if (!intr_context() && less_priority(&curr->elem, highest_elem, NULL)) {
            thread_yield();
        }
    }

     

    해결완료

    왜 ec2에선 되고 wsl 에서만 발생????

    gpt 돌림 디버깅을 통해 정확히 추적해서 얻은 결과가 아님에 주의!!! 아래는 뇌피셜임 뇌피셜!!!⚠️⚠️⚠️
    1. 인터럽트 처리 빈도 증가:
      • 성능 향상으로 인해 타이머 인터럽트 발생 빈도가 높아지면, 인터럽트 핸들러가 더 자주 호출됩니다.
      • 더 많은 타이머 인터럽트로 인해 test_max_priority() 함수가 인터럽트 컨텍스트에서 호출될 가능성이 높아집니다.
    2. 스케줄링 빈도 증가:
      • 높은 타이머 인터럽트 빈도로 인해 스케줄러가 더 빈번하게 실행되어 선점 스케줄링이 더 자주 발생합니다.
      • 이로 인해 인터럽트 컨텍스트에서 test_max_priority()가 호출될 가능성이 커지며, thread_yield()가 인터럽트 컨텍스트에서 호출되어 커널 패닉을 일으킬 수 있습니다.
    3. 운영 체제 및 하드웨어 차이:
      • WSL과 EC2는 각각 다른 가상화 기술을 사용하지만, 두 플랫폼 모두 성능 향상이 이루어지면 인터럽트 처리와 스케줄링에서 비슷한 문제를 경험할 수 있습니다.

    나의 wsl 환경에선 

    초당 연산이 2억 6천만번 일어난다. (연산 맞나? 아무튼 루프가)

     

    ec2 환경에선

    1억 5천만번 일어난다.

     

    그래서 운좋게 인터럽트를 피해서 thread_yield() 가 호출되었나 싶다. 추후에 공부해서 해당 의문점을 해결할것.

     

    결론

    실제로 thread_yield 는 인터럽트 처리중에 일어나면 안되니 해당 조건을 적용하는 것이 옳아보임.

Designed by Tistory.