PintOS Project 2-4: User Programs - System Calls 3

손찬호·2024년 5월 31일

크래프톤 정글 5기

목록 보기
10/12
post-thumbnail

현재까지 구현상황

make check로 테스트를 진행하면

FAIL tests/userprog/fork-multiple
FAIL tests/filesys/base/syn-read
FAIL tests/filesys/base/syn-write
FAIL tests/userprog/no-vm/multi-oom
...
4 of 95 tests failed.

이 4마리의 벌레를 잡아보자

단일 테스트는 아래의 코드로 실행할 수 있다.
make를 실행하면 build파일이 생기고 ./userprog/build

make tests/userprog/fork-multiple.result VERBOSE=1 
make tests/filesys/base/syn-read.result VERBOSE=1 
make tests/filesys/base/syn-write.result VERBOSE=1 
make tests/userprog/no-vm/multi-oom.result VERBOSE=1 

step 1 - threads/thread.c 수정

단일 테스트로 에러메시지를 확인해보니 thread_create (const char *name, int priority)
부분에서 문제가 생겼다. 그래서 all pass한 팀원과의 코드를 비교해보니까 예외처리를

palloc_get_page (PAL_ZERO);로 적어놨는데 PAL_ZERO가 0이 아니라 2를 의미했다.

또한 palloc_get_page(PAL_ZERO)로 할당했는데 할당이 제대로 이루어지지 않은 경우
NULL을 반환하는데 이때 예외처리로 할당했던 page공간을 free를 해줘야했다.

tid_t
thread_create (const char *name, int priority,
		thread_func *function, void *aux) {
	struct thread *t;
	tid_t tid;

	ASSERT (function != NULL);

	/* Allocate thread. */
	t = palloc_get_page (0);
	if (t == NULL)
		return TID_ERROR;

	/* Initialize thread. */
	init_thread (t, name, priority);
	tid = t->tid = allocate_tid ();

	/* Call the kernel_thread if it scheduled.
	 * Note) rdi is 1st argument, and rsi is 2nd argument. */
	t->tf.rip = (uintptr_t) kernel_thread;
	t->tf.R.rdi = (uint64_t) function;
	t->tf.R.rsi = (uint64_t) aux;
	t->tf.ds = SEL_KDSEG;
	t->tf.es = SEL_KDSEG;
	t->tf.ss = SEL_KDSEG;
	t->tf.cs = SEL_KCSEG;
	t->tf.eflags = FLAG_IF;

	/* 파일 시스템 */
	t->parent = thread_current();
	sema_init(&t->exit_sema, 0);
	sema_init(&t->wait_sema, 0);
	sema_init(&t->load_sema, 0);

	// 현재 스레드의 자식으로 추가 
	list_push_back(&thread_current()->child_list, &t->child_elem);

	t->fd_table = palloc_get_page(PAL_ZERO);
	if (t->fd_table == NULL) {
		palloc_free_page(t);
		return TID_ERROR;
	}

	t->fd_table[0] = 1;
	t->fd_table[1] = 2;
	t->next_fd = 2;

	/* Add to run queue. */
	thread_unblock (t);
	// 현재 실행 중인 스레드보다 우선순위가 높다면 교체
	check_preemption();

	return tid;
}

step 1 - 테스트 결과

...
pass tests/userprog/fork-multiple
FAIL tests/userprog/no-vm/multi-oom
pass tests/filesys/base/syn-read
pass tests/filesys/base/syn-write
1 of 95 tests failed.

tests/userprog/fork-multiple
tests/filesys/base/syn-read
tests/filesys/base/syn-write
3개의 테스트를 통과했다.

이제 마지막 하나 FAIL tests/userprog/no-vm/multi-oom만 남았다.

step 2 - tests/userprog/no-vm/multi-oom

../userprog/build$ make tests/userprog/no-vm/multi-oom.result VERBOSE=1
로 단일 테스트를 진행했다.
잘 되다가 (multi-oom) crashed child should return -1.: FAILED라는 에러메시지가 콘솔에
출력되었다.
cmd + shift + f로 "crashed child"가 출력되는 걸 확인해보니
../root/tests/userprog/no-vm/multi-oom.c의 "make_children(void)"에서 터지고 있었고
크게 2곳이 후보였는데 fork(), wait() 함수에서 문제가 발생하는 것으로 보였다.

  • pid = fork(child_name);
  • wait (pid) != -1

fork 부분에 child thread를 생성하는 부분에서 문제라 생각했다.

