include/threads/thread.h
정답
struct thread
{
...
int init_priority;
struct lock *wait_on_lock;
struct list donations;
struct list_elem donation_elem;
...
};
구현 = 최종코드
struct thread
{
/* Owned by thread.c. */
tid_t tid; /* Thread identifier. */
enum thread_status status; /* Thread state. */
char name[16]; /* Name (for debugging purposes). */
int priority; /* Priority. */
/* Shared between thread.c and synch.c. */
struct list_elem elem; /* List element. */
/*----------------[project1]-------------------*/
/* local tick */
int64_t wake_up_tick;
/* priority donaion 관련 element 추가 */
int init_priority; // donation이후 우선순위를 초기화하기 위해 초기값 저장
struct lock *wait_on_lock; // 해당 스레드가 대기하고 있는 lock자료구조 주소 저장
struct list donations; // multiple donation 을 고려하기 위해사용
struct list_elem donation_elem; // multiple donation 을 고려하기 위해사용
/*----------------[project1]-------------------*/
#ifdef USERPROG
/* Owned by userprog/process.c. */
uint64_t *pml4; /* Page map level 4 */
#endif
#ifdef VM
/* Table for whole virtual memory owned by thread. */
struct supplemental_page_table spt;
#endif
/* Owned by thread.c. */
struct intr_frame tf; /* Information for switching */
unsigned magic; /* Detects stack overflow. */
};
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);
...
}
구현 = 최종코드
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 *);
t->priority = priority;
t->magic = THREAD_MAGIC;
/*----------------[project1]-------------------*/
t->init_priority = priority;
t->wait_on_lock = NULL;
list_init(&t->donations);
/*----------------[project1]-------------------*/
}
threads/synch.c
default
void
lock_acquire (struct lock *lock)
{
ASSERT (lock != NULL);
ASSERT (!intr_context ());
ASSERT (!lock_held_by_current_thread (lock));
sema_down (&lock->semaphore);
lock->holder = thread_current ();
}
정답
void
lock_acquire (struct lock *lock)
{
ASSERT (lock != NULL);
ASSERT (!intr_context ());
ASSERT (!lock_held_by_current_thread (lock));
struct thread *cur = thread_current ();
if (lock->holder) {
cur->wait_on_lock = lock;
list_insert_ordered (&lock->holder->donations, &cur->donation_elem,
thread_compare_donate_priority, 0);
donate_priority ();
}
sema_down (&lock->semaphore);
cur->wait_on_lock = NULL;
lock->holder = cur;
}
구현1
void lock_acquire(struct lock *lock)
{
ASSERT(lock != NULL);
ASSERT(!intr_context());
ASSERT(!lock_held_by_current_thread(lock));
if (lock->holder) //lock->holder가 있다면,
{
struct thread *cur_t = thread_current();
cur_t->wait_on_lock = &lock; //내가 필요한 lock을 기록
cur_t->init_priority = cur_t->priority; //donation받기 전, 내 원래 priority기록
donate_priority(); //도네이션 해서 lock빨리써서 내놔라.
}
sema_down(&lock->semaphore); // lock쓰기
thread_current()->wait_on_lock = NULL; //기다리는 lock없으므로 wait_on_lock 초기화
lock->holder = thread_current(); // 현재 thread가 lock->holder가 되는 것
}
차이: donate_priority()함수에서 list_insert_ordered()를 사용
최종코드
void lock_acquire(struct lock *lock)
{
ASSERT(lock != NULL);
ASSERT(!intr_context());
ASSERT(!lock_held_by_current_thread(lock));
struct thread *cur_t = thread_current();
if (lock->holder != NULL)
{
cur_t->wait_on_lock = lock;
// cur_t->init_priority = cur_t->priority; 🤔
list_insert_ordered(&lock->holder->donations, &cur_t->donation_elem,
donate_priority_less, 0); // 추가 🤔
donate_priority();
}
sema_down(&lock->semaphore);
cur_t->wait_on_lock = NULL;
lock->holder = thread_current();
}
thread/thread.c
정답
bool
thread_compare_donate_priority (const struct list_elem *l,
const struct list_elem *s, void *aux UNUSED)
{
return list_entry (l, struct thread, donation_elem)->priority
> list_entry (s, struct thread, donation_elem)->priority;
}
구현1
다른 함수에서 비교하긴 했으나, 이전에 구현한 priority_less함수 사용.