๐Ÿ“€ KAIST:PINTOS | Implementation | Alarm

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

KAIST:PINTOS

๋ชฉ๋ก ๋ณด๊ธฐ
1/23
post-thumbnail

ํ…Œ์ŠคํŠธ

ํ…Œ์ŠคํŠธ ์ด๋ฆ„๋ชฉ์ 
alarm-single์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ 1๋ฒˆ์”ฉ ์ž๊ณ  ์ •ํ™•ํžˆ ๊นจ์–ด๋‚˜๋Š”๊ฐ€
alarm-multiple์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜๋ณตํ•ด์„œ sleep/wakeup ํ•˜๋Š”๊ฐ€
alarm-simultaneous์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ tick์— ๊นจ์–ด๋‚˜๋Š”๊ฐ€
alarm-prioritysleep ์ค‘์—๋„ ์šฐ์„ ์ˆœ์œ„ ์Šค์ผ€์ค„๋ง์ด ์ง€์ผœ์ง€๋Š”๊ฐ€
alarm-zerotimer_sleep(0)์ด ์ฆ‰์‹œ ๋ฐ˜ํ™˜๋˜๋Š”๊ฐ€
alarm-negative์Œ์ˆ˜ ticks์—๋„ ์‹œ์Šคํ…œ์ด ์•ˆ์ •์ ์œผ๋กœ ์ž‘๋™ํ•˜๋Š”๊ฐ€

๋ณ€๊ฒฝ์ 

1. timer_sleep() ์ˆ˜์ • (timer.c)

// ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ์ฃผ์–ด์ง„ tick ์ˆ˜๋งŒํผ ์ž ๋“ค๊ฒŒ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜
void timer_sleep(int64_t ticks) {
  // ๋งŒ์•ฝ ticks๊ฐ€ 0 ์ดํ•˜๋ผ๋ฉด, ๋ฐ”๋กœ ๋ฆฌํ„ด (์ฆ‰, ์ž ๋“ค ํ•„์š” ์—†์Œ)
  // ์˜ˆ: timer_sleep(0), timer_sleep(-1) ๋“ฑ โ†’ ๊ทธ๋ƒฅ ๋ฌด![](https://velog.velcdn.com/images/qnfrma1997/post/d79221a0-96fc-43ed-97d4-2195a702984e/image.png)
์‹œ
  if (ticks <= 0) return;

  // ํ˜„์žฌ ์‹œ๊ฐ„์„ ๊ฐ€์ ธ์™€์„œ, ์–ธ์ œ ๊นจ์–ด๋‚˜์•ผ ํ• ์ง€๋ฅผ ๊ณ„์‚ฐ
  // ์ง€๊ธˆ ์‹œ๊ฐ„ + ticks ๋งŒํผ์ด ๊นจ์–ด๋‚˜์•ผ ํ•  ์‹œ์ 
  int64_t wakeup_tick = timer_ticks() + ticks;

  // ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ sleep_list์— ๋„ฃ๊ณ  BLOCK ์ƒํƒœ๋กœ ์ „ํ™˜
  // ๊นจ์–ด๋‚˜์•ผ ํ•  ์‹œ๊ฐ„์ธ wakeup_tick์„ ์ €์žฅํ•˜๊ณ  ์ •๋ ฌ ์‚ฝ์ž…
  thread_sleep(wakeup_tick);
}

โ†’ ๋ฐ”์œ ๋Œ€๊ธฐ(busy wait)๋ฅผ ์—†์• ๊ณ , BLOCK ๋ฐฉ์‹์œผ๋กœ sleep ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋„๋ก ์ˆ˜์ •ํ•จ.


2. thread_sleep() ๊ตฌํ˜„ (thread.c)

// ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ๊นจ์–ด๋‚˜์•ผ ํ•  ์‹œ์ (wakeup_tick)๊นŒ์ง€ BLOCK ์ƒํƒœ๋กœ ๋งŒ๋“ค๊ณ  sleep_list์— ์ถ”๊ฐ€ํ•˜๋Š” ํ•จ์ˆ˜
void thread_sleep(int64_t wakeup_tick) {
  // ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ์˜ ํฌ์ธํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ด
  struct thread *curr = thread_current();

  // sleep_list๋Š” ๊ณต์œ  ์ž์›์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ธํ„ฐ๋ŸฝํŠธ๋ฅผ ์ž ์‹œ ๋น„ํ™œ์„ฑํ™”ํ•˜์—ฌ ์ถฉ๋Œ ๋ฐฉ์ง€
  enum intr_level old = intr_disable();

  // ํ˜„์žฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๊นจ์–ด๋‚˜์•ผ ํ•  ์‹œ๊ฐ„์„ ์Šค๋ ˆ๋“œ ๊ตฌ์กฐ์ฒด์— ๊ธฐ๋ก
  curr->wakeup_tick = wakeup_tick;

  // sleep_list์— ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ ๊นฐ ์‹œ๊ฐ„ ์ˆœ์„œ๋กœ ์ •๋ ฌ ์‚ฝ์ž…
  // ์ด๋•Œ ๋น„๊ต ๊ธฐ์ค€ ํ•จ์ˆ˜๋Š” wakeup_compare()
  list_insert_ordered(&sleep_list, &curr->elem, wakeup_compare, NULL);

  // ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ BLOCK ์ƒํƒœ๋กœ ์ „ํ™˜ โ†’ ์Šค์ผ€์ค„๋Ÿฌ์— ์˜ํ•ด ์‹คํ–‰ ์ค‘์ง€๋จ
  thread_block();

  // ์ธํ„ฐ๋ŸฝํŠธ ์ƒํƒœ๋ฅผ ์›๋ž˜๋Œ€๋กœ ๋ณต์› (์•ˆ์ „ํ•˜๊ฒŒ ๋‹ค์‹œ ์ผœ์คŒ)
  intr_set_level(old);
}

โ†’ ํ˜„์žฌ ์Šค๋ ˆ๋“œ๋ฅผ BLOCK ์‹œํ‚ค๊ณ , sleep_list์— ์ •๋ ฌ๋œ ์ƒํƒœ๋กœ ์‚ฝ์ž….


3. thread_awake() ๊ตฌํ˜„ (thread.c)

// ํ˜„์žฌ ์‹œ๊ฐ„(now_tick)๋ณด๋‹ค ๋จผ์ € ๊นจ์›Œ์•ผ ํ•  ์Šค๋ ˆ๋“œ๋“ค์„ sleep_list์—์„œ ๊บผ๋‚ด READY ์ƒํƒœ๋กœ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜
void thread_awake(int64_t now_tick) {
  // sleep_list๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์€ ๋™์•ˆ ๊ณ„์† ๋ฐ˜๋ณต
  while (!list_empty(&sleep_list)) {
    // ๋ฆฌ์ŠคํŠธ ๋งจ ์•ž์˜ ์š”์†Œ๋ฅผ ๊ฐ€์ ธ์™€์„œ, ํ•ด๋‹น ์Šค๋ ˆ๋“œ ํฌ์ธํ„ฐ๋กœ ๋ณ€ํ™˜
    struct thread *t = list_entry(list_front(&sleep_list), struct thread, elem);

    // ํ•ด๋‹น ์Šค๋ ˆ๋“œ์˜ wakeup_tick์ด ํ˜„์žฌ ์‹œ๊ฐ„๋ณด๋‹ค ๊ฐ™๊ฑฐ๋‚˜ ์ž‘์œผ๋ฉด โ†’ ๊นจ์–ด๋‚  ์‹œ๊ฐ„ ๋„๋‹ฌ
    if (t->wakeup_tick <= now_tick) {
      // ๋ฆฌ์ŠคํŠธ์—์„œ ํ•ด๋‹น ์Šค๋ ˆ๋“œ๋ฅผ ์ œ๊ฑฐ
      list_pop_front(&sleep_list);

      // ํ•ด๋‹น ์Šค๋ ˆ๋“œ๋ฅผ READY ์ƒํƒœ๋กœ ์ „ํ™˜ (๋‹ค์‹œ ์‹คํ–‰๋  ์ˆ˜ ์žˆ๊ฒŒ)
      thread_unblock(t);
    }
    // ์•„์ง ๊นฐ ์‹œ๊ฐ„์ด ๋˜์ง€ ์•Š์€ ์Šค๋ ˆ๋“œ๊ฐ€ ๋งจ ์•ž์— ์žˆ์œผ๋ฉด โ†’ ๊ทธ ๋’ค ์Šค๋ ˆ๋“œ๋“ค๋„ ๋ชจ๋‘ later โ†’ ์ •์ง€
    else break;
  }
}

