/* The system call implemented in this file: * m_type: SYS_FORK * * The parameters for this system call are: * m1_i1: PR_PROC_NR (child's process table slot) * m1_i2: PR_PPROC_NR (parent, process that forked) * m1_i3: PR_PID (child pid received from PM) */ #include "../kernel.h" #include "../system.h" #include "../sendmask.h" #include #if (CHIP == INTEL) #include "../protect.h" #endif INIT_ASSERT /*===========================================================================* * do_fork * *===========================================================================*/ PUBLIC int do_fork(m_ptr) register message *m_ptr; /* pointer to request message */ { /* Handle sys_fork(). PR_PPROC_NR has forked. The child is PR_PROC_NR. */ #if (CHIP == INTEL) reg_t old_ldt_sel; #endif register struct proc *rpc; struct proc *rpp; rpp = proc_addr(m_ptr->PR_PPROC_NR); assert(isuserp(rpp)); rpc = proc_addr(m_ptr->PR_PROC_NR); assert(isemptyp(rpc)); /* Copy parent 'proc' struct to child. */ #if (CHIP == INTEL) old_ldt_sel = rpc->p_ldt_sel; /* stop this being obliterated by copy */ #endif *rpc = *rpp; /* copy 'proc' struct */ #if (CHIP == INTEL) rpc->p_ldt_sel = old_ldt_sel; #endif rpc->p_nr = m_ptr->PR_PROC_NR; /* this was obliterated by copy */ rpc->p_flags |= NO_MAP; /* inhibit the process from running */ rpc->p_flags &= ~(PENDING | SIG_PENDING | P_STOP); /* Only 1 in group should have PENDING, child does not inherit trace status*/ sigemptyset(&rpc->p_pending); rpc->p_pendcount = 0; rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */ rpc->user_time = 0; /* set all the accounting times to 0 */ rpc->sys_time = 0; rpc->child_utime = 0; rpc->child_stime = 0; return(OK); } /* The system call implemented in this file: * m_type: SYS_NEWMAP * * The parameters for this system call are: * m1_i1: PR_PROC_NR (install new map for this process) * m1_p1: PR_MEM_PTR (pointer to memory map) */ /*===========================================================================* * do_newmap * *===========================================================================*/ PUBLIC int do_newmap(m_ptr) message *m_ptr; /* pointer to request message */ { /* Handle sys_newmap(). Fetch the memory map from PM. */ register struct proc *rp; phys_bytes src_phys; int caller; /* whose space has the new map (usually PM) */ int k; /* process whose map is to be loaded */ int old_flags; /* value of flags before modification */ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ /* Extract message parameters and copy new memory map from PM. */ caller = m_ptr->m_source; k = m_ptr->PR_PROC_NR; map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR; if (!isokprocn(k)) return(EINVAL); rp = proc_addr(k); /* ptr to entry of user getting new map */ /* Copy the map from PM. */ src_phys = umap_local(proc_addr(caller), D, (vir_bytes) map_ptr, sizeof(rp->p_memmap)); assert(src_phys != 0); phys_copy(src_phys,vir2phys(rp->p_memmap),(phys_bytes)sizeof(rp->p_memmap)); #if (CHIP != M68000) alloc_segments(rp); #else pmmu_init_proc(rp); #endif old_flags = rp->p_flags; /* save the previous value of the flags */ rp->p_flags &= ~NO_MAP; if (old_flags != 0 && rp->p_flags == 0) lock_ready(rp); return(OK); } /* The system call implemented in this file: * m_type: SYS_EXEC * * The parameters for this system call are: * m1_i1: PR_PROC_NR (process that did exec call) * m1_i3: PR_TRACING (flag to indicate tracing is on/ off) * m1_p1: PR_STACK_PTR (new stack pointer) * m1_p2: PR_NAME_PTR (pointer to program name) * m1_p3: PR_IP_PTR (new instruction pointer) */ /*===========================================================================* * do_exec * *===========================================================================*/ PUBLIC int do_exec(m_ptr) register message *m_ptr; /* pointer to request message */ { /* Handle sys_exec(). A process has done a successful EXEC. Patch it up. */ register struct proc *rp; reg_t sp; /* new sp */ phys_bytes phys_name; char *np; #define NLEN (sizeof(rp->p_name)-1) rp = proc_addr(m_ptr->PR_PROC_NR); assert(isuserp(rp)); if (m_ptr->PR_TRACING) cause_sig(m_ptr->PR_PROC_NR, SIGTRAP); sp = (reg_t) m_ptr->PR_STACK_PTR; rp->p_reg.sp = sp; /* set the stack pointer */ #if (CHIP == M68000) rp->p_splow = sp; /* set the stack pointer low water */ #ifdef FPP /* Initialize fpp for this process */ fpp_new_state(rp); #endif #endif #if (CHIP == INTEL) /* wipe extra LDT entries */ kmemset(&rp->p_ldt[EXTRA_LDT_INDEX], 0, (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_ldt[0])); #endif rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */ rp->p_flags &= ~RECEIVING; /* PM does not reply to EXEC call */ if (rp->p_flags == 0) lock_ready(rp); /* Save command name for debugging, ps(1) output, etc. */ phys_name = numap_local(m_ptr->m_source, (vir_bytes) m_ptr->PR_NAME_PTR, (vir_bytes) NLEN); if (phys_name != 0) { phys_copy(phys_name, vir2phys(rp->p_name), (phys_bytes) NLEN); for (np = rp->p_name; (*np & BYTE) >= ' '; np++) {} *np = 0; } return(OK); } /* The system call implemented in this file: * m_type: SYS_XIT * * The parameters for this system call are: * m1_i1: PR_PROC_NR (slot number of exiting process) * m1_i2: PR_PPROC_NR (slot number of parent process) */ /*===========================================================================* * do_xit * *===========================================================================*/ PUBLIC int do_xit(m_ptr) message *m_ptr; /* pointer to request message */ { /* Handle sys_exit. A user process has exited (the PM sent the request). */ register struct proc *rp, *rc; struct proc *np, *xp; int exit_proc_nr; /* Get a pointer to the process that exited. */ exit_proc_nr = m_ptr->PR_PROC_NR; if (exit_proc_nr == SELF) exit_proc_nr = m_ptr->m_source; if (! isokprocn(exit_proc_nr)) return(EINVAL); rc = proc_addr(exit_proc_nr); /* If this is a user process and the PM passed in a valid parent process, * accumulate the child times at the parent. */ if (isuserp(rc) && isokprocn(m_ptr->PR_PPROC_NR)) { rp = proc_addr(m_ptr->PR_PPROC_NR); lock(); rp->child_utime += rc->user_time + rc->child_utime; rp->child_stime += rc->sys_time + rc->child_stime; unlock(); } /* Now call the routine to clean up of the process table slot. This cancels * outstanding timers, possibly removes the process from the message queues, * and resets important process table fields. */ clear_proc(exit_proc_nr); return(OK); /* tell PM that cleanup succeeded */ }