int sys_fork(struct trapframe* tf, pid_t* retval) { DEBUG(DB_EXEC,"sys_fork(): entering\n"); KASSERT(curproc != NULL); KASSERT(sizeof(struct trapframe)==(37*4)); char* child_name = kmalloc(sizeof(char)* NAME_MAX); strcpy(child_name, curproc->p_name); strcat(child_name, "_c"); // create PCB for child struct proc* child_proc = NULL; proc_fork(&child_proc); if (child_proc == NULL) { return ENOMEM; } strcpy(child_proc->p_name, child_name); KASSERT(child_proc->p_pid > 0); // copy address space and registers from this process to child struct addrspace* child_as = kmalloc(sizeof(struct addrspace)); if (child_as == NULL) { kfree(child_name); proc_destroy(child_proc); return ENOMEM; } struct trapframe* child_tf = kmalloc(sizeof(struct trapframe)); if (child_tf == NULL) { kfree(child_name); as_destroy(child_as); proc_destroy(child_proc); return ENOMEM; } DEBUG(DB_EXEC,"sys_fork(): copying address space...\n"); // copy the address space just created into the child process's // PCB structure int result = as_copy(curproc->p_addrspace, &child_as); if (result) { kfree(child_name); as_destroy(child_as); proc_destroy(child_proc); return result; } child_proc->p_addrspace = child_as; DEBUG(DB_EXEC,"sys_fork(): copying trapframe space...\n"); // copy this process's trapframe to the child process memcpy(child_tf, tf, sizeof(struct trapframe)); DEBUG(DB_EXEC, "sys_fork(): copying filetable...\n"); filetable_copy(curproc->p_filetable,&child_proc->p_filetable); DEBUG(DB_EXEC,"sys_fork(): assigning child process's parent as this process...\n"); // assign child processes parent as this process child_proc->p_parent = curproc; DEBUG(DB_EXEC,"sys_fork(): adding child to children procarray...\n"); result = procarray_add(&curproc->p_children, child_proc, NULL); if (result) { DEBUG(DB_EXEC, "sys_fork(): failed to add child process to proc_table...\n"); } DEBUG(DB_EXEC,"sys_fork(): allocating data...\n"); void **data = kmalloc(2*sizeof(void*)); data[0] = (void*)child_tf; data[1] = (void*)child_as; result = thread_fork(child_name, child_proc, &enter_forked_process, data, 0); if (result) { kfree(child_name); kfree(child_tf); as_destroy(child_as); proc_destroy(child_proc); return ENOMEM; } *retval = child_proc->p_pid; DEBUG(DB_EXEC, "sys_fork(): thread_fork returned: curproc=%u, child_proc=%u\n",curproc->p_pid,child_proc->p_pid); return 0; }
pid_t sys_fork(struct trapframe *tf) { if(procarray_num(procarr) == PID_MAX - PID_MIN) { errno = EMPROC; return 0; } struct proc *newproc = kmalloc(sizeof(*newproc)); // normal field newproc->p_name = kstrdup(curthread->t_proc->p_name); // name newproc->p_cwd = curproc->p_cwd; // vnode // synch field spinlock_init(&newproc->p_lock); newproc->p_cv = cv_create("proc cv"); newproc->p_lk = lock_create("proc lock"); newproc->open_num = 0; // files field newproc->fd_table = kmalloc(sizeof(struct fd *) * MAX_fd_table); for(unsigned i = 0 ; i < MAX_fd_table ; i++) { newproc->fd_table[i] = curproc->fd_table[i]; } // pid creation for(pid_t curid = PID_MIN ; curid <= PID_MAX ; curid++) { // loop through available pid range. if(find_proc(curid) == NULL) { // first available pid found. newproc->p_pid = curid; // set pid. break; // break loop. } } threadarray_init(&newproc->p_threads); spinlock_init(&newproc->p_lock); // copy threads // struct threadarray oldthreads = curproc->p_threads; pid_t result; procarray_add(procarr,newproc,NULL); struct exitc *c = kmalloc(sizeof(struct exitc)); c->exitcode = -1; c->pid = newproc->p_pid; exitcarray_add(codes,c,NULL); // fork thread // struct thread *t = threadarray_get(&oldthreads,0); // copy trapframe to heap. struct trapframe *ctf = kmalloc(sizeof(struct trapframe)); ctf->tf_vaddr = tf->tf_vaddr; ctf->tf_status = tf->tf_status; ctf->tf_cause = tf->tf_cause; ctf->tf_lo = tf->tf_lo; ctf->tf_hi = tf->tf_hi; ctf->tf_ra = tf->tf_ra; ctf->tf_at = tf->tf_at; ctf->tf_v0 = tf->tf_v0; ctf->tf_v1 = tf->tf_v1; ctf->tf_a0 = tf->tf_a0; ctf->tf_a1 = tf->tf_a1; ctf->tf_a2 = tf->tf_a2; ctf->tf_a3 = tf->tf_a3; ctf->tf_t0 = tf->tf_t0; ctf->tf_t1 = tf->tf_t1; ctf->tf_t2 = tf->tf_t2; ctf->tf_t3 = tf->tf_t3; ctf->tf_t4 = tf->tf_t4; ctf->tf_t5 = tf->tf_t5; ctf->tf_t6 = tf->tf_t6; ctf->tf_t7 = tf->tf_t7; ctf->tf_s0 = tf->tf_s0; ctf->tf_s1 = tf->tf_s1; ctf->tf_s2 = tf->tf_s2; ctf->tf_s3 = tf->tf_s3; ctf->tf_s4 = tf->tf_s4; ctf->tf_s5 = tf->tf_s5; ctf->tf_s6 = tf->tf_s6; ctf->tf_s7 = tf->tf_s7; ctf->tf_t8 = tf->tf_t8; ctf->tf_t9 = tf->tf_t9; ctf->tf_k0 = tf->tf_k0; ctf->tf_k1 = tf->tf_k1; ctf->tf_gp = tf->tf_gp; ctf->tf_sp = tf->tf_sp; ctf->tf_s8 = tf->tf_s8; ctf->tf_epc = tf->tf_epc; //int spl = splhigh(); result = thread_fork(curthread->t_proc->p_name, newproc, enter_forked_process, ctf, (unsigned long)curproc->p_addrspace ); // parent return. //splx(spl); return newproc->p_pid; }