โ†’ ๋งค tick๋งˆ๋‹ค ๊นฐ ์‹œ๊ฐ„์ด ๋œ ์Šค๋ ˆ๋“œ๋“ค์„ READY ์ƒํƒœ๋กœ ๋ฐ”๊ฟˆ.


4. wakeup_compare() ๊ตฌํ˜„ (thread.c)

// sleep_list์— ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฝ์ž…ํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๋น„๊ต ํ•จ์ˆ˜
// wakeup_tick ๊ฐ’์„ ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฆ„์ฐจ์ˆœ ์ •๋ ฌ๋˜๋„๋ก ํ•œ๋‹ค
static bool wakeup_compare(const struct list_elem *a, const struct list_elem *b, void *aux UNUSED) {
  // a์™€ b๋Š” sleep_list ์•ˆ์˜ ์š”์†Œ๋“ค์ธ๋ฐ, list_elem ํƒ€์ž…์ด๋ฏ€๋กœ
  // ์‹ค์ œ๋กœ๋Š” struct thread ์•ˆ์— ํฌํ•จ๋œ elem ํ•„๋“œ์ž„
  // ๋”ฐ๋ผ์„œ list_entry ๋งคํฌ๋กœ๋ฅผ ์ด์šฉํ•ด ์›๋ž˜ ๊ตฌ์กฐ์ฒด(= struct thread)๋กœ ๋˜๋Œ๋ฆผ

  // a๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” thread์˜ wakeup_tick ๊ฐ’์ด b๋ณด๋‹ค ์ž‘์œผ๋ฉด true ๋ฐ˜ํ™˜
  return list_entry(a, struct thread, elem)->wakeup_tick
       < list_entry(b, struct thread, elem)->wakeup_tick;
}

โ†’ sleep_list๋ฅผ ๊นฐ ์‹œ๊ฐ„ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๊ธฐ ์œ„ํ•œ ๋น„๊ต ํ•จ์ˆ˜.


5. timer_interrupt() ์ˆ˜์ • (timer.c)

// ํƒ€์ด๋จธ ์ธํ„ฐ๋ŸฝํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋Š” ์ธํ„ฐ๋ŸฝํŠธ ํ•ธ๋“ค๋Ÿฌ
// 1์ดˆ์— TIMER_FREQ(๊ธฐ๋ณธ 100ํšŒ) ๋งŒํผ ์‹คํ–‰๋จ
void timer_interrupt(struct intr_frame *args UNUSED) {
  // ์‹œ์Šคํ…œ์ด ๋ถ€ํŒ…๋œ ์ดํ›„ ํ๋ฅธ ์ „์ฒด tick ์ˆ˜๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚ด
  // โ†’ tick์€ PintOS์˜ ๊ธฐ๋ณธ์ ์ธ ์‹œ๊ฐ„ ๋‹จ์œ„
  ticks++;

  // ํ˜„์žฌ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•œ tick ๋™์•ˆ ์‹คํ–‰๋˜์—ˆ์Œ์„ ์ปค๋„์— ์•Œ๋ฆผ
  // โ†’ ์Šค์ผ€์ค„๋ง, CPU ์ ์œ  ์‹œ๊ฐ„ ๋“ฑ ๋‚ด๋ถ€ ๊ด€๋ฆฌ์— ์‚ฌ์šฉ๋จ
  thread_tick();

  // ์ง€๊ธˆ tick๊นŒ์ง€ ๋„๋‹ฌํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด ๊นจ์šฐ๊ธฐ
  // โ†’ sleep_list์— ์žˆ๋Š” ์Šค๋ ˆ๋“œ๋“ค์„ ํ™•์ธํ•˜๊ณ ,
  //    wakeup_tick์ด ํ˜„์žฌ tick๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€ ์Šค๋ ˆ๋“œ๋“ค์„ READY๋กœ ์ „ํ™˜
  thread_awake(ticks);
}

