[05.13/week09]TIL

CHO WanGi·2025년 5월 13일

KRAFTON JUNGLE 8th

목록 보기
53/89

오늘 하루 요약

길을 잃었다

✏️ 오늘의 한 일

  • PintOS : Waiters list 정렬 + Ready Queue 검사로직 함수화

🌈오늘의 성장!

Waiters List 정렬

  • 기존에는 어떻게 Waiter리스트를 관리 했는가
  1. semaphore
  • sema_init에서 초기화
  • sema_down(P연산)에서 pushback
    • list_inserted_order로 정렬해서 push
    • thread_block
  • sema_up(V연산)에서 pop front
    • list_inserted_order로 정렬해서 push
    • thread_unblock => Ready Queue 정렬 발생

sema_up

void sema_up(struct semaphore *sema)
{
	enum intr_level old_level;

	ASSERT(sema != NULL);

	old_level = intr_disable();
	if (!list_empty(&sema->waiters))
	{
		list_sort(&sema->waiters, cmp_priority, 0);
		thread_unblock(list_entry(list_pop_front(&sema->waiters), struct thread, elem));
	}
	sema->value++;
	recheck_readyQueue();
	intr_set_level(old_level);
}

sema_down

void sema_down(struct semaphore *sema)
{
	// sema -> 접근할 공유 자원의 개수?
	enum intr_level old_level;

	ASSERT(sema != NULL);
	ASSERT(!intr_context());

	old_level = intr_disable();
	while (sema->value == 0)
	{
		// list_push_back(&sema->waiters, &thread_current()->elem);
		// waiters 정렬 요구사항 구현위해 정렬하여 Push
		list_insert_ordered(&sema->waiters, &thread_current()->elem, cmp_priority, NULL);
		thread_block();
	}
	sema->value--;
	intr_set_level(old_level);
}
  1. cond_var
    원리는 semaphore랑 같은데 좀 다른게 있다.

cond_wait

void cond_wait(struct condition *cond, struct lock *lock)
{
	struct semaphore_elem waiter;

	ASSERT(cond != NULL);
	ASSERT(lock != NULL);
	ASSERT(!intr_context());
	ASSERT(lock_held_by_current_thread(lock));

	sema_init(&waiter.semaphore, 0);
	// list_push_back(&cond->waiters, &waiter.elem);
	list_insert_ordered(&cond->waiters, &waiter.elem, cmp_condval_priority, NULL);
	lock_release(lock);
	sema_down(&waiter.semaphore);
	lock_acquire(lock);
}

리스트에 들어가는 원소 자료형이 semaphore_elem 자료형이다.
따라서 list_insert_ordered 함수에 들어가는 less 함수가 좀 달라야 한다.

cmp_condval_priority

우린 스레드의 우선순위를 가져와야 한다.
결국 자료형에 따라
semaphore_elem -> list -> thread 로 와야한다.

	// 인자로 받는 Elem이 thread가 아닌 semaphore
bool cmp_condval_priority(struct list_elem *l, struct list_elem *s, void *aux UNUSED)
{
	// thread까지 어떻게 접근?
	struct semaphore_elem *l_semaphore = list_entry(l, struct semaphore_elem, elem);
	struct semaphore_elem *s_semaphore = list_entry(s, struct semaphore_elem, elem);

	struct list *l_semaphore_waiters = &(l_semaphore->semaphore.waiters);
	struct list *s_semaphore_waiters = &(s_semaphore->semaphore.waiters);

	struct thread *l_thread = list_entry(list_begin(l_semaphore_waiters), struct thread, elem);
	struct thread *s_thread = list_entry(list_begin(s_semaphore_waiters), struct thread, elem);

	return l_thread->priority > s_thread->priority;
}

recheck_readyQueue

void recheck_readyQueue()
{
	int new_priority = thread_current()->priority;
	struct thread *first_elem = list_entry(list_begin(&ready_list), struct thread, elem);

	if (!list_empty(&ready_list) && first_elem->priority > new_priority)
	{
		thread_yield(); // 현재 CPU 점유중이던 스레드, CPU 자원 양보
	}
}

ReadyQueue가 변동되는 경우가 많아서 따로 함수화 해주었다.

⛏ 오늘의 삽질

진짜 lock 부수고 싶다.

profile
제 Velog에 오신 모든 분들이 작더라도 인사이트를 얻어가셨으면 좋겠습니다 :)

0개의 댓글