๐Ÿ’ฟ KAIST:PINTOS | Concept | Priority

์ด์ˆœ๊ฐ„ยท2025๋…„ 5์›” 13์ผ

KAIST:PINTOS

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

๋ชฉ์ฐจ

  1. ์Šค๋ ˆ๋“œ์™€ ์šฐ์„ ์ˆœ์œ„๋ž€?
  2. Priority Scheduling (์šฐ์„ ์ˆœ์œ„ ์Šค์ผ€์ค„๋ง)
  3. Preemption (์„ ์ )
  4. Priority Inversion (์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ํ˜„์ƒ)
  5. Priority Donation (์šฐ์„ ์ˆœ์œ„ ๊ธฐ๋ถ€)
  6. Donation Chain (๋„๋„ค์ด์…˜ ์ฒด์ธ)
  7. Donation ๋ณต๊ตฌ (Rollback)
  8. Ready List์™€ ์ •๋ ฌ ๊ธฐ์ค€
  9. ๋ฝ(Lock), ์„ธ๋งˆํฌ์–ด(Semaphore), ์กฐ๊ฑด๋ณ€์ˆ˜(Condvar)
  10. ์ •๋ฆฌ: ๊ตฌํ˜„ ์ฒดํฌ๋ฆฌ์ŠคํŠธ
  11. ์šฉ์–ด ์‚ฌ์ „

1. ์Šค๋ ˆ๋“œ์™€ ์šฐ์„ ์ˆœ์œ„๋ž€?

  • ์Šค๋ ˆ๋“œ(Thread)
    โ†’ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ตœ์†Œ ๋‹จ์œ„์ž…๋‹ˆ๋‹ค. PintOS์—์„œ ๊ฐ๊ฐ์˜ ์Šค๋ ˆ๋“œ๋Š” struct thread ๊ตฌ์กฐ์ฒด๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค.

  • ์šฐ์„ ์ˆœ์œ„(Priority)
    โ†’ ์ˆซ์ž๊ฐ€ ํด์ˆ˜๋ก ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์Šต๋‹ˆ๋‹ค.
    priority ํ•„๋“œ๊ฐ€ ์Šค๋ ˆ๋“œ์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ์ด ๊ฐ’์€ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ๋ˆ„๊ตฌ์—๊ฒŒ CPU๋ฅผ ์ค„์ง€ ๊ฒฐ์ •ํ•  ๋•Œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.


2. Priority Scheduling (์šฐ์„ ์ˆœ์œ„ ์Šค์ผ€์ค„๋ง)

์šด์˜์ฒด์ œ๋Š” ready_list ์•ˆ์— ์žˆ๋Š” ์Šค๋ ˆ๋“œ๋“ค ์ค‘ ๊ฐ€์žฅ ๋†’์€ priority๋ฅผ ๊ฐ€์ง„ ์Šค๋ ˆ๋“œ๋ฅผ ๊ณจ๋ผ CPU๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

  • ์ด ๋ฆฌ์ŠคํŠธ๋Š” ํ•ญ์ƒ priority ๋‚ด๋ฆผ์ฐจ์ˆœ ์ •๋ ฌ๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฆ‰, ์ˆซ์ž๊ฐ€ ํด์ˆ˜๋ก ๋จผ์ € ์‹คํ–‰๋จ!
list_insert_ordered(&ready_list, &t->elem, priority_cmp, NULL);

์ด ์ •๋ ฌ์ด ์•ˆ ๋˜์–ด ์žˆ์œผ๋ฉด ๋‚ฎ์€ priority๊ฐ€ ๋จผ์ € ์‹คํ–‰๋˜๋Š” ์ด์ƒํ•œ ์ƒํ™ฉ์ด ์ƒ๊น๋‹ˆ๋‹ค.


3. Preemption (์„ ์ )

ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ๋ณด๋‹ค ๋” ๋†’์€ priority์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๊นจ๊ฑฐ๋‚˜ ์ƒ์„ฑ๋˜๋ฉด,
ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋Š” CPU๋ฅผ ์–‘๋ณดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

