[Pintos-KAIST] Project 1 : Multi-Level Feedback Queue Scheduler

์œ ์„ ยท2024๋…„ 5์›” 3์ผ
2

Pintos - KAIST

๋ชฉ๋ก ๋ณด๊ธฐ
5/16
post-thumbnail

๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป GITHUB ๋ ˆํฌ์ง€ํ† ๋ฆฌ
๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป GITHUB Priority Donation ์ด์Šˆ

๊ณผ์ œ ์„ค๋ช…

๐Ÿ™‹โ€โ™€๏ธ WIL-Advancde Scheduler ๋ฐœํ‘œ์ž๋ฃŒ ๋ณด๋Ÿฌ๊ฐ€๊ธฐ

MLFQS

์ด์ „๊นŒ์ง€ ๊ตฌํ˜„ํ•œ priority scheduler ๋Š” ๊ทธ ์‹คํ–‰์„ ์˜ค์ง priority ์—๋งŒ ๋งก๊ธฐ๊ธฐ ๋•Œ๋ฌธ์— priority ๊ฐ€ ๋‚ฎ์€ ์Šค๋ ˆ๋“œ๋“ค์€ CPU ๋ฅผ ์ ์œ ํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์–ด๋ ต๊ณ  ์ด๋กœ ์ธํ•˜์—ฌ ํ‰๊ท ๋ฐ˜์‘์‹œ๊ฐ„(Average response time) ์€ ๊ธ‰๊ฒฉํžˆ ์ปค์งˆ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค. ๋ฌผ๋ก  priority donation ์„ ํ†ตํ•˜์—ฌ priority ๊ฐ€ ๋†’์€ ์Šค๋ ˆ๋“œ๋“ค์ด ์‹คํ–‰๋˜๋Š” ๋ฐ ํ•„์š”ํ•œ ์Šค๋ ˆ๋“œ๋Š” priority ์˜ ๋ณด์ •์„ ๋ฐ›์ง€๋งŒ, ์ด๋งˆ์ €๋„ ๋ฐ›์ง€ ๋ชปํ•˜๋Š” ์Šค๋ ˆ๋“œ๊ฐ€ ์กด์žฌํ•  ๊ฐ€๋Šฅ์„ฑ๋„ ๋งค์šฐ ํฌ๋‹ค. Advanced Scheduler ๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  average response time ์„ ์ค„์ด๊ธฐ ์œ„ํ•ด multi-level feedback queue ์Šค์ผ€์ค„๋ง ๋ฐฉ์‹์„ ๋„์ž…ํ•œ๋‹ค. ์ด ์Šค์ผ€์ค„๋ง ๋ฐฉ์‹์˜ ํŠน์ง•์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ์—์„œ๋Š” 2๋ฒˆ์„ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ํ•œ๋‹ค.

  1. Priority ์— ๋”ฐ๋ผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ Ready Queue ๊ฐ€ ์กด์žฌํ•œ๋‹ค. (Multi-level)
  2. Priority ๋Š” ์‹ค์‹œ๊ฐ„์œผ๋กœ ์กฐ์ ˆํ•œ๋‹ค. (Feedback)

KEYWORD

๊ตฌํ˜„์„ ์œ„ํ•ด ์ƒˆ๋กœ ์ถ”๊ฐ€๋˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๋“ค์ด ์žˆ๋‹ค.

1๏ธโƒฃ NICENESS

  • ์Šค๋ ˆ๋“œ์˜ ์  ํ‹€ํ•จ์„ ๋‚˜ํƒ€๋‚ด ์ค€๋‹ค.
  • ์ˆ˜์น˜๊ฐ€ ๋†’์œผ๋ฉด Priority๊ฐ€ ์ค„์–ด๋“ค์–ด CPU๋ฅผ ๋” ์ ๊ฒŒ ์ ์œ ํ•˜๊ฒŒ ๋œ๋‹ค.

