๐ฉ๐ปโ๐ป GITHUB ๋ ํฌ์งํ ๋ฆฌ
๐ฉ๐ปโ๐ป GITHUB Priority Donation ์ด์
Priority Inverstion Problem์ thread๊ฐ ๋ ๊ฐ ์ด์์ lock๋ณด์ ๊ฐ๋ฅํ ๋, ๋์ priority์ thread๊ฐ ๋ฎ์ priority์ thread๋ณด๋ค ๋ฆ๊ฒ ์คํ๋ ์ ์๋ ๋ฌธ์ ์ ์ ๋งํ๋ค.
โ๏ธ ์์ธํ Priority Inversion Problem ์ค๋ช ํ์ธํ๊ธฐ
๊ฐ๋จํ๊ฒ ์ค๋ช
ํ์๋ฉด,
H (high), M (medium), L (low) ๋ผ๋ ์ธ ๊ฐ์ ์ค๋ ๋๊ฐ ์๊ณ ๊ฐ๊ฐ์ ์ฐ์ ์์๋ H > M > L ์ด๋ค. H ๊ฐ L ์ ๊ธฐ๋ค๋ ค์ผ ํ๋ ์ํฉ(์๋ฅผ ๋ค์ด, H ๊ฐ lock ์ ์์ฒญํ๋๋ฐ ์ด lock ์ L ์ด ์ ์ ํ๊ณ ์๋ ๊ฒฝ์ฐ)์ด ์๊ธด๋ค๋ฉด H ๊ฐ L ์๊ฒ CPU ์ ์ ๋ฅผ ๋๊ฒจ์ฃผ๋ฉด M ์ด L ๋ณด๋ค ์ฐ์ ์์๊ฐ ๋์ผ๋ฏ๋ก ์ ์ ๊ถ์ ์ ์ ํ์ฌ ์คํ๋์ด์ ์ค๋ ๋๊ฐ ๋ง๋ฌด๋ฆฌ ๋๋ ์์๊ฐ M->L->H ๊ฐ ๋๋ค. ๋ฐ๋ผ์ M ์ด ๋ ๋์ ์ฐ์ ์์๋ฅผ ๊ฐ์ง H ๋ณด๋ค ์ฐ์ ํ์ฌ ์คํ๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด priority donation์ ๊ตฌํํ์ฌ์ผ ํ๋ค.
priority donation ์ด๋ ์์ ์ํฉ์์ H ๊ฐ ์์ ์ด ๊ฐ์ง priority ๋ฅผ L ์๊ฒ ์ผ์์ ์ผ๋ก ์๋ํ์ฌ์ H ์์ ์ ์คํ์ ์ํด L ์ด ์์ ๊ณผ ๋์ผํ ์ฐ์ ์์๋ฅผ ๊ฐ์ ธ์ ์ฐ์ ์ ์ผ๋ก ์คํ๋ ์ ์๋๋ก ๋ง๋๋ ๋ฐฉ๋ฒ์ด๋ค.
ํํ ์ค documents ์์๋ priority donation ์ด ์ผ์ด๋ ์ ์๋ ๋ชจ๋ ์ํฉ์ ๊ณ ๋ คํด์ผ ํ๋ค๊ณ ํ๋ฉด์ Multiple donation, Nested donation ๋ ๊ฐ์ง๋ฅผ ์ธ๊ธํ๋ค.
void lock_acquire (struct lock *lock)
: lock์ ์ ์ ํ๊ณ ์๋ ์ค๋ ๋์ ์์ฒญ ํ๋ ์ค๋ ๋์ ์ฐ์ ์์๋ฅผ ๋น๊ตํ์ฌ priority donation์ ์ํํ๋๋ก ์์ void lock_release (struct lock *lock)
: donation list ์์ ์ค๋ ๋๋ฅผ ์ ๊ฑฐํ๊ณ ์ฐ์ ์์๋ฅผ ๋ค์ ๊ณ์ฐํ๋๋ก remove_with_lock()
, refresh_prioriy()
ํจ์๋ฅผ ํธ์ถvoid thread_set_priority (int new_priority)
: ์ค๋ ๋ ์ฐ์ ์์ ๋ณ๊ฒฝ์ donation์ ๋ฐ์์ ํ์ธ ํ๊ณ ์ฐ์ ์์ ๋ณ๊ฒฝ์ ์ํด donation_priority()
ํจ์ ์ถ๊ฐvoid donate_priority(void)
: priority donation์ ์ํ void remove_with_lock(struct lock *lock)
: donation list์์ ์ค๋ ๋ ์ํธ๋ฆฌ๋ฅผ ์ ๊ฑฐ void refresh_priority(void)
: ์ฐ์ ์์๋ฅผ ๋ค์ ๊ณ์ฐ ๋์ ์์ ์ค
Source ./activate
์์น๊ฒ ํ๋๋ฒ!!
๋ฃจํธ ๋๋ ํ ๋ฆฌ๋ก ์ด๋
code .bashrc
์
๋ ฅ
ํ์ผ ์ ์ผ ๋ฐ์ ๋ณธ์ธ์ source activate ๊ฒฝ๋ก ์ถ๊ฐ
/pintos ๊ฒฝ๋ก์์ source ./activate
(์ฌ์ ํ๊ฒฝ ์ค์ ์ ํ๋ค๋ฉด ์ํด์ค๋ ๋๋ค!)
threads ํด๋ ๋ค์ด๊ฐ์ make clean
make check
๋ฅผ ์ํํ๋ฉด Test Case๋ค์ ๋ํด์ ์ฑ์ ์ ์ํํ๋ค.
Test Case ํ๊ฐ์ง๋ง ๋๋ฆฌ๊ณ ์ถ๋ค๋ฉด, pintos/(ํ๋ก์ ํธ๋ช
)/build์ ๋ค์ด๊ฐ์ ์๋ ๋ช
๋ น์ด๋ฅผ ์ํํ๋ฉด ๋๋ค.
pintos -T (Timout์ด ๊ฑธ๋ฆฌ๋ ์๊ฐ) -- -q -run (Test case ์ด๋ฆ)
ex) `pintos -T 30 -- -q run donate-one
- donation ์ดํ ์ฐ์ ์์๋ฅผ ์ด๊ธฐํํ๊ธฐ ์ํด ์ด๊ธฐ ์ฐ์ ์์ ๊ฐ์ ์ ์ฅํ ํ๋
- ํด๋น ์ฐ๋ ๋๊ฐ ๋๊ธฐํ๊ณ ์๋ lock ์๋ฃ๊ตฌ์กฐ์ ์ฃผ์๋ฅผ ์ ์ฅํ ํ๋
- multiple donation์ ๊ณ ๋ คํ๊ธฐ ์ํ ๋ฆฌ์คํธ ์ถ๊ฐ
- ํด๋น ๋ฆฌ์คํธ๋ฅผ ์ํ elem๋ ์ถ๊ฐ
.
.
.
/** project1-Priority Inversion Problem */
int original_priority;
struct lock *wait_lock;
struct list donations;
struct list_elem donation_elem;
.
.
.
Priority donation ๊ด๋ จ ์๋ฃ๊ตฌ์กฐ ์ด๊ธฐํ ์ฝ๋ ์ฝ์
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-Priority Inversion Problem */
t->priority = t->original_priority = priority;
list_init(&t->donations);
t->wait_lock = NULL;
t->magic = THREAD_MAGIC;
}
- ํด๋น lock์ holder๊ฐ ์กด์ฌํ์ฌ wait์ ํ๊ฒ ๋๋ฉด ์๋ ๋์์ ์ํ.
- wait์ ํ๊ฒ ๋ lock ์๋ฃ๊ตฌ์กฐ ํฌ์ธํฐ ์ ์ฅ
- ์ฐ๋ ๋ ๋์คํฌ๋ฆฝํฐ์ ์ถ๊ฐํ ํ๋
- lock์ ํ์ฌ holder์ ๋๊ธฐ์ list์ ์ถ๊ฐ
- priority donation์ ์ํํ๋ ์ฝ๋ ์ถ๊ฐ
- ๊ตฌํํ๊ฒ ๋ ํจ์์ธ
donate_priority()
- lock ํ๋ ํ lock์ holder ๊ฐฑ์
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;
}
.
.
.
/** project1-Priority Inversion Problem */
void donate_priority(void);
void remove_with_lock(struct lock *lock);
void refresh_priority(void);
.
.
.
- void donate_priority(void)
- priority donation์ ์ํํ๋ ํจ์
- Nested donation์ ๊ณ ๋ คํ์ฌ ๊ตฌํ
- ํ์ฌ ์ฐ๋ ๋๊ฐ ๊ธฐ๋ค๋ฆฌ๊ณ ์๋ lock๊ณผ ์ฐ๊ฒฐ๋ ๋ชจ๋ ์ฐ๋ ๋๋ค์ ์ํํ๋ฉฐ ํ
์ฌ ์ฐ๋ ๋์ ์ฐ์ ์์๋ฅผ lock์ ๋ณด์ ํ๊ณ ์๋ ์ฐ๋ ๋์๊ฒ ๊ธฐ๋ถ- nested depth๋ 8๋ก ์ ํ
/** project1-Priority Inversion Problem */
void
donate_priority()
{
struct thread *t = thread_current();
int priority = t->priority;
for (int depth = 0; depth < 8; depth++)
{
if (t->wait_lock == NULL)
break;
t = t->wait_lock->holder;
t->priority = priority;
}
}
- lock์ ํด์ ํ ํ, ํ์ฌ ์ฐ๋ ๋์ ๋๊ธฐ ๋ฆฌ์คํธ ๊ฐฑ์ (
remove_with_lock()
์ฌ์ฉ)- priority๋ฅผ donation ๋ฐ์์ ์ ์์ผ๋ฏ๋ก ์๋์ priorit๋ก ์ด๊ธฐํ (
refresh_priority()
์ฌ์ฉ)
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);
}
- lock์ ํด์ง ํ์ ๋, waiters ๋ฆฌ์คํธ์์ ํด๋น ์ํธ๋ฆฌ๋ฅผ ์ญ์ ํ๊ธฐ ์ํ ํจ์๋ฅผ ๊ตฌํ
- ํ์ฌ ์ฐ๋ ๋์ waiters ๋ฆฌ์คํธ๋ฅผ ํ์ธํ์ฌ ํด์งํ lock์ ๋ณด์ ํ๊ณ ์๋ ์ํธ๋ฆฌ๋ฅผ ์ญ์
/** project1-Priority Inversion Problem */
void remove_with_lock(struct lock *lock)
{
struct thread *t = thread_current();
struct list_elem *curr = list_begin(&t->donations);
struct thread *curr_thread = NULL;
while (curr != list_end(&t->donations))
{
curr_thread = list_entry(curr, struct thread, donation_elem);
if (curr_thread->wait_lock == lock)
list_remove(&curr_thread->donation_elem);
curr = list_next(curr);
}
}
- ์ค๋ ๋์ ์ฐ์ ์์๊ฐ ๋ณ๊ฒฝ ๋์์ ๋, donation์ ๊ณ ๋ คํ์ฌ ์ฐ์ ์์๋ฅผ ๋ค์ ๊ฒฐ์ ํ๋ ํจ์
- ํ์ฌ ์ฐ๋ ๋์ ์ฐ์ ์์๋ฅผ ๊ธฐ๋ถ ๋ฐ๊ธฐ ์ ์ ์ฐ์ ์์๋ก ๋ณ๊ฒฝ
- ํ์ฌ ์ฐ๋ ๋์ waiters ๋ฆฌ์คํธ์์ ๊ฐ์ฅ ๋์ ์ฐ์ ์์๋ฅผ ํ์ฌ ์ฐ๋ ๋์ ์ฐ์ ์์์ ๋น๊ต ํ ์ฐ์ ์์ ์ค์
/** project1-Priority Inversion Problem */
void refresh_priority(void)
{
struct thread *t = thread_current();
t->priority = t->original_priority;
if (list_empty(&t->donations))
return;
list_sort(&t->donations, cmp_priority, NULL);
struct list_elem *max_elem = list_front(&t->donations);
struct thread *max_thread = list_entry(max_elem, struct thread, donation_elem);
if (t->priority < max_thread->priority)
t->priority = max_thread->priority;
}
refresh_priority()
ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ฐ์ ์์์ ๋ณ๊ฒฝ์ผ๋ก ์ธํ donation ๊ด๋ จ
์ ๋ณด๋ฅผ ๊ฐฑ์donation_priority()
,test_max_priority()
ํจ์๋ฅผ ์ ์ ํ ์ฌ์ฉํ์ฌ priority
donation์ ์ํํ๊ณ ์ค์ผ์ค๋ง
void
thread_set_priority (int new_priority) {
thread_current ()->priority = new_priority;
/** project1-Priority Inversion Problem */
thread_current()->original_priority = new_priority;
/** project1-Priority Inversion Problem */
refresh_priority();
/** project1-Priority Scheduling */
test_max_priority();
}