if (!intr_context() && thread_current()->priority < max_priority)
  thread_yield();
  • intr_context()๋Š” ์ธํ„ฐ๋ŸฝํŠธ ์ฒ˜๋ฆฌ ์ค‘์ธ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • thread_yield()๋Š” ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ready_list๋กœ ๋ณด๋‚ด๊ณ  ์Šค์ผ€์ค„๋ง์„ ๋‹ค์‹œ ํ•ฉ๋‹ˆ๋‹ค.

4. Priority Inversion (์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ํ˜„์ƒ)

๋‚ฎ์€ priority์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฝ์„ ์ฅ๊ณ  ์žˆ๊ณ , ๋†’์€ priority์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ทธ ๋ฝ์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํ™ฉ์ด ์˜ค๋ฉด?

  • ๋†’์€ priority ์Šค๋ ˆ๋“œ๋Š” ๋ฝ์„ ์–ป๊ธฐ ์ „๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•จ
  • ํ•˜์ง€๋งŒ ์ค‘๊ฐ„ priority ์Šค๋ ˆ๋“œ๊ฐ€ ๊ณ„์† ์‹คํ–‰๋˜๋ฉด โ†’ ๋†’์€ priority ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ๋ชปํ•˜๋Š” ์šฐ์„ ์ˆœ์œ„ ์—ญ์ „ ๋ฐœ์ƒ

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Priority Donation ๊ฐœ๋…์ด ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.


5. Priority Donation (์šฐ์„ ์ˆœ์œ„ ๊ธฐ๋ถ€)

๋†’์€ priority์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฝ์„ ์ฅ๊ณ  ์žˆ๋Š” ๋‚ฎ์€ priority์˜ ์Šค๋ ˆ๋“œ๋ฅผ ๊ธฐ๋‹ค๋ฆด ๋•Œ,
์ž์‹ ์˜ priority๋ฅผ ์ž„์‹œ๋กœ ๊ธฐ๋ถ€ํ•ฉ๋‹ˆ๋‹ค.

donation ๋ฐœ์ƒ ์กฐ๊ฑด

  • lock_acquire() ๋„์ค‘ lock์ด ์ด๋ฏธ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์— ์˜ํ•ด ์‚ฌ์šฉ ์ค‘์ผ ๋•Œ
  • waiting_lock ํ•„๋“œ๋ฅผ ๋”ฐ๋ผ๊ฐ€๋ฉฐ holder์—๊ฒŒ priority๋ฅผ ์ „๋‹ฌ

๐Ÿ”จ ํ•„์š”ํ•œ ๊ตฌ์กฐ์ฒด ํ•„๋“œ

int original_priority;           // ๊ธฐ๋ถ€๋ฐ›๊ธฐ ์ „ ์šฐ์„ ์ˆœ์œ„ ์ €์žฅ
struct lock *waiting_lock;       // ๋‚ด๊ฐ€ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋Š” ๋ฝ
struct list donations;           // ๋‚˜์—๊ฒŒ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ธฐ๋ถ€ํ•œ ์Šค๋ ˆ๋“œ๋“ค

6. โ›“๏ธ Donation Chain (๋„๋„ค์ด์…˜ ์ฒด์ธ)

ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋˜ ๋‹ค๋ฅธ ๋ฝ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋‹ค๋ฉด?

Thread C (priority 50) โ†’ ๋Œ€๊ธฐ ์ค‘: lock2
Thread B (priority 20) โ†’ lock2 holder, ๋Œ€๊ธฐ ์ค‘: lock1
Thread A (priority 10) โ†’ lock1 holder

์ด๋ ‡๊ฒŒ ์—ฐ๊ฒฐ๋œ ์ƒํ™ฉ์—์„œ, Thread C๋Š” B์—๊ฒŒ, B๋Š” A์—๊ฒŒ priority๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ๊ธฐ๋ถ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

โ†’ ๋„๋„ค์ด์…˜์€ ์žฌ๊ท€์ ์œผ๋กœ ์ „๋‹ฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

