* Finish a fork operation, with process p2 nearly set up. * Copy and update the pcb, set up the stack so that the child * ready to run and return to user mode. */
| 142 | * ready to run and return to user mode. |
| 143 | */ |
| 144 | void |
| 145 | cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) |
| 146 | { |
| 147 | struct proc *p1; |
| 148 | struct pcb *pcb2; |
| 149 | struct mdproc *mdp1, *mdp2; |
| 150 | struct proc_ldt *pldt; |
| 151 | |
| 152 | p1 = td1->td_proc; |
| 153 | if ((flags & RFPROC) == 0) { |
| 154 | if ((flags & RFMEM) == 0) { |
| 155 | /* unshare user LDT */ |
| 156 | mdp1 = &p1->p_md; |
| 157 | mtx_lock(&dt_lock); |
| 158 | if ((pldt = mdp1->md_ldt) != NULL && |
| 159 | pldt->ldt_refcnt > 1 && |
| 160 | user_ldt_alloc(p1, 1) == NULL) |
| 161 | panic("could not copy LDT"); |
| 162 | mtx_unlock(&dt_lock); |
| 163 | } |
| 164 | return; |
| 165 | } |
| 166 | |
| 167 | /* Ensure that td1's pcb is up to date. */ |
| 168 | fpuexit(td1); |
| 169 | update_pcb_bases(td1->td_pcb); |
| 170 | |
| 171 | /* Point the stack and pcb to the actual location */ |
| 172 | set_top_of_stack_td(td2); |
| 173 | td2->td_pcb = pcb2 = get_pcb_td(td2); |
| 174 | |
| 175 | /* Copy td1's pcb */ |
| 176 | bcopy(td1->td_pcb, pcb2, sizeof(*pcb2)); |
| 177 | |
| 178 | /* Properly initialize pcb_save */ |
| 179 | pcb2->pcb_save = get_pcb_user_save_pcb(pcb2); |
| 180 | bcopy(get_pcb_user_save_td(td1), get_pcb_user_save_pcb(pcb2), |
| 181 | cpu_max_ext_state_size); |
| 182 | |
| 183 | /* Point mdproc and then copy over td1's contents */ |
| 184 | mdp2 = &p2->p_md; |
| 185 | bcopy(&p1->p_md, mdp2, sizeof(*mdp2)); |
| 186 | |
| 187 | /* |
| 188 | * Create a new fresh stack for the new process. |
| 189 | * Copy the trap frame for the return to user mode as if from a |
| 190 | * syscall. This copies most of the user mode register values. |
| 191 | */ |
| 192 | td2->td_frame = (struct trapframe *)td2->td_md.md_stack_base - 1; |
| 193 | bcopy(td1->td_frame, td2->td_frame, sizeof(struct trapframe)); |
| 194 | |
| 195 | td2->td_frame->tf_rax = 0; /* Child returns zero */ |
| 196 | td2->td_frame->tf_rflags &= ~PSL_C; /* success */ |
| 197 | td2->td_frame->tf_rdx = 1; |
| 198 | |
| 199 | /* |
| 200 | * If the parent process has the trap bit set (i.e. a debugger |
| 201 | * had single stepped the process to the system call), we need |
nothing calls this directly
no test coverage detected