pintOS project1: threads - Priority Inversion (donation)

Etherealยท2021๋…„ 10์›” 1์ผ
1

pintOS

๋ชฉ๋ก ๋ณด๊ธฐ
2/9

https://poalim.tistory.com/35?category=758538
๐Ÿ›‘๊ฑฐ์˜ ๋Œ€๋ถ€๋ถ„์˜ ๋„์›€์„ ํ•ด๋‹น ๋งํฌ์—์„œ ๋ฐ›์•„์™”์Šต๋‹ˆ๋‹ค.

๐Ÿ“–Priority Inversion (donation)


๐Ÿ“‘Priority scheduling ์—์„œ Inversion์€ ์™œ ๋ฐœ์ƒํ•˜๊ณ  Donation ์™œ ํ•„์š”ํ• ๊นŒ?


https://web.eecs.umich.edu/~akamil/teaching/sp04/pri/#fig:inversion

Priority Scheduling ์€ ํ”„๋กœ์„ธ์Šค ํ˜น์€ ์“ฐ๋ ˆ๋“œ ์ค‘ ๋‹ค์Œ์— ๋ฌด์—‡์ด ์‹คํ–‰ ๋  ์ง€ scheduling ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

์ด๋ฅผ priority๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์„ ์ •ํ•˜๊ฒŒ ๋˜๋ฉด priority scheduling์ด๋‹ค. Priority๋Š” thread ๊ตฌ์กฐ์ฒด์— ๋งด๋ฒ„๋กœ ๊ฐ ์“ฐ๋ ˆ๋“œ์— ๊ธฐ๋ก๋œ๋‹ค. thread_ready state ์ธ thread๋“ค์ด ready_list์— priority ๊ธฐ์ค€ ์˜ค๋ฆ„ ์ฐจ์ˆœ์œผ๋กœ ๊ธฐ๋ก๋˜์–ด์žˆ๋‹ค.

  • ๋‹ค์Œ๊ณผ ๊ฐ™์ด ready thread๋“ค A, B, C๊ฐ€ ๊ฐ๊ฐ 1, 2, 3 priority๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์ฐธ๊ณ ๋กœ priority๋Š” ํฐ ์ˆ˜ ์ผ ์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’๋‹ค. ์ด ๊ฒฝ์šฐ schedule ์ด ์ง„ํ–‰๋˜๋ฉด C thread๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

https://web.eecs.umich.edu/~akamil/teaching/sp04/pri/#fig:inversion

๐Ÿ“…Priority Inversion


priority๊ฐ€ ๋‚ฎ์€ thread(A or L)์ด Key๋ฅผ ๋“ค๊ณ  ์žˆ์„ ๋•Œ, ์‹คํ–‰ ์ค‘์ธ thread(H, C)๊ฐ€ key๋ฅผ ์š”์ฒญํ•˜๋Š” ๊ฒฝ์šฐ, key๊ฐ€ ๋‹ค๋ฅธ thread์—๊ฒŒ ์ข…์†๋˜์–ด์žˆ๊ธฐ์— key๊ฐ€ ๋ฐ˜ํ™˜ ๋  ๋•Œ๊นŒ์ง€ thread(H, C)๋Š” Blocked state๋กœ ๋“ค์–ด๊ฐ€๊ณ , ๊ทธ ํ›„ schedule์— ์˜ํ•ด ๋‹ค์Œ priority ์ธ thread(B, M)์ด ์‹คํ–‰๋˜๋Š”๋ฐ, ์ด ์ƒํ™ฉ์ด Priority inversion์ด๋‹ค. Priority๊ฐ€ ๋†’์€ thread(H, L)์ด ๋ฉ€์ฉกํžˆ ์žˆ๋Š”๋ฐ priority๊ฐ€ ์ƒ๋Œ€์ ์œผ๋กœ ๋‚ฎ์€ thread(B, M)์ด ์‹คํ–‰๋˜๋Š” Inversion ์ด๋‹ค.

thread ๋“ค์€ ํ•œ ํ”„๋กœ์„ธ์Šค ์•ˆ์—์„œ ์ƒ์„ฑ๋˜๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ ์‹คํ–‰ ํ๋ฆ„์ธ๋ฐ ์ด๋“ค์€ ํ”„๋กœ์„ธ์Šค์— ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ๊ณต์œ ํ•œ๋‹ค. ์ด๋•Œ ์„œ๋กœ ๋™์‹œ์— ํ•œ ์ž์›์„ ๊ฑด๋“œ๋ฆด ๊ฒฝ์šฐ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค. ์ด๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•ด semaphore/lock/conditional variable๋“ฑ์„ ์ด์šฉํ•œ๋‹ค.