왜냐하면 테스트 코드 중간에 210번째에서 이미 child스레드가 생성되었는데 한 번 더 생성요청을 하는 테스트코드가 있었기 때문이다.
child_210_X: exit(-1)
child_210_O: exit(211)

../userprog/process.c/ 수정

자식이 로드되다가 오류로 exit하면 TID_ERROR를 반환하도록 추가했고

../userprog/syscall.c의 error가 발생했을 때 thread_exit()이 아닌
exit(TID_ERROR)인 시스템 콜을 호출하도록 설정했다.

step 2 - 테스트 결과

pass tests/userprog/args-none
pass tests/userprog/args-single
pass tests/userprog/args-multiple
pass tests/userprog/args-many
pass tests/userprog/args-dbl-space
pass tests/userprog/halt
pass tests/userprog/exit
pass tests/userprog/create-normal
pass tests/userprog/create-empty
pass tests/userprog/create-null
pass tests/userprog/create-bad-ptr
pass tests/userprog/create-long
pass tests/userprog/create-exists
pass tests/userprog/create-bound
pass tests/userprog/open-normal
pass tests/userprog/open-missing
pass tests/userprog/open-boundary
pass tests/userprog/open-empty
pass tests/userprog/open-null
pass tests/userprog/open-bad-ptr
pass tests/userprog/open-twice
pass tests/userprog/close-normal
pass tests/userprog/close-twice
pass tests/userprog/close-bad-fd
pass tests/userprog/read-normal
pass tests/userprog/read-bad-ptr
pass tests/userprog/read-boundary
pass tests/userprog/read-zero
pass tests/userprog/read-stdout
pass tests/userprog/read-bad-fd
pass tests/userprog/write-normal
pass tests/userprog/write-bad-ptr
pass tests/userprog/write-boundary
pass tests/userprog/write-zero
pass tests/userprog/write-stdin
pass tests/userprog/write-bad-fd
pass tests/userprog/fork-once
pass tests/userprog/fork-multiple
pass tests/userprog/fork-recursive
pass tests/userprog/fork-read
pass tests/userprog/fork-close
pass tests/userprog/fork-boundary
pass tests/userprog/exec-once
pass tests/userprog/exec-arg
pass tests/userprog/exec-boundary
pass tests/userprog/exec-missing
pass tests/userprog/exec-bad-ptr
pass tests/userprog/exec-read
pass tests/userprog/wait-simple
pass tests/userprog/wait-twice
pass tests/userprog/wait-killed
pass tests/userprog/wait-bad-pid
pass tests/userprog/multi-recurse
pass tests/userprog/multi-child-fd
pass tests/userprog/rox-simple
pass tests/userprog/rox-child
pass tests/userprog/rox-multichild
pass tests/userprog/bad-read
pass tests/userprog/bad-write
pass tests/userprog/bad-read2
pass tests/userprog/bad-write2
pass tests/userprog/bad-jump
pass tests/userprog/bad-jump2
pass tests/filesys/base/lg-create
pass tests/filesys/base/lg-full
pass tests/filesys/base/lg-random
pass tests/filesys/base/lg-seq-block
pass tests/filesys/base/lg-seq-random
pass tests/filesys/base/sm-create
pass tests/filesys/base/sm-full
pass tests/filesys/base/sm-random
pass tests/filesys/base/sm-seq-block
pass tests/filesys/base/sm-seq-random
pass tests/filesys/base/syn-read
pass tests/filesys/base/syn-remove
pass tests/filesys/base/syn-write
pass tests/userprog/no-vm/multi-oom
pass tests/threads/alarm-single
pass tests/threads/alarm-multiple
pass tests/threads/alarm-simultaneous
pass tests/threads/alarm-priority
pass tests/threads/alarm-zero
pass tests/threads/alarm-negative
pass tests/threads/priority-change
pass tests/threads/priority-donate-one
pass tests/threads/priority-donate-multiple
pass tests/threads/priority-donate-multiple2
pass tests/threads/priority-donate-nest
pass tests/threads/priority-donate-sema
pass tests/threads/priority-donate-lower
pass tests/threads/priority-fifo
pass tests/threads/priority-preempt
pass tests/threads/priority-sema
pass tests/threads/priority-condvar
pass tests/threads/priority-donate-chain
All 95 tests passed.

후기

All passed한 팀원의 도움을 받아 무사히 Project 2를 마무리했다.
어디를 고쳐야하는지는 테스트로 직접 확인했지만
어떻게 고쳐야하는지는 Project 3도 해야했기에 팀원의 도움을 받았다.

profile
매일 1%씩 성장하려는 주니어 개발자입니다.

0개의 댓글