while (lock && lock->holder && lock->holder->priority < t->priority)
{
  lock->holder->priority = t->priority;
  lock = lock->holder->waiting_lock;
}

7. ๐Ÿงน Donation ๋ณต๊ตฌ (Rollback)

๋ฝ์„ ํ•ด์ œํ•  ๋•Œ๋Š” ํ•ด๋‹น ๋ฝ์„ ํ†ตํ•ด ๋ฐ›์€ donation์„ ๋˜๋Œ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.

remove_with_lock(lock);     // ํ•ด๋‹น ๋ฝ ๊ด€๋ จ donation ์ œ๊ฑฐ
refresh_priority();         // ๊ฐ€์žฅ ๋†’์€ donation์œผ๋กœ priority ๋ณต์›
  • ๊ธฐ๋ถ€๋ฐ›์€ donation ๋ชฉ๋ก์„ ์œ ์ง€ํ•˜๊ณ ,
  • ํŠน์ • ๋ฝ์— ๋Œ€ํ•œ donation๋งŒ ์ œ๊ฑฐํ•˜๋Š” ๋ฐฉ์‹

8. ๐Ÿ“‹ Ready List์™€ ์ •๋ ฌ ๊ธฐ์ค€

ready_list, sema->waiters, condvar->waiters ๋“ฑ ๋ชจ๋“  ๋Œ€๊ธฐ ํ๋Š” priority ์ˆœ์„œ๋Œ€๋กœ ์ •๋ ฌ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

bool priority_cmp(const struct list_elem *a, const struct list_elem *b, void *aux UNUSED)
{
  return list_entry(a, struct thread, elem)->priority
       > list_entry(b, struct thread, elem)->priority;
}

9. ๐Ÿ”’ ๋ฝ, ์„ธ๋งˆํฌ์–ด, ์กฐ๊ฑด๋ณ€์ˆ˜

  • ๋ฝ(lock): ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ์ž์›์„ ์‚ฌ์šฉํ•˜๋„๋ก ์ œ์–ด
    โ†’ lock_acquire(), lock_release()์—์„œ donation ์ฒ˜๋ฆฌ ํ•„์š”

  • ์„ธ๋งˆํฌ์–ด(semaphore): ๋Œ€๊ธฐ ํ์™€ signal ๊ฐœ๋…์œผ๋กœ ์ž์›์„ ์ œ์–ด
    โ†’ sema_down()์—์„œ priority ์ˆœ์„œ๋กœ ๋Œ€๊ธฐ ํ ์‚ฝ์ž…

  • ์กฐ๊ฑด๋ณ€์ˆ˜(condvar): ์–ด๋–ค ์กฐ๊ฑด์ด ๋งŒ์กฑ๋  ๋•Œ๋งŒ ๊นจ์šฐ๊ธฐ
    โ†’ cond_signal()์—์„œ ๊ฐ€์žฅ ๋†’์€ priority ์Šค๋ ˆ๋“œ๋ฅผ ๊นจ์›Œ์•ผ ํ•จ


10. โœ… ๊ตฌํ˜„ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

๊ตฌํ˜„ ํ•ญ๋ชฉ์„ค๋ช…๊ด€๋ จ ํ…Œ์ŠคํŠธ
ready_list ์ •๋ ฌ๋†’์€ priority๊ฐ€ ์•ž์—priority-fifo, priority-preempt
donate_priority()๊ธฐ๋ถ€ ๋กœ์งpriority-donate-one, -multiple, -nest, -chain
remove_with_lock()donation ์ œ๊ฑฐpriority-donate-multiple2, -lower
thread_set_priority()์šฐ์„ ์ˆœ์œ„ ์ˆ˜๋™ ๋ณ€๊ฒฝpriority-change
sema/cond ์ •๋ ฌ์„ธ๋งˆํฌ์–ด / ์กฐ๊ฑด๋ณ€์ˆ˜ ๋Œ€๊ธฐ ์ˆœ์„œ ์ •๋ ฌpriority-sema, priority-condvar