https://renelemon.tistory.com/99?category=950734

๐Ÿ“…Priority Donation

์œ„์™€ ๊ฐ™์€ Inversion case๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด priority donation ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์ž.

Priority Donation์€ key holder thread์—๊ฒŒ lock์„ ์š”์ฒญํ•˜๊ณ  ์žˆ๋Š” thread์˜ priority๋ฅผ donateํ•ด์ฃผ์–ด donate ๋ฐ›์€ thread๊ฐ€ ์‹คํ–‰๋˜์–ด lock์„ release ํ•ด์ค„ ๋•Œ๊นŒ์ง€ ์‹คํ–‰ ๋  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ํŠน์ˆ˜ ์ƒํ™ฉ

๐ŸšธMultiple Donation


์Šค๋ ˆ๋“œ, ๋ฝ ๊ตฌ์กฐ์ฒด๋ฅผ ๋„์‹ํ™”ํ•ด๋ณด๋ฉด ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™๋‹ค.

๋‹จ์–ด์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์—ฌ๋Ÿฌ๋ฒˆ์˜ donation ์ด ์ผ์–ด๋‚œ ์ƒํ™ฉ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์œ„์˜ ์˜ˆ์‹œ์—์„œ L ๊ฐ€ lock A, lock B ๋ผ๋Š” ๋‘ ๊ฐ€์ง€ lock ์„ ์ ์œ ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ํ•ด๋ณด์ž. H ๊ฐ€ lock A ๋ฅผ, M ์ด lock B ๋ฅผ ๊ฐ๊ฐ ์š”์ฒญํ•˜์˜€์„ ๋•Œ, L ์€ ์ž์‹ ์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” lock ์„ ์š”์ฒญํ•œ ๋ชจ๋“  ์Šค๋ ˆ๋“œ์—๊ฒŒ priority ๋ฅผ ์–‘๋„๋ฐ›๊ณ , ์ด ์ค‘ ๊ฐ€์žฅ ๋†’์€ priority ๋ฅผ ์ผ์‹œ์ ์œผ๋กœ ์ž์‹ ์˜ priority ๋กœ ๊ฐ–๋Š”๋‹ค. ๊ทธ๋ฆผ์œผ๋กœ ๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

๐ŸšธNested Donation


์ด ์ƒํ™ฉ์—์„œ ์Šค๋ ˆ๋“œ, ๋ฝ ๊ตฌ์กฐ์ฒด๋ฅผ ๋„์‹ํ™”ํ•ด๋ณด๋ฉด ์•„๋ž˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™๋‹ค.

๊ทธ๋ฆผ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด H ๊ฐ€ lock B ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด M ์—๊ฒŒ priority donation ์„ ํ–‰ํ•˜๊ณ  M ์€ lock A ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด L ์—๊ฒŒ priority donation ์„ ํ–‰ํ•˜๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ, ์—ฌ๋Ÿฌ๋ฒˆ์˜ ๋‹จ๊ณ„์  donation ์ด ์ผ์–ด๋‚˜๋Š” ์ƒํ™ฉ์ด๋‹ค.

์ด๋•Œ donation์€ H๋ถ€ํ„ฐ ๋ฐœ์ƒํ•ด์„œ M, L ๋ชจ๋‘ H์˜ priority๋ฅผ donate ๋ฐ›์•„ ์ˆœ์ฐจ์ ์œผ๋กœ lock์„ ํ•ด์†Œํ•ด thread H๊ฐ€ ์ •์ƒ์ ์œผ๋กœ lock์„ accquire ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

โœ…๊ตฌํ˜„


๐Ÿ’ปthread.h, .c


struct thread

