24.03.14 TIL

lsjoon·2024년 3월 14일
0

TIL

목록 보기
46/51

Weekly Task

  • Project 2 :
    1. Argument Passing,
    2. User Memory, System Calls,
    3. Process Termination Messages,
    4. Denying Writes to Executables,
    5. (Extra) Extend File Descriptor

Project 2

2-1. Argument Passing 구현 준비

Comment

어제는, project 2 를 본격적으로 시작하기 전에 깃북을 정독하여 정리하고 오늘부터 드디어 구현을 위한 준비를 시작했는데 시작하자마자 문제가 발생하였다.

문제1


project 1 의 모든 테스트 케이스를 통과했음에도, userprog 폴더에서 build 한 뒤 실행하자 아래와 같은 에러 문구와 함께 부팅조차 되지 않았다.

동기도 구글링을 통해 해결했다고 하여 검색해보니, 지금까지는 process, 즉 kernel 단에서 동작했지만 이제는 userprogram이라는 user 단에서 동작하기 때문에 동작하는 유저 프로그램, 즉 process가 없는 경우가 존재할 수 있었다. 따라서 thread 를 교체하는 과정에서 준비된 스레드가 존재하는지 확인한 뒤에 교체해줄 필요가 있었다. 따라서 아래의 코드를 추가하였다.

  if (list_empty(&ready_list))
    return;

문제2


Kernel panic in run:
PANIC at ../../threads/thread.c:338 in thread_yield():
assertion `!intr_context ()' failed.

그 다음 직면한 문제는, 인터럽트 핸들러가 켜져있는 상태에서 스레드 교체가 발생하여 디버깅 함수가 동작한 문제였다. 이 또한 구글링을 통해 인터럽트 핸들러가 켜져있을 경우, 스레드 교체를 하지 않도록 if문을 추가함으로써 해결하였다.

if (!intr_context()) {
	thread_yield ()
}

문제3


두 문제를 모두 해결하고 나니, 이번엔 무한루프가 발생하였다.

문제를 해결하는 과정에서, 기존의 함수를 건드리지 않는 선에서 해결하려다 보니 서순이 조금 잘못되었다는 생각이 들었다. 따라서 함수 안의 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);
}
profile
중요한 것은 꺾여도 그냥 하는 마음

0개의 댓글