307c825515
The call works. Permission check, restriction of outstanding notifications to be added. Low level code to make it work from within interrupt handlers will be added as well.
223 lines
6.8 KiB
C
223 lines
6.8 KiB
C
/* 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 <signal.h>
|
|
#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_ntf_q = NULL; /* remove pending notifications */
|
|
rpc->p_flags |= NO_MAP; /* inhibit 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 */
|
|
}
|
|
|
|
|