Priority donation์„ ์œ„ํ•ด thread.h์˜ thread ๊ตฌ์กฐ์ฒด์— ์ถ”๊ฐ€์ ์ธ ๋งด๋ฒ„๋ฅผ ์„ ์–ธํ•ด์ค€๋‹ค.

	...
		/* priority donation */
	/* priority๋ฅผ ์–‘๋„ ๋ฐ›๊ณ  ๋ฐ˜ํ™˜ํ•˜๊ณ ๋‚˜์„œ ์›๋ž˜ priority๋ฅผ ๋ณต์›ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ก*/
	int init_priority; 
	/* thread๊ฐ€ ํ˜„์žฌ ์–ป๊ธฐ ์œ„ํ•ด ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋Š” lock์˜ ์ฃผ์†Œ๋กœ ์Šค๋ ˆ๋“œ๋Š” ์ด lock ์ด release ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฐ๋‹ค. */
	struct lock *wait_on_lock; 
	/* ์ž์‹ ์—๊ฒŒ priority ๋ฅผ ๋‚˜๋ˆ„์–ด์ค€ thread๋“ค์˜ ๋ฆฌ์ŠคํŠธ์ด๊ณ  */
	struct list donations; 
	 /*  donations ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ element ๋กœ thread ๊ตฌ์กฐ์ฒด์˜ ๊ทธ๋ƒฅ elem ๊ณผ ๊ตฌ๋ถ„ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค. */
	struct list_elem donation_elem;
	...

์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€๋œ ๋งด๋ฒ„๋“ค์ธ ๋งŒํผ ์ดˆ๊ธฐํ™” ์‹œ์ผœ์ค˜์•ผํ•œ๋‹ค. init_thread() ์—์„œ.

/* thread/thread.c */
static void
init_thread (struct thread *t, const char *name, int priority)
{
  ...
  t->init_priority = priority;
  t->wait_on_lock = NULL;
  list_init (&t->donations);
  ...
}

์ด ํ•จ์ˆ˜๋Š” ์ž์‹ ์˜ priority ๋ฅผ ํ•„์š”ํ•œ lock ์„ ์ ์œ ํ•˜๊ณ  ์žˆ๋Š” ์Šค๋ ˆ๋“œ์—๊ฒŒ ๋นŒ๋ ค์ฃผ๋Š” ํ•จ์ˆ˜์ด๋‹ค. ํ•œ ๊ฐ€์ง€ ์ฃผ์˜ํ•  ์ ์€, nested donation ์—์„œ ์‚ดํŽด๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ ํ•˜์œ„์— ์—ฐ๊ฒฐ๋œ ๋ชจ๋“  ์Šค๋ ˆ๋“œ์— donation ์ด ์ผ์–ด๋‚œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

void
donate_priority (void) {
    int depth;
    struct thread *cur = thread_current ();

	/* Nested donation ์ƒํ™ฉ์„ ๋Œ€๋น„ํ•ด for๋ฌธ์„ ๋Œ๋ฆฐ๋‹ค */
    for (depth = 0; depth < 8; depth++){
		/* lock์„ ์–ป๊ธฐ ๊ธฐ๋‹ค๋ฆฌ๋Š” thread๊ฐ€ ์•„๋‹ ๊ฒฝ์šฐ breakํ•œ๋‹ค. */
		if (!cur->wait_on_lock) break;
		/* ์ผ ๊ฒฝ์šฐ ์ตœ์ƒ์œ„ priority๋ฅผ donate ํ•ด์ค€๋‹ค. */
		struct thread *holder = cur->wait_on_lock->holder;
		holder->priority = cur->priority;
		cur = holder;
    }
}

๐Ÿ”ฐremove_with_lock()

donations ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ํ˜„์žฌ thread์—๊ฒŒ priority๋ฅผ ๋นŒ๋ ค์ค€ thread๋“ค์„
donation ๋ฆฌ์ŠคํŠธ์—์„œ ์ œ๊ฑฐํ•ด์ฃผ๋Š” ํ•จ์ˆ˜. ๋‹ค๋งŒ ํ˜„์žฌ releaseํ•˜๊ณ  ์žˆ๋Š” lock ๋•Œ๋ฌธ์—
donateํ•œ thread๋งŒ ํ•ด๋‹น๋œ๋‹ค.


/* thread/thread.c */
/* donations ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ํ˜„์žฌ thread์—๊ฒŒ priority๋ฅผ ๋นŒ๋ ค์ค€ thread๋“ค์„
	donation ๋ฆฌ์ŠคํŠธ์—์„œ ์ œ๊ฑฐํ•ด์ฃผ๋Š” ํ•จ์ˆ˜. ๋‹ค๋งŒ ํ˜„์žฌ releaseํ•˜๊ณ  ์žˆ๋Š” lock ๋•Œ๋ฌธ์—
	donateํ•œ thread๋งŒ ํ•ด๋‹น๋œ๋‹ค. */