โ†’ ํƒ€์ด๋จธ ์ธํ„ฐ๋ŸฝํŠธ ๋ฐœ์ƒ ์‹œ๋งˆ๋‹ค ๊นฐ ์Šค๋ ˆ๋“œ๋ฅผ ์ฒดํฌํ•ด์„œ ๊นจ์šฐ๋Š” ํ๋ฆ„ ์ถ”๊ฐ€.


์ถ”๊ฐ€

  • thread.h์— thread_sleep, thread_awake ํ•จ์ˆ˜ ์„ ์–ธ ์ถ”๊ฐ€ (๊ฒฝ๊ณ  ์ œ๊ฑฐ ๋ชฉ์ )
  • list_insert_ordered()๋Š” PintOS์—์„œ ๊ธฐ๋ณธ ์ œ๊ณต๋˜๋Š” ์ •๋ ฌ ์‚ฝ์ž… ํ•จ์ˆ˜ โ†’ ์ง์ ‘ ์‚ฌ์šฉ
  • list_entry()๋ฅผ ํ†ตํ•ด list_elem โ†’ struct thread ํฌ์ธํ„ฐ ๋ณ€ํ™˜

ํ…Œ์ŠคํŠธ ํŒŒ์ผ(.output) ๊ด€๋ฆฌ

  • make check TEST=alarm-single ๋ช…๋ น์€ alarm ๊ณ„์—ด ํ…Œ์ŠคํŠธ๋“ค์„ ์—ฐ์† ์‹คํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์—,
  • ๊ฐ๊ฐ์˜ .output ํŒŒ์ผ(alarm-single.output, alarm-multiple.output ๋“ฑ)์„ ์ˆ˜๋™์œผ๋กœ ์ƒ์„ฑํ•˜๊ณ ,
  • tests/threads/ ๋””๋ ‰ํ† ๋ฆฌ์— ๋ณต์‚ฌํ•˜์—ฌ ์ž๋™ ์ฑ„์ ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๊ตฌ์„ฑ

ํ‚ค์›Œ๋“œ

ํ‚ค์›Œ๋“œ์˜๋ฏธ
BLOCK / READY ์ƒํƒœ์Šค๋ ˆ๋“œ๊ฐ€ CPU๋ฅผ ์ ์œ  ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€
sleep_list์ž ๋“  ์Šค๋ ˆ๋“œ๋“ค์„ ๋ณด๊ด€ํ•˜๋Š” ์ „์—ญ ๋ฆฌ์ŠคํŠธ
wakeup_tick์Šค๋ ˆ๋“œ๊ฐ€ ๊นจ์–ด๋‚˜์•ผ ํ•  ์‹œ์  (tick)
list_insert_ordered๋ฆฌ์ŠคํŠธ์— ์ •๋ ฌ ์‚ฝ์ž…ํ•˜๋Š” ํ•จ์ˆ˜
list_entrylist_elem* โ†’ ๊ตฌ์กฐ์ฒด ํฌ์ธํ„ฐ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋งคํฌ๋กœ
interrupt_disable/enable๋ฆฌ์ŠคํŠธ ์กฐ์ž‘ ์‹œ ์ธํ„ฐ๋ŸฝํŠธ ์ถฉ๋Œ ๋ฐฉ์ง€์šฉ

์ •๋ฆฌ

๊ธฐ์กด timer_sleep()์€ busy wait ๋ฐฉ์‹์ด๋ผ ๋น„ํšจ์œจ์ ์ด์—ˆ๊ณ ,
thread_sleep()๊ณผ thread_awake()๋ฅผ ๊ตฌํ˜„ํ•ด BLOCK ์ƒํƒœ ๊ธฐ๋ฐ˜ ์Šฌ๋ฆฝ/์›จ์ดํฌ์—… ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด์•ผํ•จ
๊ทธ๊ฑธ timer_interrupt()์— ์—ฐ๊ฒฐํ•ด์„œ ๋งค tick๋งˆ๋‹ค sleep_list๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ๊นฐ ์Šค๋ ˆ๋“œ๋ฅผ READY๋กœ ๋งŒ๋“ฌ

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

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

์ตœ๊ณ 

1๊ฐœ์˜ ๋‹ต๊ธ€