스레드는 총 4kb의 메모리 공간을 가진다. 커널 스택이 위에서부터 내려오는 구조.
struct thread
는 너무 커지면 안 된다. 너무 커지면 kernel stack
을 위한 자리가 없다. THREAD_MAGIC 까지의 공간이 스레드의 크기이다.kernel stack
은 너무 커지면 안 된다. stack은 지역 변수 혹은 함수의 매개변수를 저장하는 공간이므로, kernel 함수들은 이들을 사용하는 것 보다는 동적 메모리 할당을 이용하는 것이 더 좋다.0에서 magic까지의 공간이 스레드의 TCB 공간이다. 총 4kb의 공간 중에 TCB를 뺀 공간을 커널 스택으로 사용한다.
4 kB +---------------------------------+
| kernel stack |
| | |
| V |
| grows downward |
| |
| |
| |
| |
sizeof (struct thread) +---------------------------------+
| magic |
| intr_frame |
| : |
| : |
| status |
| tid |
0 kB +---------------------------------+
thread를 struct로 구현한 코드.
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. */
};
tid_t tid
: 스레드 ID
enum thread_status status
: 스레드 상태
enum thread_status {
THREAD_RUNNING, /* Running thread. */
THREAD_READY, /* Not running but ready to run. */
THREAD_BLOCKED, /* Waiting for an event to trigger. */
THREAD_DYING /* About to be destroyed. */
};
struct list_elem elem
: 프로세스가 ready_list
나 semaphore
의 waiting list
에서 대기중일 때 그 큐에 doubly linked list 형태로 존재하는데, 그 연결을 담당한다. 해당 스레드의 이 항목을 찾으면 앞뒤로 연결되어 있는 프로세스를 알 수 있지 않을까 생각.
struct list_elem {
struct list_elem *prev; /* Previous list element. */
struct list_elem *next; /* Next list element. */
};
struct intr_frame tf
:
unsigned magic
: 항상 THREAD_MAGIC == 0xcd6abf4b
의 값을 가지는데, 스레드의 스택 맨 끝 값을 의미하는 듯. thread_current()
함수가 매번 magic
값을 체크하는데, stack overflow가 발생하면 이 값이 바뀌게 되어 있다.
Idle 스레드를 만들고, Preemptive thread scheduling을 시작한다.
/* Starts preemptive thread scheduling by enabling interrupts.
Also creates the idle thread. */
void
thread_start (void) {
/* Create the idle thread. */
struct semaphore idle_started;
sema_init (&idle_started, 0);
// idle 스레드를 만들고 맨 처음 ready queue에 들어간다.
// semaphore를 1로 UP 시켜 공유 자원의 접근을 가능하게 한 다음 바로 BLOCK된다.
thread_create ("idle", PRI_MIN, idle, &idle_started);
/* Start preemptive thread scheduling. */
// thread_create(idle)에서 disable했던 인터럽트 상태를 enable로 만듦.
// 이제 스레드 스케줄링이 가능하다. 인터럽트가 가능하므로.
intr_enable ();
/* Wait for the idle thread to initialize idle_thread. */
sema_down (&idle_started);
}
idle 스레드 : 어떤 스레드들도 실행되고 있지 않을 때 실행되는 스레드. 맨 처음 thread_start()가 호출될 때 ready queue에 먼저 들어가 있는다.