1130-trouble shooting(pintos - project 1 ~donations)

그로밋·2023년 11월 30일
0

krafton jungle

목록 보기
39/58

last commit - Donate tests passed except priority-donate-lower/priority-donate-chain

Trouble shooting 1

try - build after editing timer.c

error - build failed

why the error occured?

헤더 파일과 소스파일을 동일한 소스파일에 include해서 빌드 자체가 실패함
(timer.c에서 thread.c와 thread.h를 동시에 include함)

how I fix

헤더 파일만 정의.

what I learn

헤더 파일과 소스파일을 같이 넣으면 안되는 이유

  • 다중 정의 : 동일한 함수 또는 변수 선언이 두 번 제공되어 충돌이 발생할 수 있음(warning)
  • 무한 재귀 : 헤더 파일이 소스파일을 포함 & 소스 파일이 헤더파일을 포함

Trouble shooting 2

try - compare the priorities when semaphore_elem a and semaphore_elem b are given and return 1 if a is bigger, otherwise return 0.

The key is to access the threads' priorities from the given semaphore_elems

trouble - access the threads' priorities from the given semaphore_elems

why the error occured?

구조체들을 정확하게 파악하고 있지 않아서

how I fix

어떤 구조인지 먼저 파악하기

STRUCTURE

  • semaphore_elem
    - list_elem
    - semaphore
  • semaphore
    - list(waiters: list of threads)
    - value

어떤 path로 접근 할지 써보기

list_elem -> sema_elem -> sema -> waiter list -> thread -> priority

what I learn

  • 구조체들을 미리 종이나 어딘가에 그려놓고 시작하자.
  • 압축적인 코드보다 때로는 길지만 명시적인게 더 좋다.
	struct semaphore_elem *sema_elem_a = list_entry(a, struct semaphore_elem, elem);
	struct semaphore_elem *sema_elem_b = list_entry(b, struct semaphore_elem, elem);

	struct semaphore sema_a = sema_elem_a->semaphore;
	struct semaphore sema_b = sema_elem_b->semaphore;

	struct list *waiters_a = &sema_a.waiters;
	struct list *waiters_b = &sema_b.waiters;

	if(list_empty(waiters_a) == true)
		return false;
	
	if(list_empty(waiters_b) == true)
		return true;
	
	struct thread* t_a = list_entry(list_begin(waiters_a), struct thread, elem);
	struct thread* t_b = list_entry(list_begin(waiters_b), struct thread, elem);
	
	return t_a->priority > t_b->priority;

Trouble shooting 3

try - test priority-condvar

trouble - failed

priority-sema는 pass하는데 priority-condvar는 실패했다.
테스트 결과를 확인해 보니까 정렬이 안되고 있는 점을 발견할 수 있었다.

why the error occured?

error 1.

struct semaphore_elem *semaElem_a = list_entry(a, struct thread, elem);
list_entry함수에서 두번째 매개변수로 구조체를 넣어줘야 하고 여기에 넣은 구조체가 리턴된다. 저장하고자 하는 변수의 구조체와 같게 맞춰줘야 했는데 thread 구조체로 잘못 넣어주고 있었다.

how I fix

struct semaphore_elem *semaElem_a = list_entry(a, struct semaphore_elem, elem);

what I learn

함수를 사용할 때 어떤 타입으로 리턴이 되는지 확인하자.


why the error occured?

error 2.

struct thread* t_a = list_begin(waiters_a);
여기서 생기는 문제는 list_begin은 list_elem 타입을 반환하는데 thread 구조체로 받고있다.

how I fix

struct thread* t_a = list_entry(list_begin(waiters_a), struct thread, elem);
list_entry()함수로 감싸서 thread를 반환하게 하였다.

what I learn

마찬가지로 함수를 사용할 때 어떤 타입으로 리턴이 되는지 확인하자.


why the error occured?

error 2.

list_begin(&waiters_a)
list_begin()의 정의를 보면 인자로 struct list * 를 받게 되어있고 waiter이라는 리스트도 포인터변수 이기 때문에 &waiters_a로 하게되면 더블포인터가 되버린다.

how I fix

list_begin(waiters_a)

what I learn

인자로 어떤 값을 넣어줘야 하는지 함수 정의를 잘 보고, 사용하는 데이터가 포인터 변수인지 일반 변수인지 잘 체크하자.

Trouble shooting 4

try - test priority-change

trouble - failed

테스트 코드가 아래와 같았기 때문에 thread_set_priority 가 제대로 동작하지 않는다는 걸 알 수 있었다.

  msg ("Creating a high-priority thread 2.");
  thread_create ("thread 2", PRI_DEFAULT + 1, changing_thread, NULL);
  msg ("Thread 2 should have just lowered its priority.");
  thread_set_priority (PRI_DEFAULT - 2);
  msg ("Thread 2 should have just exited.");

why the error occured?

void
thread_set_priority (int new_priority) {
	struct thread *curr = thread_current();
	curr->priority = new_priority;
	goback_priority();
	test_max_priority(); 

curr->priority = new_priority; 이 코드는 원래 thread_set_priority함수에 있던 코드이다. 그래서 건드리지 않고 밑에다가 필요한 함수들을 적었었는데, 이 코드 때문에 앞에 패스했던 테스트들도 줄줄이 fail 했었다.

이 코드의 문제는 donation을 하고나서 생겼는데, 이유는 인자로 받은 새로운 priority를 donation을 받았을 수도 있는 priority 변수에 덮어 썼기 때문에 문제가 발생했다.

만약 priority가 30인데 set을 40으로 했었고 그 다음에 50을 donate받았다고 가정했을 때, 다시 돌아가야 하는 priority는 40이어야 하는데 이 코드 때문에 40이 아니라 30으로 돌아가게 된다.

how I fix

간단하게 curr->pri_before_dona = new_priority;이렇게 priority를 pri_before_dona로 해주면 된다.

what I learn

당연한 코드는 없다. 기존의 코드라도 내가 바꾼 로직때문에 제대로 동작하지 않을 수 있으니 오류가 난다면 로직을 생각해서 함수의 흐름을 타고 모든 코드를 의심하자.

names I changed

  • / 기부 받기 전 priority /
    int pri_before_dona;

  • / 해당 스레드가 대기하고 있는 lock 자료구조의 주소를 저장할 필드 /
    struct lock *lock_im_waiting;

  • / 기부 해주신 스레드의 목록 /
    struct list donor_list;

  • / donor_list를 관리하기 위한 element 로 thread 구조체의 그냥 elem 과 구분하여 사용하도록 한다. /
    struct list_elem donor_list_elem;


TODO:

  • priority 실패 했던 테스트 케이스 priority-donate-lower/priority-donate-chain 해결하기.
  • ne 사용하지 않고 포인터로 해결해보기(thread_awake())
  • 스레드가 뭔지 스케줄링, 스케줄러, 세마포어, 락 이런걸 면접관이 물어보면 대답할 수 있게 정리하기
profile
Work as though your strength were limitless. <S. Bernhardt>

0개의 댓글