Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
Tags
- JavaScript
- Java
- 시스템콜
- 사이드프로젝트
- Flutter
- HTML
- 백준
- 자바스크립트
- 소켓
- userprog
- 4기
- 오블완
- 알고리즘
- 크래프톤정글
- CSS
- 스택
- 리액트
- Vue.js
- TiL
- 코드트리
- 핀토스
- corou
- 자바
- 모션비트
- 큐
- 크래프톤 정글
- defee
- 나만무
- 티스토리챌린지
- pintos
Archives
- Today
- Total
미새문지
pintOS - project1(Thread) synch.c 본문
728x90
synch.c
< sema_init >
더보기
// 세마포어 초기화
void
sema_init (struct semaphore *sema, unsigned value) {
ASSERT (sema != NULL); // 세마포어가 없으면 종료
sema->value = value; // 해당 세마포어의 value값을 인자의 value로 저장
list_init (&sema->waiters); // 해당 세마포어의 대기자를 매개로 list 초기화
}
< sema_down >
더보기
// 세마 감소(스레드 잠금 획득)
void
sema_down (struct semaphore *sema) {
enum intr_level old_level;
ASSERT (sema != NULL);
ASSERT (!intr_context ());
old_level = intr_disable (); // 인터럽트를 비활성화
// 세마포어의 값이 0이 아닐 때까지 반복
while (sema->value == 0) {
// 세마포어의 대기자에 우선도 위주로 정렬해 현재 스레드의 elem을 삽입
list_insert_ordered(&sema->waiters, &thread_current()->elem, sema_priority, NULL);
// 스레드를 블럭(언블락될 때까지 대기)
thread_block ();
}
thread_current()->has_lock += 1; // 현재 스레드의 lock을 1증가
sema->value--; // 세마포어 값을 감소
intr_set_level (old_level); // 인터럽트를 다시 복원
}
< sema_up >
더보기
// 세마 증가(스레드 잠금 해제)
void
sema_up (struct semaphore *sema) {
enum intr_level old_level;
struct thread *sema_top_priority;
ASSERT (sema != NULL);
old_level = intr_disable (); // 인터럽트를 비활성화
// 세마포어의 대기자가 있다면
if (!list_empty (&sema->waiters))
{
// 대기자를 우선도로 정렬
list_sort(&sema->waiters, sema_priority, NULL);
// 세마포어 대기자의 맨 앞 스레드를 저장(우선도가 가장 높음)
sema_top_priority = list_entry(list_pop_front(&sema->waiters),
struct thread, elem);
// 스레드를 언블락
thread_unblock (sema_top_priority);
}
thread_current()->has_lock -= 1; // 현재 스레드의 lock을 1감소
sema->value++; // 세마포어 값을 증가
intr_set_level (old_level); // 인터럽트를 다시 복원
thread_yield(); // 실행중인 스레드와 대기자 스레드 교체
}
< lock_init >
더보기
// lock 초기화
void
lock_init (struct lock *lock) {
ASSERT (lock != NULL); // lock이 없으면 종료
lock->holder = NULL; // lock의 홀더를 NULL로 초기화
sema_init (&lock->semaphore, 1); // lock의 세마포어에 1로 초기화
}
< lock_acquire >
더보기
// lock을 획득
void
lock_acquire (struct lock *lock) {
ASSERT (lock != NULL); // lock이 없으면 종료
ASSERT (!intr_context ()); // 인터럽트가 실행중이면 종료
ASSERT (!lock_held_by_current_thread (lock)); // 현재 스레드가 lock을 보유중이면 종료
struct thread *lock_holder;
struct thread *now = thread_current();
if (lock->holder != NULL) // lock 홀더가 존재하면
{
lock_holder = lock->holder; // lock_holder에 lock의 홀더 저장
now->wait_on_lock = lock; // 현재 스레드의 대기 중인 lock에 lock을 저장
// 현재 스레드의 우선도가 lock_holder의 우선도보다 크면
if (now->priority> lock_holder->priority)
{
// lock_holder의 기부자에 삽입 후 현재 스레드부터 재귀
list_insert_ordered(&lock_holder->donors, &now->donor_elem, lock_priority, NULL);
donate_recursion(now);
}
}
sema_down (&lock->semaphore); // lock의 세마포어를 매개변수로 세마를 감소
thread_current()->wait_on_lock = NULL; // 현재 스레드의 대기중인 lock을 초기화
lock->holder = thread_current (); // lock의 홀더에 현재 스레드 저장
}
< lock_release >
더보기
// lock을 해제
void
lock_release (struct lock *lock) {
ASSERT (lock != NULL); // lock이 없으면 종료
ASSERT (lock_held_by_current_thread (lock)); // 현재 스레드가 lock이 없으면 종료
if (!list_empty(&lock->holder->donors)){ // 기부자 리스트에 스레드가 존재하면
struct list_elem *element;
element = list_front(&lock->holder->donors);
// 요소가 빌 때까지 반복
while(element != NULL){
struct thread *t = list_entry(element, struct thread, donor_elem);
// 스레드가 기다리고 있는 lock이 인자 lock과 같다면 리스트에서 제거
if (t->wait_on_lock == lock){
list_remove(element);
}
element = element->next; // 요소를 다음으로 변경
if (element->next == NULL){ // 다음 요소가 없다면 탈출
break;
}
}
}
// 현재 스레드의 기부자 리스트에 스레드가 있다면
if (!list_empty(&thread_current()->donors))
{
// 기부자 리스트의 맨 앞 스레드를 가져와서 그 스레드의 우선도를 현재 스레드 우선도에 저장
struct thread* foremost_thread = list_entry(list_front(&thread_current()->donors), struct thread, donor_elem);
thread_current()->priority = foremost_thread->priority;
}
// 기부자 리스트가 없으면
else {
// 현재 스레드의 원래 우선도를 우선도에 저장
thread_current()->priority = thread_current()->original_priority;
}
// lock을 소유중인 스레드와 현재 스레드가 기다리고 있는 lock을 초기화한다.
lock->holder = NULL;
thread_current()->wait_on_lock = NULL;
// lock의 세마포어를 증가시킨다.
sema_up (&lock->semaphore);
}
< lock_held_by_current_thread >
더보기
// 현재 스레드가 lock을 보유하고 있는지 확인
bool
lock_held_by_current_thread (const struct lock *lock) {
ASSERT (lock != NULL); // lock이 없으면 종료
// lock을 가진 스레드가 현재 스레드면 true 아니면 false
return lock->holder == thread_current ();
}
< donate_recursion >
더보기
// nest나 chain에 쓰일 기부 함수 재귀 적용
void donate_recursion(struct thread *t){
// t의 우선도가 t의 wait_on_lock의 holder의 우선도보다 크면
if(t->priority > t->wait_on_lock->holder->priority)
// t의 wait_on_lock의 holder의 우선도에 t의 우선도를 넣는다.
t->wait_on_lock->holder->priority = t->priority;
// // t의 wait_on_lock의 holder의 wait_on_lock이 존재하면
if(t->wait_on_lock->holder->wait_on_lock != NULL){
// holder를 스레드 매개변수로 재귀
donate_recursion(t->wait_on_lock->holder);
}
}
< cond_wait >
더보기
// 특정 조건이 충족될 때까지 대기
void
cond_wait (struct condition *cond, struct lock *lock) {
// 특정 조건을 기다리는 스레드
struct semaphore_elem waiter;
// 특정 조건을 기다리는 스레드의 우선도
waiter.sema_priority = NULL;
ASSERT (cond != NULL);
ASSERT (lock != NULL);
ASSERT (!intr_context ());
ASSERT (lock_held_by_current_thread (lock));
sema_init (&waiter.semaphore, 0); // 기다리는 스레드의 세마포어 초기화
// 스레드의 우선도를 현재 스레드의 우선도로 넣기
waiter.sema_priority = thread_current()->priority;
// 특정조건을 기다리는 스레드 리스트에 우선도로 정렬하여 스레드 삽입
list_insert_ordered (&cond->waiters, &waiter.elem, sema_elem_priority, NULL);
lock_release (lock); // lock을 해제
sema_down (&waiter.semaphore); // 세마포어 감소
lock_acquire (lock); // lock을 획득
}
< cond_signal >
더보기
// 조건 변수를 기다리는 스레드를 깨워 실행
void
cond_signal (struct condition *cond, struct lock *lock UNUSED) {
ASSERT (cond != NULL);
ASSERT (lock != NULL);
ASSERT (!intr_context ());
ASSERT (lock_held_by_current_thread (lock));
// 조건 변수를 기다리는 리스트에 스레드가 존재하면
if (!list_empty (&cond->waiters))
// 리스트의 맨 앞 스레드의 세마포어를 증가시킨다.
sema_up (&list_entry (list_pop_front (&cond->waiters),
struct semaphore_elem, elem)->semaphore);
}
< cond_broadcast >
더보기
// 조건 변수를 기다리는 모든 스레드를 깨운다.
void
cond_broadcast (struct condition *cond, struct lock *lock) {
ASSERT (cond != NULL);
ASSERT (lock != NULL);
// 조건 변수를 기다리는 리스트가 빌 때까지
while (!list_empty (&cond->waiters))
// 스레드를 깨워 실행시킨다.
cond_signal (cond, lock);
}
728x90
'크래프톤 정글 > pintOS' 카테고리의 다른 글
pintOS - project2(Userprog) syscall.c (3) | 2024.03.29 |
---|---|
pintOS - Project 2 Userprog WIL (2) | 2024.03.23 |
pintOS - project1(Thread) thread.c - mlfqs (3) | 2024.03.11 |
pintOS - project1(Thread) thread.c (1) | 2024.03.11 |
pintOS - Project 1 Thread WIL (1) | 2024.03.11 |