2๏ธโƒฃ PRIORITY

  • ๊ธฐ์กด์˜ ๊ณ ์ •๋˜๊ฑฐ๋‚˜ Donation๋œ ํƒœ์ƒ์ ์ธ Priority๊ฐ€ ์•„๋‹Œ CPU ์‚ฌ์šฉ๋Ÿ‰๊ณผ Niceness์— ์˜ํ•ด ๊ฒฐ์ •๋˜๊ฒŒ ๋œ๋‹ค.

3๏ธโƒฃ RECENT_CPU

  • ๋ง ๊ทธ๋Œ€๋กœ ์ตœ๊ทผ CPU์˜ ์ ์œ  TICK์„ ๋‚˜ํƒ€๋‚ธ๋‹ค.
  • ์ด ์ˆ˜์น˜๊ฐ€ ๋†’์œผ๋ฉด ์—ญ์‹œ Priority๊ฐ€ ์ค„์–ด๋“ค๊ฒŒ ๋œ๋‹ค.

4๏ธโƒฃ LOAD AVG

  • ์‹œ์Šคํ…œ์˜ ํ˜„์žฌ ๋ถ€ํ•˜ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ง€ํ‘œ์ด๋‹ค.

PRIORITY, RECENT_CPU, LOAD_AVG๋ฅผ ๊ตฌํ•˜๋Š” ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

PRIORITY๋Š” ์ œ์‹œ๋œ ๊ฐ€์ค‘์น˜๋กœ ๊ฒฐ์ •๋˜๊ฒŒ ๋˜๊ณ , RECENT CPU์˜ ๊ฒฝ์šฐ CPU ์ ์œ ์‹œ๊ฐ„์˜ ๊ฐ’์„ ์ง€์ˆ˜ ๊ฐ€์ค‘ ํ‰๊ท ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณ„์‚ฐํ•˜๊ฒŒ ๋œ๋‹ค. LOAD AVERAGE๋Š” 1๋ถ„ ๋™์•ˆ ์ˆ˜ํ–‰ ๊ฐ€๋Šฅํ•œ ์Šค๋ ˆ๋“œ์˜ ํ‰๊ท  ๊ฐœ์ˆ˜๋ฅผ ์ถ”์ •ํ•˜๋Š” ๊ณ„์‚ฐ์‹์ด๋‹ค.

NICENESS๊ฐ€ ์—†๋Š”๋ฐ ์ด๋Š” Test Program์—์„œ ์ž„์˜๋กœ ์ง€์ •ํ•ด ์ค€๋‹ค.

๐Ÿ’ก ์ด ๋•Œ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์ด ์žˆ๋‹ค. ๋ฐ”๋กœ ์‹ค์ˆ˜ํ˜•์ด๋ผ๋Š” ๊ฒƒ!
๊ทธ๋Ÿฌ๋‚˜ ํ•€ํ† ์Šค์—์„œ๋Š” ์‹ค์ˆ˜๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Œ!!! ์ด๋ฅผ ์œ„ํ•ด ๊ณ ์ •์†Œ์ˆ˜์  ํ‘œํ˜„์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋จ..!!!

๊ณ ์ •์†Œ์ˆ˜์ 


๊ณ ์ •์†Œ์ˆ˜์  ํ‘œํ˜„์ด๋ž€ 32๋น„ํŠธ์งœ๋ฆฌ ์ •์ˆ˜ํ˜•์„ ๊ฐ–๊ณ  14๋ฒˆ์งธ ์ž๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ œ์ผ ์•ž 1์ž๋ฆฌ๋Š” ๋ถ€ํ˜ธ, ์™ผ์ชฝ 17์ž๋ฆฌ๋Š” ์ •์ˆ˜, ์˜ค๋ฅธ์ชฝ 14์ž๋ฆฌ๋Š” ์†Œ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ฒ•์ด๋‹ค.