void
remove_with_lock (struct lock *lock) {
    struct list_elem *e;
    struct thread *cur = thread_current ();

	/* donation ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ */
    for (e = list_begin (&cur->donations); e != list_end (&cur->donations); e = list_next (e)){
		struct thread *t = list_entry (e, struct thread, donation_elem);
		/* ์ธ์ž๋กœ ๋ฐ›์€ lock์„ ์›ํ•ด์„œ donate๋ฅผ ํ•œ ๊ฒฝ์šฐ๋ผ๋ฉด */
		if (t->wait_on_lock == lock)
			list_remove (&t->donation_elem);
    }
}

donation ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋Š” ๊ฒฝ์šฐ๋Š” nested donation์ด ๋ฐœ์ƒํ•œ ๊ฒฝ์šฐ ๋•Œ๋ฌธ์ด๋‹ค.

๐Ÿ”ฐrefresh_priority()


ํ˜„์žฌ thread์˜ priority๋ฅผ ์›๋ž˜๋Œ€๋กœ ๋ณต๊ตฌ์‹œํ‚ค๊ฑฐ๋‚˜, ์•„์ง donations ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด
(์•„์ง ๋‚˜์—๊ฒŒ priority๋ฅผ ๋นŒ๋ ค์ค€ thread๋“ค์ด ๋‚จ์•„์ž‡๋‹ค๋ฉด) ๊ทธ์ค‘ ๊ฐ€์žฅ ๋†’์€ priority๋กœ ์žฌ์„ค์ •.

/* thread/thread.c */
/* ํ˜„์žฌ thread์˜ priority๋ฅผ ์›๋ž˜๋Œ€๋กœ ๋ณต๊ตฌ์‹œํ‚ค๊ฑฐ๋‚˜, ์•„์ง donations ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š๋‹ค๋ฉด
	(์•„์ง ๋‚˜์—๊ฒŒ priority๋ฅผ ๋นŒ๋ ค์ค€ thread๋“ค์ด ๋‚จ์•„์ž‡๋‹ค๋ฉด) ๊ทธ์ค‘ ๊ฐ€์žฅ ๋†’์€ priority๋กœ ์žฌ์„ค์ •. */
void
refresh_priority (void) {
    struct thread *cur = thread_current ();

    cur->priority = cur->init_priority;

	/* donate ๋ฐ›์€ priority๊ฐ€ ์•„์ง ๋‚จ์•„์žˆ๋‹ค๋ฉด */
    if (!list_empty (&cur->donations)) {
		list_sort (&cur->donations, thread_compare_donate_priority, 0);

		/* ๊ทธ์ค‘ ๊ฐ€์žฅ ๋†’์€  priority๋ฅผ ํ˜„์žฌ thread์˜ priority๋กœ ์„ค์ • */
    	struct thread *front = list_entry (list_front (&cur->donations), struct thread, donation_elem);
		if (front->priority > cur->priority)
			cur->priority = front->priority;
    }
}

๐Ÿ’ปsynch.c


๐Ÿ”ฐlock_acquire()


lock์„ ๋ฐ›์•„์˜ค๋Š”, ์š”์ฒญํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋‹ค๋ฅธ thread๊ฐ€ key๋ฅผ ๋ณด์œ ์ค‘์ผ ๊ฒฝ์šฐ lock์„ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ์„ ๋•Œ๊นŒ์ง€ (key๊ฐ€ release ๋  ๋•Œ๊นŒ์ง€) thread๋ฅผ sleep/block ์‹œํ‚ต๋‹ˆ๋‹ค.

donate_priority()๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

