본 위키는 commit 기준 pmanager finish - first all complete에 맞추어 작성되어 있습니다. 12299_2019030991_홍정범
thread의 실체 만들기
가장 처음 고민했던 것은 “기존에 있는 proc 구조체의 활용” 이었다. 우선 기본적으로 xv6 자체가 proc 구조체로 구성되어있는 ptable을 기준으로 실행되게 되어있기 때문에 proc구조체를 기본적인 실행단위로 고정해야겠다 라고 생각했다. 하지만 쓰레드의 스택을 기반으로 일을 해야하기 때문에, proc이라는 빈 통에 쓰레드를 넣어 일을 시켜야겠다고 생각했다. 즉, 나의 아이디어는 한 프로세스안에 실행되고 있는 쓰레드들을 번갈아가며 proc 구조체 안에 갈아끼우자 라는 것이었다.
이를 위해 개념적으로 몇 가지를 정의했는데, 원래 xv6에서 allocproc으로 할당받게 되는 프로세스는 main thread라고 부르기로 했다. 그리고 proc 구조체 안에 배열을 만들어 쓰레드들을 저장하기로 했다. 한 프로세스가 가질 수 있는 최대 쓰레드는 main thread를 포함해서 10개로 제한했고 main thread는 항상 배열의 첫번째 칸에 위치하게 디자인했다. thread와 proc 구조체는 서로 독립적인 state를 가지며 각 thread의 id는 배열에서의 번호, 즉 0 ~ 9 만 가질수 있게 디자인했다. (이는 test code를 운영할 때 예민하게 처리해주어야 한다.)
struct thread {
//thread state
thread_t tid; // thread ID (0~9)
enum procstate state; // thread state (independent)
//thread data
char *kstack; // Bottom of kernel stack for this process
struct trapframe *tf; // Trap frame for current syscall
struct context *context; // swtch() here to run process
// sleep data
void *chan; // If non-zero, sleeping on chan
// talk about it later
uint start; // thread pool idx;
void *retval; // Return value
};
struct proc {
// shared data
uint sz; // Size of process memory (bytes)
pde_t* pgdir; // Page table
enum procstate state; // Process state
int pid; // Process ID
struct proc *parent; // Parent process
int killed; // If non-zero, have been killed
char name[16]; // Process name (debugging)
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
//thread table
struct thread ttable[10]; // thread table (the main thread is in the ttable[0])
// talk about it later
uint thread_pool[10]; // thread reallocate address
uint sz_limit; // limit of memory
// copy from thread
char *kstack; // Bottom of kernel stack for this process
struct trapframe *tf; // Trap frame for current syscall
struct context *context; // swtch() here to run process
int cur_thread; // current thread ID
};
single-thread 기반 흐름 구성하기
xv6 process 실행 대략적인 흐름도
원래 proc 구조체 안에 있던 kernel stack에 공간을 할당받고 이것저것 초기 데이터를 설정해 주었지만, 나의 디자인에서는 proc 구조체는 쓰레드의 stack을 잠시 담아 일을 시켜줄 뿐이기에, 본래 스택의 주인인 쓰레드에 데이터를 할당해주었다. 처음 프로세스를 만들 때에는 단일 쓰레드의 프로세스로, main thread를 만들어주는 과정이기 때문에 main thread의 위치인 table의 0번칸에 할당해주었다.
allocproc을 통해 main thread에 스택을 할당받은 proc 구조체를 넘겨받게 되는데, init proceess에 대한 데이터 역시 main thread에 trapframe에 기록을 해준다.