. [PintOS, Appendix ] Threads
본문 바로가기
Pintos Project/Project 1

[PintOS, Appendix ] Threads

by 불냥이_ 2021. 1. 30.

Thread

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. */

#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. */
};

- 스레드를 위한 구조체이다.

- 스레드 구조체는 (스택) 메모리의 머리에 있다. -> 스레드는 고유한 스택을 가지고 있는데, 그 메모리의 처음 부분에 있는 것.

- 그리고 스레드의 스택은 점점 힙영역으로 커져간다.

-> struct thread가 너무 크면 커널 스택을 위한 영역이 없을 것이다. 그래서 몇 바이트 정도의 공간만 가지게 된다. (반드시 1kB 미만으로 잡아준다.)

-> 커널 스택도 너무 커지면 안된다. 커널에서 스택 오버플로우가 발생하면 스레드 상태를 변이시킬 가능성이 있다.

-> 그렇기에 커널 함수는 큰 사이즈의 structure나 non-static 지역 변수를 가지면 안된다.

-> malloc이나 palloc_get_page()같은 동적할당을 활용하라.

 

 

tid_t tid

- 스레드의 식별자이다.

- 모든 스레드는 스레드의 수명동안 고유의 식별자를 가진다.

- tid_t 는 정수이며, 새로 생기는 스레드는 다음으로 높은 숫자의 tid를 가진다. (1, 2, 3번같이 오름차순으로)

- 원하면 type이나 순서 매기는 방식을 바꿀 수 있다.

 

 

enum thread_status status;

세가지의 상태가 있다.

- THREAD_RUNNING

   ㆍ기동(running) 중.

   ㆍ오직 한 스레드가 주어진 시간동안 기동하고 있다.

   ㆍthread_current()는 현제 기동중인 스레드를 반환한다.

 

- THREAD_READY

   ㆍ스레드가 기동할 준비가 되었지만 기동하지 않는 상태

   ㆍ스케줄러에 의해 기동될 수 있다. 

   ㆍready thread는 ready_list라는 이중연결리스트 안에 보관된다.

 

- THREAD_BLOCKED

   ㆍ대기(or 일시정지) 중인 상태이다. (ready와는 다름)

   ㆍ이 스레드는 thread_unblock() 으로 상태가 THREAD_READY 로 바뀌기 전에는 스케줄에 할당되지 않는다.

   ㆍ원시적 synchronization 방법이다. 

   ㆍBlocked thread가 무엇을 기다리고 있는지 알 수 있는 방법은 없다. (하지만 backtrace가 도움이 될 수도 있다.)

 

- THREAD_DYING

   ㆍ다음 스레드가 온다면 스케줄러에 의해 사라질 스레드라는 것을 나타낸다. 

 

 

char name[16]

- 스레드의 이름이나 축약어를 기록한다.

 

 

struct intr_frame tf;

- context switching을 위해 정보를 저장한다.

- 스택 포인터나 레지스터가 담긴다.

 

 

int priority;

- 스레드의 우선순위. 0부터 63까지 있다.

- 높을수록 우선순위가 높아진다.

 

 

struct list_elem elem;

- 스레드를 이중연결 리스트에 넣기 위해서 쓰인다. 

- 이중연결리스트라 하면, ready_list (run을 위해 ready중인 스레드의 리스트), sema_down()에서 세마포어에서 waiting중인 스레드 리스트를 말한다.

- 이 두 경우에서 쓸 수 있는 이유는 세마포어에 있는 스레드는 ready상태가 될 수 없고, 반대로 ready인 스레드는 세마포어일 수가 없다. 그래서 이 두 리스트에 대해서 같은 list_elem을 사용할 수 있는 것이다.

 

 

 

uint64_t *pm14;

Project 2 이후로 쓰인다. ㅂㅇ

 

 

unsigned magic

- 스택 오버플로우를 탐지하기 위해서 사용된다.

- 스택 오버플로우가 일어나면 이 숫자가 (오버플로우때문에) 바뀌는 성질을 이용한다.

- 구조체의 말단에 배치된다.

 

 

Thread Functions

void thread_init (void);

- 스레드 시스템을 시작하기 위해 호출한다.

- 핀토스의 첫번째 스레드를 만든다.

- 뭔가 추가설명이 있는데 잘 모르겠다. 

 

void thread_start (void);

- 스케줄러를 시작하기 위해 호출한다.

- ready 상태의 스레드가 없을 때, 스케줄되는 idle thread를 만든다. 

- main()이나 intr_yield_on_return() 을 사용하는 인터럽트를 가능하게 만든다.

- 부가효과?

 

 

void thread_tick (void);

- timer tick의 timer interrupt가 호출한다.

- time slice가 만료되었을 때, 스케줄러를 가동한다.

- 스레드 통계를 가지고 있다.

 

 

void thread_print_stats (void);

- 스레드가 shutdown일 때, 호출된다.

- 스레드 통계를 출력한다.

 

 

tid_t thread_create (const char *name, int priority, thread func *func, void *aux);

- 인자name으로 스레드를 만들고 시작한다.

   ㆍ만들어진 스레드의 tid를 반환한다.

   ㆍ이 스레드는 인자func 을 실행한다.

   ㆍ인자*aux 는 func의 인자를 나타낸다.

- thread_create()는 스레드의 페이지를 할당하고, 스레드의 멤버들을 초기화하며, 스레드 스택을 할당한다.

- 스레드는 blocked state 상태에서 초기화되며, 반환 직전에 unblocked된다. 이는 스레드가 스케줄할 수 있도록 하기 위함이다.

 

 

void thread_func (void *aux);

- 이는 스레드로 실행되는 함수의 type이다.

- 인자*aux는 이 함수의 인자를 나타낸다.

 

 

void thread_block (void);

- running 상태의 스레드를 blocked 상태로 바꾼다. 이 스레드는 호출이 있지 않으면 다시 기동하지 않는다.

- 상당히 low-level 방식의 synchronization이기 때문에 다른 동기화를 쓰는 것을 추천한다.

 

 

void thread_unblock (struct thread *thread);

- blocked 상태의 스레드를 ready로 바꾼다.

 

 

struct thread *thread_current (void);

- running 상태 스레드를 반환한다. 

 

 

tid_t thread_tid (void);

- running 상태 스레드의  tid를 반환한다.

- thread_current ()->tid 와 같다.

 

 

const char *thread_name (void);

- running 상태 스레드의 이름을 반환한다.

- thread_current ()->name 과 같다.

 

 

void thread_exit (void) NO_RETURN;

- 현재 스레드를 나가게 한다.

- 비가역적이다.

 

 

void thread_yield (void);

- 스케줄러가 새로운 스레드를 기동할 수 있도록 스케줄러에 CPU를 할당한다. 

- 새로운 스레드가 current thread로 바뀐다. 

- 그 때문에, 스레드를 특정 시간동안만 running 상태에서 벗어날 수 없도록 하기위해 이 함수를 쓰는 것은 안된다. 

 

 

int thread_get_priority (void);
void thread_set_priority (int new_priority);

- 스레드에 새로운 우선순위를 부여한다.

 

 

int thread_get_nice (void);
void thread_set_nice (int new_nice);
int thread_get_recent_cpu (void);
int thread_get_load_avg (void);

- ???

댓글