๊ทธ๋ž˜์„œ F๋ผ๋Š” 2์˜14์Šน์งœ๋ฆฌ ์ˆซ์ž๋ฅผ ๋งŒ๋“ค์–ด ์‹ค์ˆ˜์™€ ์ •์ˆ˜๋ฅผ ์ „ํ™˜ํ•˜๊ฒŒ ๋˜๊ณ  ์ด์— ๋”ฐ๋ผ ํŠน์ˆ˜ํ•œ ๋งคํฌ๋กœ๋ฅผ ๋งŒ๋“ค์–ด ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋ง์…ˆ์„ ํ• ๋•Œ๋Š” ์ •์ˆ˜์— F๋ฅผ ๊ณฑํ•ด ์‹ค์ˆ˜๋กœ ๋งŒ๋“ค์–ด ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์‹ค์ˆ˜๋ผ๋ฆฌ ๊ณฑ์…ˆ์„ ํ•  ๋•Œ๋Š” ๋‘˜ ๋‹ค F๊ฐ€ ๊ณฑํ•ด์ง„ ์ƒํƒœ์ด๋ฏ€๋กœ ์ค‘๋ณต๋œ F๋ฅผ ์‚ญ์ œํ•˜๊ธฐ ์œ„ํ•ด F๋กœ ๋‚˜๋ˆ„์–ด ์ค€๋‹ค.

๊ตฌํ˜„ ๋ชฉํ‘œ

Multi-Level Feedback Queue ์Šค์ผ€์ฅด๋Ÿฌ( BSD ์Šค์ผ€์ค„๋Ÿฌ์™€ ์œ ์‚ฌ) ๊ตฌํ˜„

์ˆ˜์ • ํ•จ์ˆ˜

  • void thread_set_priority(int new_priority) : ํ˜„์žฌ ์ˆ˜ํ–‰์ค‘์ธ ์Šค๋ ˆ๋“œ์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๋ณ€๊ฒฝ
  • static void timer_interrupt(struct intr_frame *args UNUSED) : timer interrupt ํ•ธ๋“ค๋Ÿฌ

๊ตฌํ˜„ํ•ด์•ผํ•  ํ•จ์ˆ˜

  • int thread_get_nice (void)
  • void thread_set_nice (int)
  • int thread_get_recent_cpu (void)
  • int thread_get_load_avg (void)

์ถ”๊ฐ€ ํ•จ์ˆ˜

  • void mlfqs_priority (struct thread *t) : ์ธ์ž๋กœ ์ฃผ์–ด์ง„ ์Šค๋ ˆ๋“œ์˜ priority๋ฅผ ์—…๋ฐ์ดํŠธ
  • void mlfqs_recent_cpu (struct thread *t) : ์ธ์ž๋กœ ์ฃผ์–ด์ง„ ์Šค๋ ˆ๋“œ์˜ recent_cpu๋ฅผ ์—…๋ฐ์ดํŠธ
  • void mlfqs_load_avg (void) : ์‹œ์Šคํ…œ์˜ load_avg๋ฅผ ์—…๋ฐ์ดํŠธ
  • void mlfqs_increment (void) : ํ˜„์žฌ ์ˆ˜ํ–‰์ค‘์ธ ์Šค๋ ˆ๋“œ์˜ recent_cpu๋ฅผ 1์ฆ๊ฐ€ ์‹œํ‚ด
  • void mlfqs_recalc (void) : ๋ชจ๋“  ์Šค๋ ˆ๋“œ์˜ priority, recent_cpu๋ฅผ ์—…๋ฐ์ดํŠธ

์‚ฌ์ „ ํ™˜๊ฒฝ ์„ค์ •

๋™์ž‘ ์ˆœ์„œ ์ค‘ Source ./activate ์•ˆ์น˜๊ฒŒ ํ•˜๋Š”๋ฒ•!!

  1. ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™

  2. code .bashrc ์ž…๋ ฅ

  3. ํŒŒ์ผ ์ œ์ผ ๋ฐ‘์— ๋ณธ์ธ์˜ source activate ๊ฒฝ๋กœ ์ถ”๊ฐ€

