일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- 백준 18352번
- 위상 정렬(Topology Sort)
- 백준 2812번
- DFS
- 다익스트라 알고리즘(Dijkstra Algorithm)
- BFS
- 이분 탐색(Binary Search)
- 백준 2493번
- 백준 9012번
- BFS(Breadth First Search)
- 그리디 알고리즘(Greedy Algorithm)
- 백준 21606번
- 백준 2504번
- 백준 2261번
- DFS(Depth First Search)
- 스택(Stack)
- DFS & BFS
- 큐(Queue)
- 트리(Tree)
- 분할 정복(Divide and Conquer)
- 백준 10000번
- 백준 1948번
- 백준 17608번
- 위상 정렬(Topological Sort)
- 이분 그래프(Bipartite Graph)
- 플로이드 워셜 알고리즘(Floyd-Warshall Algorithm)
- 백준 1707번
- 동적 프로그래밍(Dynamic Programming)
- 알고리즘 개념
- 그래프(Graph)
- Today
- Total
Always Be Wise
Project_1 : Threads - Priority Scheduling(2) 본문
이제부터 본격적으로 Priority Scheduling을 구현해보도록 하겠다.
가장 먼저 우선순위가 가장 높은 스레드가 CPU를 점유할 수 있도록 만들어야 한다.
이를 위해 ready_list 관련 함수들을 수정하고자 한다. ready_list는 CPU를 사용하고자 대기하고 있는 스레드들을 관리하는 리스트이다.
해당 리스트에서 스레드를 꺼낼 때 우선순위가 가장 높은 스레드를 꺼낼 수 있다면 상기의 목적을 달성할 수 있다.
이를 손쉽게 가능하게 하는 방법은 ready_list를 우선순위 기준으로 내림차순 정렬하는 것이다.
따라서 ready_list에 새로운 스레드를 넣을 때, 우선순위를 고려하고자 한다.
우선순위를 고려하여 ready_list에 스레드를 넣는다면, 리스트는 항상 정렬된 상태를 유지할 수 있게 된다.
또한, ready_list에서 스레드 꺼내는 방식을 추가로 수정하지 않더라도 항상 우선순위가 높은 스레드를 꺼낼 수 있게 된다.
삽입 과정에서 list_insert_ordered( ) 함수를 이용하고자 한다.
해당 함수는 Pintos에서 리스트를 다루기 위해 미리 구현된 함수이다.
list_insert_ordered( ) 함수의 인자로는 스레드를 넣을 리스트와, 넣고자 하는 스레드, 삽입시 기준이 될 함수가 들어간다.
해당 함수의 내부를 살펴보면 list_insert( ) 함수를 호출하는 것을 알 수 있다.
그리고 list_insert( ) 함수의 결과, 두 번째 인자에 해당하는 스레드가첫 번째 인자에 해당하는 스레드 앞에 위치하게 된다.
그런데 앞서 ready_list는 우선순위가 높은 순으로 정렬되어 있어야 한다고 하였다.
따라서 list_insert_ordered( ) 함수 내부의 less( ) 함수는 아래와 같이 elem > e 일 때 true를 반환하는 함수여야 한다.
/* threads/thread.c */
/* PROJECT1: THREADS - Priority Scheduling */
bool thread_compare_priority (struct list_elem *l, struct list_elem *s, void *aux UNUSED) {
return list_entry (l, struct thread, elem)->priority > list_entry (s, struct thread, elem)->priority;
}
이제 이 내용을 바탕으로 ready_list에 스레드를 삽입하는 과정을 수정하고자 한다.
아래 thread_yield( ) 함수와, thread_unblock( ) 함수 코드에서 list_push_back( ) 함수를 주석 처리하였다.
그리고 새롭게 list_insert_orered( ) 함수를 넣어주었다.
/* threads/thread.c */
/* PROJECT1: THREADS - Priority Scheduling */
void thread_yield (void) {
struct thread *curr = thread_current ();
enum intr_level old_level;
ASSERT (!intr_context ());
old_level = intr_disable ();
if (curr != idle_thread)
// list_push_back (&ready_list, &curr->elem);
list_insert_ordered(&ready_list, &curr->elem, thread_compare_priority, 0);
do_schedule (THREAD_READY);
intr_set_level (old_level);
}
void thread_unblock (struct thread *t) {
enum intr_level old_level;
ASSERT (is_thread (t));
old_level = intr_disable ();
ASSERT (t->status == THREAD_BLOCKED);
// list_push_back (&ready_list, &t->elem);
list_insert_ordered(&ready_list, &t->elem, thread_compare_priority, 0);
t->status = THREAD_READY;
intr_set_level (old_level);
}
그런데 추가적으로 고려해야 할 사항이 있다.
새롭게 ready_list에 삽입된 스레드의 우선순위가 현재 CPU를 점유하고 있는 스레드의 우선순위보다 높다면 CPU 점유를 넘겨야 한다.
이를 위해 ready_list의 맨 앞 스레드의 우선순위와 현재 CPU를 점유하고 있는 스레드의 우선순위를 비교하는 함수를 만들었다.
그리고 이를 thread_create( )와 thread_set_priority( ) 함수에 추가해주었다.
/* threads/thread.c */
/* PROJECT1: THREADS - Priority Scheduling */
void thread_test_preemption (void){
if (!list_empty (&ready_list) &&
thread_current ()->priority <
list_entry (list_front (&ready_list), struct thread, elem)->priority)
thread_yield ();
}
tid_t thread_create (const char *name, int priority, thread_func *function, void *aux) {
struct thread *t;
tid_t tid;
ASSERT (function != NULL);
/* Allocate thread. */
t = palloc_get_page (PAL_ZERO);
if (t == NULL)
return TID_ERROR;
/* Initialize thread. */
init_thread (t, name, priority);
tid = t->tid = allocate_tid ();
/* Call the kernel_thread if it scheduled.
* Note) rdi is 1st argument, and rsi is 2nd argument. */
t->tf.rip = (uintptr_t) kernel_thread;
t->tf.R.rdi = (uint64_t) function;
t->tf.R.rsi = (uint64_t) aux;
t->tf.ds = SEL_KDSEG;
t->tf.es = SEL_KDSEG;
t->tf.ss = SEL_KDSEG;
t->tf.cs = SEL_KCSEG;
t->tf.eflags = FLAG_IF;
/* Add to run queue. */
thread_unblock (t);
thread_test_preemption();
return tid;
}
void thread_set_priority (int new_priority) {
thread_current ()->priority = new_priority;
thread_test_preemption();
}
지금까지의 과정을 통해 우선순위가 가장 높은 스레드가 CPU를 점유할 수 있게 되었다.
터미널의 다음과 같이 입력하면 결과를 확인할 수 있다.
'카이스트 정글 - 프로젝트 > Pintos' 카테고리의 다른 글
Project_1 : Threads - Priority Scheduling(4) (0) | 2021.12.29 |
---|---|
Project_1 : Threads - Priority Scheduling(3) (0) | 2021.12.28 |
Project_1 : Threads - Priority Scheduling(1) (0) | 2021.12.26 |
Project_1 : Threads - Alarm Clock (0) | 2021.12.26 |
Project_1 : Threads - Introduction (0) | 2021.12.26 |