/*===========================================================================* * do_fork * *===========================================================================*/ PUBLIC int do_fork() { /* The process pointed to by 'mp' has forked. Create a child process. */ register struct mproc *rmp; /* pointer to parent */ register struct mproc *rmc; /* pointer to child */ int i, child_nr, t; char *sptr, *dptr; long prog_bytes; phys_clicks prog_clicks, child_base; long parent_abs, child_abs; extern phys_clicks alloc_mem(); /* If tables might fill up during FORK, don't even start since recovery half * way through is such a nuisance. */ rmp = mp; if (procs_in_use == NR_PROCS) return(EAGAIN); if (procs_in_use >= NR_PROCS - LAST_FEW && rmp->mp_effuid != 0)return(EAGAIN); /* Determine how much memory to allocate. */ prog_clicks = (phys_clicks) rmp->mp_seg[T].mem_len + rmp->mp_seg[D].mem_len + rmp->mp_seg[S].mem_len; #ifdef i8088 prog_clicks += rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_len; /* gap too */ #endif prog_bytes = (long) prog_clicks << CLICK_SHIFT; if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(EAGAIN); /* Create a copy of the parent's core image for the child. */ child_abs = (long) child_base << CLICK_SHIFT; parent_abs = (long) rmp->mp_seg[T].mem_phys << CLICK_SHIFT; i = mem_copy(ABS, 0, parent_abs, ABS, 0, child_abs, prog_bytes); if ( i < 0) panic("do_fork can't copy", i); /* Find a slot in 'mproc' for the child process. A slot must exist. */ for (rmc = &mproc[0]; rmc < &mproc[NR_PROCS]; rmc++) if ( (rmc->mp_flags & IN_USE) == 0) break; /* Set up the child and its memory map; copy its 'mproc' slot from parent. */ child_nr = rmc - mproc; /* slot number of the child */ procs_in_use++; sptr = (char *) rmp; /* pointer to parent's 'mproc' slot */ dptr = (char *) rmc; /* pointer to child's 'mproc' slot */ i = sizeof(struct mproc); /* number of bytes in a proc slot. */ while (i--) *dptr++ = *sptr++;/* copy from parent slot to child's */ rmc->mp_parent = who; /* record child's parent */ rmc->mp_seg[T].mem_phys = child_base; rmc->mp_seg[D].mem_phys = child_base + rmc->mp_seg[T].mem_len; rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + (rmp->mp_seg[S].mem_phys - rmp->mp_seg[D].mem_phys); rmc->mp_exitstatus = 0; rmc->mp_sigstatus = 0; /* Find a free pid for the child and put it in the table. */ do { t = 0; /* 't' = 0 means pid still free */ next_pid = (next_pid < 30000 ? next_pid + 1 : INIT_PROC_NR + 1); for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) if (rmp->mp_pid == next_pid) { t = 1; break; } rmc->mp_pid = next_pid; /* assign pid to child */ } while (t); /* Tell kernel and file system about the (now successful) FORK. */ sys_fork(who, child_nr, rmc->mp_pid); tell_fs(FORK, who, child_nr, 0); /* Report child's memory map to kernel. */ sys_newmap(child_nr, rmc->mp_seg); /* Reply to child to wake it up. */ reply(child_nr, 0, 0, NIL_PTR); return(next_pid); /* child's pid */ }
/*===========================================================================* * do_fork * *===========================================================================*/ PUBLIC int do_fork() { /* The process pointed to by 'mp' has forked. Create a child process. */ register struct mproc *rmp; /* pointer to parent */ register struct mproc *rmc; /* pointer to child */ int i, child_nr, t; phys_clicks prog_clicks, child_base; phys_bytes prog_bytes, parent_abs, child_abs; /* Intel only */ /* If tables might fill up during FORK, don't even start since recovery half * way through is such a nuisance. */ rmp = mp; if (procs_in_use == NR_PROCS) return(EAGAIN); if (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)return(EAGAIN); /* Determine how much memory to allocate. Only the data and stack need to * be copied, because the text segment is either shared or of zero length. */ prog_clicks = (phys_clicks) rmp->mp_seg[S].mem_len; prog_clicks += (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); prog_bytes = (phys_bytes) prog_clicks << CLICK_SHIFT; if ( (child_base = alloc_mem(prog_clicks)) == NO_MEM) return(ENOMEM); /* Create a copy of the parent's core image for the child. */ child_abs = (phys_bytes) child_base << CLICK_SHIFT; parent_abs = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT; i = sys_copy(ABS, 0, parent_abs, ABS, 0, child_abs, prog_bytes); if (i < 0) panic("do_fork can't copy", i); /* Find a slot in 'mproc' for the child process. A slot must exist. */ for (rmc = &mproc[0]; rmc < &mproc[NR_PROCS]; rmc++) if ( (rmc->mp_flags & IN_USE) == 0) break; /* Set up the child and its memory map; copy its 'mproc' slot from parent. */ child_nr = (int)(rmc - mproc); /* slot number of the child */ procs_in_use++; *rmc = *rmp; /* copy parent's process slot to child's */ rmc->mp_parent = who; /* record child's parent */ rmc->mp_flags &= (IN_USE|SEPARATE); /* inherit only these flags */ /* A separate I&D child keeps the parents text segment. The data and stack * segments must refer to the new copy. */ if (!(rmc->mp_flags & SEPARATE)) rmc->mp_seg[T].mem_phys = child_base; rmc->mp_seg[D].mem_phys = child_base; rmc->mp_seg[S].mem_phys = rmc->mp_seg[D].mem_phys + (rmp->mp_seg[S].mem_vir - rmp->mp_seg[D].mem_vir); rmc->mp_exitstatus = 0; rmc->mp_sigstatus = 0; /* Find a free pid for the child and put it in the table. */ do { t = 0; /* 't' = 0 means pid still free */ next_pid = (next_pid < 30000 ? next_pid + 1 : INIT_PID + 1); for (rmp = &mproc[0]; rmp < &mproc[NR_PROCS]; rmp++) if (rmp->mp_pid == next_pid || rmp->mp_procgrp == next_pid) { t = 1; break; } rmc->mp_pid = next_pid; /* assign pid to child */ } while (t); /* Tell kernel and file system about the (now successful) FORK. */ sys_fork(who, child_nr, rmc->mp_pid); tell_fs(FORK, who, child_nr, rmc->mp_pid); /* Report child's memory map to kernel. */ sys_newmap(child_nr, rmc->mp_seg); /* Reply to child to wake it up. */ setreply(child_nr, 0); return(next_pid); /* child's pid */ }