ํ…Œ์ŠคํŠธ ๋ฐฉ๋ฒ•

  1. /pintos ๊ฒฝ๋กœ์—์„œ source ./activate (์‚ฌ์ „ ํ™˜๊ฒฝ ์„ค์ •์„ ํ–ˆ๋‹ค๋ฉด ์•ˆํ•ด์ค˜๋„ ๋œ๋‹ค!)

  2. threads ํด๋” ๋“ค์–ด๊ฐ€์„œ make clean make check๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด Test Case๋“ค์— ๋Œ€ํ•ด์„œ ์ฑ„์ ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

  3. Test Case ํ•œ๊ฐ€์ง€๋งŒ ๋Œ๋ฆฌ๊ณ  ์‹ถ๋‹ค๋ฉด, pintos/(ํ”„๋กœ์ ํŠธ๋ช…)/build์— ๋“ค์–ด๊ฐ€์„œ ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด ๋œ๋‹ค.
    pintos -T (Timout์ด ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„) -- -q -run (Test case ์ด๋ฆ„)
    ex) `pintos -T 30 -- -q run donate-one

๊ตฌํ˜„

์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์œ„ํ•œ ์ž๋ฃŒ๊ตฌ์กฐ ์ถ”๊ฐ€

  • include/threads/thread.h
.
.
.
/** project1-Advanced Scheduler */
#define NICE_DEFAULT 0
#define RECENT_CPU_DEFAULT 0
#define LOAD_AVG_DEFAULT 0
.
.
.
/** project1-Advanced Scheduler */
int niceness;
int recent_cpu;
.
.
.

์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ์œ„ํ•ด ์ถ”๊ฐ€๋กœ ๊ตฌํ˜„ํ•  ํ•จ์ˆ˜ ์„ ์–ธ

  • include/threads/thread.h
/** project1-Advanced Scheduler */
void mlfqs_priority(struct thread *t);
void mlfqs_recent_cpu(struct thread *t);
void mlfqs_load_avg(void);
void mlfqs_increment(void);
void mlfqs_recalc_recent_cpu(void);
void mlfqs_recalc_priority(void);

all_list, all_elem ์ž๋ฃŒ ๊ตฌ์กฐ ์ถ”๊ฐ€

  • include/threads/thread.h
	int niceness;
	int recent_cpu;
	struct list_elem all_elem; /** project1-Advanced Scheduler */
  • threads/thread.c
static struct list ready_list;

/** project1-Advanced Scheduler */
static struct list all_list;

/* Idle thread. */
static struct thread *idle_thread;

.
.
.

thread_init() ํ•จ์ˆ˜ ์ˆ˜์ •

all list ์ดˆ๊ธฐํ™”

void
thread_init (void) {
	ASSERT (intr_get_level () == INTR_OFF);

	/* Reload the temporal gdt for the kernel
	 * This gdt does not include the user context.
	 * The kernel will rebuild the gdt with user context, in gdt_init (). */
	struct desc_ptr gdt_ds = {
		.size = sizeof (gdt) - 1,
		.address = (uint64_t) gdt
	};
	lgdt (&gdt_ds);

	/* Init the globla thread context */
	lock_init (&tid_lock);
	list_init (&ready_list);
	list_init (&destruction_req);
	list_init (&sleep_list); /** project1-Alarm Clock */
	list_init(&all_list); /** project1-Advanced Scheduler */

	/* Set up a thread structure for the running thread. */
	initial_thread = running_thread ();
	init_thread (initial_thread, "main", PRI_DEFAULT);

	/** project1-Advanced Scheduler */
	if (thread_mlfqs)
		list_push_back(&all_list, &(initial_thread->all_elem));

	initial_thread->status = THREAD_RUNNING;
	initial_thread->tid = allocate_tid ();
}

init_thread() ํ•จ์ˆ˜ ์ˆ˜์ •

  • threads/thread.c
static void
init_thread (struct thread *t, const char *name, int priority) {
	ASSERT (t != NULL);
	ASSERT (PRI_MIN <= priority && priority <= PRI_MAX);
	ASSERT (name != NULL);

	memset (t, 0, sizeof *t);
	t->status = THREAD_BLOCKED;
	strlcpy (t->name, name, sizeof t->name);
	t->tf.rsp = (uint64_t) t + PGSIZE - sizeof (void *);

	/** project1-Advanced Scheduler */
    if (thread_mlfqs) {
        mlfqs_priority(t);
        list_push_back(&all_list, &t->all_elem);
    } else {
        t->priority = priority;
    }

    t->wait_lock = NULL;
    list_init(&t->donations);

    t->magic = THREAD_MAGIC;

    /** #Advanced Scheduler */
    t->original_priority = t->priority;
    t->niceness = NICE_DEFAULT;
    t->recent_cpu = RECENT_CPU_DEFAULT;
}

fixed point ์—ฐ์‚ฐ ํ•จ์ˆ˜ ๊ตฌํ˜„

  • include/threads/fixed_point.h
/** project1-Advanced Scheduler */
#define F (1 << 14)
#define INT_MAX ((1 << 31) - 1)
#define INT_MIN (-(1 << 31))

/*
 * ๊ณ ์ • ์†Œ์ˆ˜์ ์„ ์œ„ํ•œ ์‚ฐ์ˆ  ์—ฐ์‚ฐ
 * n: int ; x, y: ๊ณ ์ • ์†Œ์ˆ˜์  ์ˆซ์ž ; F: 17.14๋กœ ํ‘œํ˜„ํ•œ 1
 */

int int_to_fp(int n);         /* integer๋ฅผ fixed point๋กœ ์ „ํ™˜ */
int fp_to_int_round(int x);   /* FP๋ฅผ int๋กœ ์ „ํ™˜(๋ฐ˜์˜ฌ๋ฆผ) */
int fp_to_int(int x);         /* FP๋ฅผ int๋กœ ์ „ํ™˜(๋ฒ„๋ฆผ) */
int add_fp(int x, int y);     /* FP์˜ ๋ง์…ˆ */
int add_mixed(int x, int n);  /* FP์™€ int์˜ ๋ง์…ˆ */
int sub_fp(int x, int y);     /* FP์˜ ๋บ„์…ˆ(x-y) */
int sub_mixed(int x, int n);  /* FP์™€ int์˜ ๋บ„์…ˆ(x-n) */
int mult_fp(int x, int y);    /* FP์˜ ๊ณฑ์…ˆ */
int mult_mixed(int x, int y); /* FP์™€ int์˜ ๊ณฑ์…ˆ */
int div_fp(int x, int y);     /* FP์˜ ๋‚˜๋ˆ—์…ˆ(x/y) */
int div_mixed(int x, int n);  /* FP์™€ int ๋‚˜๋ˆ—์…ˆ(x/n) */


/* ํ•จ์ˆ˜ ๋ณธ์ฒด */

/* integer๋ฅผ fixed point๋กœ ์ „ํ™˜ */
int int_to_fp(int n) {
    return n * F;
}

/* FP๋ฅผ int๋กœ ์ „ํ™˜(๋ฐ˜์˜ฌ๋ฆผ) */
int fp_to_int_round(int x) {
    if (x >= 0)
        return (x + F / 2) / F;
    else
        return (x - F / 2) / F;
}

/* FP๋ฅผ int๋กœ ์ „ํ™˜(๋ฒ„๋ฆผ) */
int fp_to_int(int x) {
    return x / F;
}

/* FP์˜ ๋ง์…ˆ */
int add_fp(int x, int y) {
    return x + y;
}

/* FP์™€ int์˜ ๋ง์…ˆ */
int add_mixed(int x, int n) {
    return x + n * F;
}

/* FP์˜ ๋บ„์…ˆ(x-y) */
int sub_fp(int x, int y) {
    return x - y;
}

/* FP์™€ int์˜ ๋บ„์…ˆ(x-n) */
int sub_mixed(int x, int n) {
    return x - n * F;
}

/* FP์˜ ๊ณฑ์…ˆ */
int mult_fp(int x, int y) {
    return ((int64_t)x) * y / F;
}

/* FP์™€ int์˜ ๊ณฑ์…ˆ */
int mult_mixed(int x, int n) {
    return x * n;
}

/* FP์˜ ๋‚˜๋ˆ—์…ˆ(x/y) */
int div_fp(int x, int y) {
    return ((int64_t)x) * F / y;
}

/* FP์™€ int ๋‚˜๋ˆ—์…ˆ(x/n) */
int div_mixed(int x, int n) {
    return x / n;
}

fixed_point.h ์ธํด๋ฃจ๋“œ, ์Šค์ผ€์ค„๋Ÿฌ ๊ด€๋ จ ์ƒ์ˆ˜ ์ •์˜, ๋ณ€์ˆ˜ ์„ ์–ธ ๋ฐ ์ดˆ๊ธฐํ™”

  • threads/thread.c
#include "threads/synch.h"
#include "threads/vaddr.h"
#include "intrinsic.h"
#include "threads/fixed_point.h" /** project1-Advanced Scheduler */
#ifdef USERPROG
#include "userprog/process.h"
#endif
.
.
.
bool thread_mlfqs;

/** project1-Advanced Scheduler */
int load_avg;
.
.
.	struct semaphore idle_started;
	sema_init (&idle_started, 0);
	thread_create ("idle", PRI_MIN, idle, &idle_started);

	/** project1-Advanced Scheduler */
	load_avg = LOAD_AVG_DEFAULT;

	/* Start preemptive thread scheduling. */
	intr_enable ();

mlfqs_priority() ํ•จ์ˆ˜ ๊ตฌํ˜„

  • threads/thread.c

    recent_cpu์™€ nice๊ฐ’์„ ์ด์šฉํ•˜์—ฌ priority๋ฅผ ๊ณ„์‚ฐ

/** project1-Advanced Scheduler */
void 
mlfqs_priority (struct thread *t) 
{
    if (t == idle_thread)
        return;

    t->priority = fp_to_int(add_mixed(div_mixed(t->recent_cpu, -4), PRI_MAX - t->niceness * 2));
}

mlfqs_recent_cpu() ํ•จ์ˆ˜ ๊ตฌํ˜„

  • threads/thread.c

    recent_cpu ๊ฐ’ ๊ณ„์‚ฐ

/** project1-Advanced Scheduler */
void 
mlfqs_recent_cpu (struct thread *t) 
{
    if (t == idle_thread)
        return;

    t->recent_cpu = add_mixed(mult_fp(div_fp(mult_mixed(load_avg, 2), add_mixed(mult_mixed(load_avg, 2), 1)), t->recent_cpu), t->niceness);
}

mlfqs_load_avg() ํ•จ์ˆ˜ ๊ตฌํ˜„

  • threads/thread.c

    load_avg ๊ฐ’ ๊ณ„์‚ฐ

/** project1-Advanced Scheduler */
void 
mlfqs_load_avg (void) 
{
    int ready_threads;

    ready_threads = list_size(&ready_list);

    if (thread_current() != idle_thread)
        ready_threads++;

    load_avg = add_fp(mult_fp(div_fp(int_to_fp(59), int_to_fp(60)), load_avg), mult_mixed(div_fp(int_to_fp(1), int_to_fp(60)), ready_threads));
}

mlfqs_increment() ํ•จ์ˆ˜ ๊ตฌํ˜„

  • threads/thread.c

    recent_cpu ๊ฐ’ 1์ฆ๊ฐ€

/** project1-Advanced Scheduler */
void 
mlfqs_increment (void) 
{
    if (thread_current() == idle_thread)
        return;

    thread_current()->recent_cpu = add_mixed(thread_current()->recent_cpu, 1);
}

mlfqs_recal() ํ•จ์ˆ˜ ๊ตฌํ˜„

  • threads/thread.c

    ๋ชจ๋“  thread์˜ recent_cpu์™€ priority๊ฐ’ ์žฌ๊ณ„์‚ฐ

/** project1-Advanced Scheduler */
void 
mlfqs_recalc_recent_cpu (void) 
{
    struct list_elem *e = list_begin(&all_list);
    struct thread *t = NULL;

    while (e != list_end(&all_list)) {
        t = list_entry(e, struct thread, all_elem);
        mlfqs_recent_cpu(t);

        e = list_next(e);
    }
}

/** project1-Advanced Scheduler */
void mlfqs_recalc_priority (void) 
{
    struct list_elem *e = list_begin(&all_list);
    struct thread *t = NULL;

    while (e != list_end(&all_list)) {
        t = list_entry(e, struct thread, all_elem);
        mlfqs_priority(t);

        e = list_next(e);
    }
}

thread_set_priority() ํ•จ์ˆ˜ ์ˆ˜์ •

  • threads/thread.c
    • mlfqs ์Šค์ผ€์ค„๋Ÿฌ๋ฅผ ํ™œ์„ฑ ํ•˜๋ฉด thread_mlfqs ๋ณ€์ˆ˜๋Š” ture๋กœ ์„ค์ •๋œ๋‹ค.
    • Advanced scheduler์—์„œ๋Š” ์šฐ์„ ์ˆœ์œ„๋ฅผ ์ž„์˜๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋‹ค.
void
thread_set_priority (int new_priority) {

	/** project1-Advanced Scheduler */
	if (thread_mlfqs)
        return;

	/** project1-Priority Inversion Problem */
    thread_current()->original_priority = new_priority;

thread_set_nice() ํ•จ์ˆ˜ ๊ตฌํ˜„

  • threads/thread.c

    ํ˜„์žฌ thread์˜ nice๊ฐ’์„ nice๋กœ ์„ค์ •

void
thread_set_nice (int nice UNUSED) {
	/* TODO: Your implementation goes here */
	/** project1-Advanced Scheduler */
    struct thread *t = thread_current();

    enum intr_level old_level = intr_disable();
    t->niceness = nice;
    mlfqs_priority(t);
    test_max_priority();
    intr_set_level(old_level);
}

thread_get_nice() ํ•จ์ˆ˜ ๊ตฌํ˜„

  • threads/thread.c

    ํ˜„์žฌ thread์˜ nice ๊ฐ’ ๋ฐ˜ํ™˜

int
thread_get_nice (void) {
	/* TODO: Your implementation goes here */
	return 0;
	/** project1-Advanced Scheduler */
    struct thread *t = thread_current();

    enum intr_level old_level = intr_disable();
    int nice = t->niceness;
    intr_set_level(old_level);

    return nice;
}

thread_get_load_avg() ํ•จ์ˆ˜ ๊ตฌํ˜„

  • threads/thread.c

    load_avg์— 100์„ ๊ณฑํ•ด์„œ ๋ฐ˜ํ™˜

int
thread_get_load_avg (void) {
	/* TODO: Your implementation goes here */
	return 0;
	/** project1-Advanced Scheduler */
    enum intr_level old_level = intr_disable();
    int load_avg_val = fp_to_int_round(mult_mixed(load_avg, 100));  
    intr_set_level(old_level);

    return load_avg_val;
}

thread_get_recent_cpu() ํ•จ์ˆ˜ ๊ตฌํ˜„

  • threads/thread.c

    recent_cpu์— 100์„ ๊ณฑํ•ด์„œ ๋ฐ˜ํ™˜

int
thread_get_recent_cpu (void) {
	/* TODO: Your implementation goes here */
	return 0;
	/** project1-Advanced Scheduler */
    struct thread *t = thread_current();

    enum intr_level old_level = intr_disable();
    int recent_cpu = fp_to_int_round(mult_mixed(t->recent_cpu, 100)); 
    intr_set_level(old_level);

    return recent_cpu;
}

timer_interrupt() ํ•จ์ˆ˜ ์ˆ˜์ •

devices/timer.c

  • 1์ดˆ ๋งˆ๋‹ค load_avg, ๋ชจ๋“  ์Šค๋ ˆ๋“œ์˜ recent_cpu, priority ์žฌ๊ณ„์‚ฐ
  • 4tick ๋งˆ๋‹ค ํ˜„์žฌ ์Šค๋ ˆ๋“œ์˜ priority ์žฌ๊ณ„์‚ฐ
static void
timer_interrupt (struct intr_frame *args UNUSED) {
	ticks++;
	thread_tick ();

	if (thread_mlfqs) 
	{
		mlfqs_increment();

		if (!(ticks % 4)) 
		{
			mlfqs_recalc_priority();

			if (!(ticks % TIMER_FREQ)) 
			{
				mlfqs_load_avg();
				mlfqs_recalc_recent_cpu();
			}
		}
    }

	/** project1-Alarm Clock */
	if (get_next_tick_to_awake() <= ticks)
	{
	thread_awake(ticks);
	}
}

lock_acquire() ํ•จ์ˆ˜ ์ˆ˜์ •

threads/synch.c

mlfqs ์Šค์ผ€์ค„๋Ÿฌ ํ™œ์„ฑํ™”์‹œ priority donation ๊ด€๋ จ ์ฝ”๋“œ ๋น„ํ™œ์„ฑํ™”

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

/* project1-Priority Inversion Problem /
struct thread *t = thread_current();
if (lock->holder != NULL) {
t->wait_lock = lock;
list_push_back(&lock->holder->donations, &t->donation_elem);
donate_priority();
}

sema_down (&lock->semaphore);

/* project1-Priority Inversion Problem /
t->wait_lock = NULL;
lock->holder = t;
}


### lock_release() ํ•จ์ˆ˜ ์ˆ˜์ •
threads/synch.c
>  mlfqs ์Šค์ผ€์ค„๋Ÿฌ ํ™œ์„ฑํ™”์‹œ priority donation ๊ด€๋ จ ์ฝ”๋“œ ๋น„ํ™œ์„ฑํ™” 

```c
void
lock_release (struct lock *lock) {
	ASSERT (lock != NULL);
	ASSERT (lock_held_by_current_thread (lock));

	lock->holder = NULL;

   /** project1-Priority Inversion Problem */
   remove_with_lock(lock);
   refresh_priority();

	sema_up (&lock->semaphore);
}