lock_acquire (struct lock *lock) {
	ASSERT (lock != NULL);
	ASSERT (!intr_context ());
	ASSERT (!lock_held_by_current_thread (lock));

	/* ==================== project1 Priority Donation ==================== */
	struct thread *cur = thread_current();

	/* ์œ„์—์„œ lock์ด ํ˜„์žฌ thread์—๊ฒŒ ์žˆ๋Š”์ง€๋ฅผ ์ด๋ฏธ assertํ–ˆ๊ธฐ์— holder๊ฐ€ ์žˆ๋‹ค๋ฉด ๋‹ค๋ฅธ thread๋‹ค.
		๋”ฐ๋ผ์„œ donation์„ ํ†ตํ•ด lock holder thread๊ฐ€ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. */
	if (lock->holder) {
		cur->wait_on_lock = lock;
		/* lock holder์˜ donation ๋ฆฌ์ŠคํŠธ์— ํ˜„์žฌ thread๋ฅผ ๊ธฐ๋กํ•ด์ค€๋‹ค. Priority ์ˆœ์œผ๋กœ */
		list_insert_ordered(&lock->holder->donations, &cur->donation_elem, 
						thread_compare_donate_priority, NULL);
		donate_priority();
	}
	
	sema_down (&lock->semaphore);
	cur->wait_on_lock = NULL;
	lock->holder = cur;
	/* ============

๐Ÿ”ฐlock_release()

ํ˜„์žฌ thread๊ฐ€ ๋“ค๊ณ  ์žˆ๋Š” lock์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜.

remove_with_lock(), refresh_priority๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.


/* Releases LOCK, which must be owned by the current thread.
   This is lock_release function.

   An interrupt handler cannot acquire a lock, so it does not
   make sense to try to release a lock within an interrupt
   handler. */
void
lock_release (struct lock *lock) {
	ASSERT (lock != NULL);
	ASSERT (lock_held_by_current_thread (lock));

	/* ==================== project1 Priority Donation ==================== */
    remove_with_lock (lock);
    refresh_priority ();	
	/* ==================== project1 Priority Donation ==================== */

	lock->holder = NULL;
	sema_up (&lock->semaphore);
}

๐Ÿšธextra case / thread_set_priority()


ํ˜„์žฌ thread๊ฐ€ lock, donation๊ณผ ๊ด€๊ณ„์—†์ด thread_set_priority ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•จ์œผ๋กœ ์ž์‹ ์˜ priority๊ฐ€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ ํ•„ํžˆ init_priority์ฆ‰ ์›๋ณธ priority๋ฅผ ๊ฐฑ์‹ ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค. ๋˜ํ•œ donations ๋ฆฌ์ŠคํŠธ๋“ค์— ์žˆ๋Š” ์Šค๋ ˆ๋“œ๋“ค๋ณด๋‹ค priority ๊ฐ€ ๋†’์•„์ง€๋Š” ๊ฒฝ์šฐ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. ์ด ๊ฒฝ์šฐ priority ๋Š” donations ๋ฆฌ์ŠคํŠธ ์ค‘ ๊ฐ€์žฅ ๋†’์€ priority ๊ฐ€ ์•„๋‹ˆ๋ผ ์ƒˆ๋กœ ๋ฐ”๋€ priority ๊ฐ€ ์ ์šฉ๋  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์•ผ ํ•œ๋‹ค.

/* thread/thread.c */
/* Sets the current thread's priority to NEW_PRIORITY. */
void
thread_set_priority (int new_priority) {
	/* ==================== project1 Prioirity Scheduling ==================== */
    thread_current ()->init_priority = new_priority;
    // thread_current ()->priority = new_priority;
	refresh_priority ();
	test_max_priority();
	/* ==================== project1 Prioirity Scheduling ==================== */
}

condition variable


https://firecatlibrary.tistory.com/58?category=875424

๐Ÿ’ฏ

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
FAIL tests/threads/mlfqs/mlfqs-load-1
FAIL tests/threads/mlfqs/mlfqs-load-60
FAIL tests/threads/mlfqs/mlfqs-load-avg
FAIL tests/threads/mlfqs/mlfqs-recent-1
pass tests/threads/mlfqs/mlfqs-fair-2
pass tests/threads/mlfqs/mlfqs-fair-20
FAIL tests/threads/mlfqs/mlfqs-nice-2
FAIL tests/threads/mlfqs/mlfqs-nice-10
FAIL tests/threads/mlfqs/mlfqs-block
7 of 27 tests failed.
profile
๊ฟˆ์—๋‹ค๊ฐ€ ์šฐ๋ฆฌ๋“ค์˜ ๋›์„ ๋‹ฌ๊ณ  ์•ž์œผ๋กœ ๋‹ค๊ฐ€์˜ฌ ๊ทธ ๋‚ ์„ ์œ„ํ•ด ๋ฐค์„ ์ง€๋‚˜์ž

0๊ฐœ์˜ ๋Œ“๊ธ€