process_fork ()

tid_t
process_fork (const char *name, struct intr_frame *if_ UNUSED) {
thread_t *curr = thread_current();
struct intr_frame *f = (pg_round_up(rrsp()) - sizeof(struct intr_frame));
memcpy(&curr->parent_if, f, sizeof(struct intr_frame));
tid_t tid = thread_create(name, PRI_DEFAULT, __do_fork, curr);
if (tid == TID_ERROR)
return TID_ERROR;
thread_t *child = get_child_process(tid);
sema_down(&child->fork_sema);
if (child->exit_status == TID_ERROR)
return TID_ERROR;
return tid;
}
duplicate_pte ()

#ifndef VM
static bool
duplicate_pte (uint64_t *pte, void *va, void *aux) {
struct thread *current = thread_current ();
struct thread *parent = (struct thread *) aux;
void *parent_page;
void *newpage;
bool writable;
if (is_kernel_vaddr(va))
return true;
parent_page = pml4_get_page (parent->pml4, va);
if (parent_page == NULL)
return false;
newpage = palloc_get_page(PAL_ZERO);
if (newpage == NULL)
return false;
memcpy(newpage, parent_page, PGSIZE);
writable = is_writable(pte);
if (!pml4_set_page (current->pml4, va, newpage, writable)) {
return false;
}
return true;
}
#endif
__do_fork ()



static void
__do_fork (void *aux) {
struct intr_frame if_;
struct thread *parent = (struct thread *) aux;
struct thread *current = thread_current ();
struct intr_frame *parent_if = &parent->parent_if;
bool succ = true;
memcpy (&if_, parent_if, sizeof (struct intr_frame));
if_.R.rax = 0;
current->pml4 = pml4_create();
if (current->pml4 == NULL)
goto error;
process_activate (current);
#ifdef VM
supplemental_page_table_init (¤t->spt);
if (!supplemental_page_table_copy (¤t->spt, &parent->spt))
goto error;
#else
if (!pml4_for_each (parent->pml4, duplicate_pte, parent))
goto error;
#endif
* TODO: Hint) 파일 객체를 복제하려면 include/filesys/file.h에서 `file_duplicate`를 사용하세요.
이 함수가 부모의 리소스를 성공적으로 복제할 때까지 부모는 fork()에서 반환되어서는 안 됩니다. */
if (parent->fd_idx >= FDCOUNT_LIMIT)
goto error;
struct dict_elem dup_file_dict[DICTLEN];
int dup_idx = 0;
current->fd_idx = parent->fd_idx;
struct file *file;
for (int fd = 0; fd < FDCOUNT_LIMIT; fd++) {
file = parent->fdt[fd];
if (file == NULL)
continue;
bool is_exist = false;
for (int i = 0; i <= dup_idx; i++) {
if (dup_file_dict[i].key == file) {
current->fdt[fd] = file_duplicate(file);
is_exist = true;
break;
}
}
if (is_exist)
continue;
if (file > STDERR)
current->fdt[fd] = file_duplicate(file);
else
current->fdt[fd] = file;
if (dup_idx < DICTLEN) {
dup_file_dict[dup_idx].key = file;
dup_file_dict[dup_idx++].value = current->fdt[fd];
}
}
sema_up(¤t->fork_sema);
process_init ();
if (succ)
do_iret (&if_);
error:
sema_up(¤t->fork_sema);
exit(TID_ERROR);
}