๐Ÿ“š ์šฉ์–ด ์‚ฌ์ „

์šฉ์–ด์„ค๋ช…
Thread (์Šค๋ ˆ๋“œ)CPU์—์„œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์ž‘์—… ๋‹จ์œ„
Priority (์šฐ์„ ์ˆœ์œ„)์Šค๋ ˆ๋“œ์˜ ์‹คํ–‰ ์šฐ์„ ๋„
Preemption (์„ ์ )๋” ๋†’์€ priority๊ฐ€ ๋‚˜ํƒ€๋‚  ๋•Œ CPU๋ฅผ ์–‘๋ณดํ•˜๋Š” ๊ฒƒ
Priority Inversion๋‚ฎ์€ priority๊ฐ€ ๋†’์€ priority๋ฅผ ๋ง‰๋Š” ํ˜„์ƒ
Donation๋†’์€ priority๊ฐ€ ๋‚ฎ์€ priority์—๊ฒŒ ์šฐ์„ ๊ถŒ์„ ์ผ์‹œ์ ์œผ๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ๊ฒƒ
Chain Donation๋„๋„ค์ด์…˜์ด ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์— ๊ฑธ์ณ ์—ฐ์‡„์ ์œผ๋กœ ์ผ์–ด๋‚˜๋Š” ๊ฒƒ
Rollback๋ฝ ํ•ด์ œ ์‹œ ๋„๋„ค์ด์…˜์„ ํšŒ์ˆ˜ํ•˜๊ณ  ์›๋ž˜ priority ๋ณต์›
Lock์ž์›์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์ œํ•œํ•˜๋Š” ๋™๊ธฐํ™” ๊ธฐ๋ฒ•
Semaphore๋Œ€๊ธฐ ํ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ณ ์ „์  ๋™๊ธฐํ™” ๊ธฐ๋ฒ•
Condvar์กฐ๊ฑด์ด ์ถฉ์กฑ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•˜๋Š” ๊ตฌ์กฐ

๐Ÿ” ๊ตฌํ˜„ ์ˆœ์„œ์™€ ์˜์กด์„ฑ โ€“ ๋ฌด์—‡๋ถ€ํ„ฐ ๋งŒ๋“ค์–ด์•ผ ํ• ๊นŒ?

PintOS Project 1์˜ priority-* ๊ด€๋ จ ๊ธฐ๋Šฅ๋“ค์€ ์„œ๋กœ ๊ฐ•ํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
๋‹จ์ˆœํžˆ ์ˆœ์„œ๋Œ€๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ๊ธฐ๋Šฅ ๊ฐ„ ์˜์กด์„ฑ์„ ๊ณ ๋ คํ•ด์„œ ์ˆœ์„œ๋ฅผ ์ •ํ•ด์•ผ ํ…Œ์ŠคํŠธ๊ฐ€ ์ œ๋Œ€๋กœ ํ†ต๊ณผ๋ฉ๋‹ˆ๋‹ค.


๐Ÿงฑ ๊ตฌํ˜„ ๋‹จ๊ณ„๋ณ„ ์˜์กด ๊ตฌ์กฐ