thread_exit() ํ•จ์ˆ˜ ์ˆ˜์ •

threads/thread.c

์Šค๋ ˆ๋“œ ์ข…๋ฃŒ ์‹œ all_list์—์„œ ์ œ๊ฑฐ

void
thread_exit (void) {
	ASSERT (!intr_context ());

#ifdef USERPROG
	process_exit ();
#endif
	/** project1-Advanced Scheduler */
	if (thread_mlfqs)
        list_remove(&thread_current()->all_elem);
	/* Just set our status to dying and schedule another process.
	   We will be destroyed during the call to schedule_tail(). */
	intr_disable ();
	do_schedule (THREAD_DYING);
	NOT_REACHED ();
}

ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

์ฐธ๊ณ 

profile
Sunny Day!

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

comment-user-thumbnail
2024๋…„ 5์›” 3์ผ

good ~ ๐Ÿ˜ฎ

1๊ฐœ์˜ ๋‹ต๊ธ€
comment-user-thumbnail
2024๋…„ 5์›” 3์ผ

์™€์šฐ ์ง์ง์ง ๐Ÿ‘

1๊ฐœ์˜ ๋‹ต๊ธ€
comment-user-thumbnail
2024๋…„ 9์›” 4์ผ

์‹ค๋ก€์ง€๋งŒ MLFQS๋ž‘ KEYWORD์— ์ € ๋””์ž์ธ ์–ด๋–ค ๊ฑธ๋กœ ์ œ์ž‘ํ•˜์‹ ๊ฑด์ง€ ์—ฌ์ญค๋ด๋„๋ ๊นŒ์š”?๋„ˆ๋ฌด ์ž˜ ๋งŒ๋“œ์…”์„œ ์ €๋„ ๋งŒ๋“œ์‹ ๊ฑธ๋กœ ์ œ์ž‘ํ•˜๊ณ ์‹ถ์–ด์„œ ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค~

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