๋‹จ๊ณ„๊ตฌํ˜„ ํ•ญ๋ชฉ์˜์กด ์ด์œ 
1๏ธโƒฃready_list ์ •๋ ฌ๋ชจ๋“  priority ์Šค์ผ€์ค„๋ง ๋กœ์ง์˜ ๊ธฐ๋ฐ˜. ์Šค๋ ˆ๋“œ๊ฐ€ ๊นจ์–ด๋‚  ๋•Œ ์˜ฌ๋ฐ”๋ฅธ ์ˆœ์„œ๋กœ ์ •๋ ฌ๋˜์–ด ์žˆ์–ด์•ผ ์ดํ›„ donation๋„ ์˜๋ฏธ ์žˆ์Œ.
2๏ธโƒฃdonate_priority()๋„๋„ค์ด์…˜ ๋กœ์ง ๊ตฌํ˜„. ์—ญ์ „ ํ˜„์ƒ ํ•ด๊ฒฐ์˜ ํ•ต์‹ฌ์ด๋ฉฐ, ready_list ์ •๋ ฌ์ด ๋˜์–ด์•ผ๋งŒ donation์ด ํšจ๊ณผ์ ์œผ๋กœ ๋ฐ˜์˜๋จ.
3๏ธโƒฃremove_with_lock() & refresh_priority()๋ฝ ํ•ด์ œ ์‹œ ๋„๋„ค์ด์…˜ ํšŒ์ˆ˜. donation์ด ๊ตฌํ˜„๋œ ํ›„์—์•ผ ํ•„์š”ํ•˜๋ฉฐ, rollback ๋กœ์ง์œผ๋กœ ๋ฐ˜๋“œ์‹œ ์ด์–ด์ ธ์•ผ ํ•จ.
4๏ธโƒฃthread_set_priority()์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜๋™์œผ๋กœ priority๋ฅผ ๋ฐ”๊ฟ€ ๋•Œ, donation ์—ฌ๋ถ€์— ๋”ฐ๋ผ ์–ด๋–ค ๊ฐ’์„ ๋ฐ˜์˜ํ• ์ง€ ๊ฒฐ์ •ํ•ด์•ผ ํ•จ. donation ๋กœ์ง์ด ์„ ํ–‰๋˜์–ด์•ผ ์˜๋ฏธ ์žˆ์Œ.
5๏ธโƒฃsema_down() / cond_signal() ์ •๋ ฌ์„ธ๋งˆํฌ์–ด/์กฐ๊ฑด๋ณ€์ˆ˜ waiters ๋ฆฌ์ŠคํŠธ๋„ priority ๊ธฐ๋ฐ˜ ์ •๋ ฌ์ด ํ•„์š”. ๋ฝ ๊ธฐ๋ฐ˜ donation ๋กœ์ง์ด ๋ชจ๋‘ ๋™์ž‘ํ•œ ์ดํ›„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒŒ ์•ˆ์ „.

๐Ÿ’ก ์™œ ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•œ๊ฐ€?

  • ์ •๋ ฌ ๋จผ์ € โ†’ donation ๋‚˜์ค‘
    ๋„๋„ค์ด์…˜์„ ํ•ด๋„ ready_list๊ฐ€ FIFO ๋ฐฉ์‹์ด๋ผ๋ฉด ๋†’์€ priority ์Šค๋ ˆ๋“œ๋Š” ์‹คํ–‰๋˜์ง€ ๋ชปํ•จ โ†’ ํ…Œ์ŠคํŠธ ์‹คํŒจ

  • rollback์€ donation ์—†์ด๋Š” ์˜๋ฏธ ์—†์Œ
    ๋„๋„ค์ด์…˜์ด ์—†๋Š”๋ฐ rollback ๋จผ์ € ๊ตฌํ˜„ํ•˜๋ฉด ์ฝ”๋“œ๋งŒ ๋ณต์žกํ•ด์ง€๊ณ  ํ…Œ์ŠคํŠธ์— ์˜ํ–ฅ ์—†์Œ

  • ์„ธ๋งˆํฌ์–ด ์ •๋ ฌ์€ ๋งˆ์ง€๋ง‰์—
    ๊ธฐ๋ณธ์ ์ธ ๋ฝ ๊ธฐ๋ฐ˜ donation์ด ์™„์ „ํžˆ ์ž‘๋™ํ•œ ํ›„์—, ๋‚˜๋จธ์ง€ ๋™๊ธฐํ™” ๊ตฌ์กฐ์— priority-aware ๋™์ž‘์„ ํ™•์žฅํ•˜๋ฉด ๋œ๋‹ค

profile
์„œํˆด์ง€์–ธ์ • ๋Š˜ ํ–‰๋™์ด ๋จผ์ €์ด๊ธฐ๋ฅผ

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