[comp.os.cpm] UZI,part 4 of 5

dbraun@cadavr.intel.com (Doug Braun ~) (11/29/88)

UZI, Part 4 of 5:

#!/bin/sh
#
#Run this file through sh to get:
#    scall2.c
#    process.c
echo -n 'Extracting scall2.c ... '
sed 's/^X//' > scall2.c << 'EOF_scall2.c'
X/**************************************************
XUZI (Unix Z80 Implementation) Kernel:  scall2.c
X***************************************************/
X
X
X/*LINTLIBRARY*/
X#include "unix.h"
X#include "extern.h"
X
X
X/* Getpid() */
X
X_getpid()
X{
X    return(udata.u_ptab->p_pid);
X}
X
X/* Getppid() */
X
X_getppid()
X{
X    return(udata.u_ptab->p_pptr->p_pid);
X}
X
X
X/* Getuid() */
X
X_getuid()
X{
X    return(udata.u_ptab->p_uid);
X}
X
X
X_getgid()
X{
X    return(udata.u_gid);
X}
X
X
X/*********************************
Xsetuid(uid)
Xint uid;
X***********************************/
X
X#define uid (int)udata.u_argn
X
X_setuid()
X{
X    if (super() || udata.u_ptab->p_uid == uid)
X    {
X	udata.u_ptab->p_uid = uid;
X	udata.u_euid = uid;
X	return(0);
X    }
X    udata.u_error = EPERM;
X    return(-1);
X}
X
X#undef uid
X
X
X
X/*****************************************
Xsetgid(gid)
Xint gid;
X****************************************/
X
X#define gid (int16)udata.u_argn
X
X_setgid()
X{
X    if (super() || udata.u_gid == gid)
X    {
X	udata.u_gid = gid;
X	udata.u_egid = gid;
X	return(0);
X    }
X    udata.u_error = EPERM;
X    return(-1);
X}
X
X#undef gid;
X
X
X
X/***********************************
Xtime(tvec)
Xint tvec[];
X**************************************/
X
X#define tvec (int *)udata.u_argn
X
X_time()
X{
X    rdtime(tvec);  /* In machdep.c */
X    return(0);
X}
X
X#undef tvec
X
X
X/**************************************
Xstime(tvec)
Xint tvec[];
X**********************************/
X
X#define tvec (int *)udata.u_argn
X
X_stime()
X{
X/*
X    ifnot (super())
X    {
X	udata.u_error = EPERM;
X	return(-1);
X    }
X    sttime(tvec);
X    return(0);
X*/
X
X    udata.u_error = EPERM;
X    return(-1);
X}
X
X#undef tvec
X
X
X
X/********************************************
Xtimes(buf)
Xchar *buf;
X**********************************************/
X
X#define buf (char *)udata.u_argn
X
X_times()
X{
X    ifnot (valadr(buf,6*sizeof(time_t)))
X	return(-1);
X
X    di();
X    bcopy(&udata.u_utime, buf, 4*sizeof(time_t));
X    bcopy(&ticks, buf + 4*sizeof(time_t), sizeof(time_t));
X    ei();
X    return(0);
X}
X
X#undef buf
X
X
X
X/* User's execve() call. All other flavors are library routines. */
X
X/*****************************************
Xexecve(name, argv, envp)
Xchar *name;
Xchar *argv[];
Xchar *envp[];
X*****************************************/
X
X#define name (char *)udata.u_argn2
X#define argv (char **)udata.u_argn1
X#define envp (char **)udata.u_argn
X
X_execve()
X{
X    register inoptr ino;
X    register char *buf;
X    inoptr n_open();
X    char *bread();
X    blkno_t bmap();
X
X    ifnot (ino = n_open(name,NULLINOPTR))
X	return(-1);
X
X    if (ino->c_node.i_size.o_blkno >= ((uint16)(&udata)/512))
X    {
X	udata.u_error = ENOMEM;
X	goto nogood;
X    }
X
X    ifnot ( (getperm(ino) & OTH_EX) &&
X	    (ino->c_node.i_mode & F_REG) &&
X	    (ino->c_node.i_mode & (OWN_EX | OTH_EX | GRP_EX)) )
X    {
X	udata.u_error = EACCES;
X	goto nogood;
X    }
X
X    setftime(ino, A_TIME);
X
X    /* Gather the arguments, and put them on the root device */
X    /* Put environment on another block */
X    if (wargs(argv, 0) || wargs(envp, 1))
X	goto nogood;
X
X    /* Read in the first block of the new program */
X    buf = bread( ino->c_dev, bmap(ino, 0, 1), 0);
X
X    if ((*buf & 0xff) != EMAGIC)
X    {
X	udata.u_error = ENOEXEC;
X	goto nogood2;
X    }
X
X    /* Here, check the setuid stuff. No other changes need be made in
X    the user data */
X    if (ino->c_node.i_mode & SET_UID)
X	udata.u_euid = ino->c_node.i_uid;
X
X    if (ino->c_node.i_mode & SET_GID)
X	udata.u_egid = ino->c_node.i_gid;
X
X    bcopy(buf,PROGBASE,512);
X    bfree(buf, 0);
X
X    /* At this point, we are committed to reading in and executing
X    the program. We switch to a local stack, and pass to it
X    the necessary parameter: ino */
X
X    udata.u_ino = ino;     /* Termorarily stash these here */
X
X    tempstk();
X    exec2();   /* Never returns */
X
Xnogood2:
X    bfree(buf, 0);
Xnogood:
X    i_deref(ino);
X    return(-1);
X
X}
X
X#undef name
X#undef argv
X#undef envp
X
X
Xexec2()
X{
X    register blkno_t blk;
X    register char **argv;
X    register char **envp;
X    register int (**sp)();
X    int argc;
X    char *rargs();
X    register char *progptr;
X    char *buf;
X    blkno_t pblk;
X    blkno_t bmap();
X    char *bread();
X
X    /* Read in the rest of the program */
X    progptr = PROGBASE+512;
X    for (blk = 1; blk <= udata.u_ino->c_node.i_size.o_blkno; ++blk)
X    {
X	pblk = bmap(udata.u_ino, blk, 1);
X	if (pblk != -1)
X	{
X	    buf = bread( udata.u_ino->c_dev, pblk, 0);
X	    bcopy(buf, progptr, 512);
X	    bfree(buf, 0);
X	}
X	progptr += 512;
X    }
X    i_deref(udata.u_ino);
X
X    /* Zero out the free memory */
X    bzero(progptr,(uint16)((char *)&udata - progptr));
X    udata.u_break = progptr;
X
X
X    /* Read back the arguments and the environment */
X    argv = (char **)rargs((char *)&udata, 0, &argc);
X    envp = (char **)rargs((char *)argv, 1, NULL);
X
X    /* Fill in udata.u_name */
X    bcopy(*argv,udata.u_name,8);
X
X    /* Turn off caught signals */
X    for (sp= udata.u_sigvec; sp < (udata.u_sigvec+NSIGS); ++sp)
X	if (*sp != SIG_IGN)
X	    *sp = SIG_DFL;
X
X    /* Shove argc and the address of argv just below envp */
X    *(envp - 1) = (char *)argc;
X    *(envp - 2) = (char *)argv;
X
X    /* Go jump into the program, first setting the stack */
X    doexec((int16 *)(udata.u_isp = envp - 2));
X
X}
X
X
Xwargs(argv,blk)
Xchar **argv;
Xint blk;
X{
X    register char *ptr;    /* Address of base of arg strings in user space */
X    register int n;
X    struct s_argblk *argbuf;
X    register char *bufp;
X    register int j;
X    char *zerobuf();
X    char *bread();
X
X    /* Gather the arguments, and put them on the swap device */
X    argbuf = (struct s_argblk *)bread(SWAPDEV, udata.u_ptab->p_swap+blk, 2);
X    bufp = argbuf->a_buf;
X    for (j=0; argv[j] != NULL; ++j)
X    {
X	ptr = argv[j];
X	do
X	{
X	    *bufp++ = *ptr;
X	    if (bufp >= argbuf->a_buf+500)
X	    {
X	        udata.u_error = E2BIG;
X	        bfree((char *)argbuf, 1);
X	        return (1);
X	    }
X	}
X	while (*ptr++ != '\0');
X    }
X
X    argbuf->a_argc = j;  /* Store argc in argbuf. */
X    argbuf->a_arglen = bufp - argbuf->a_buf;  /*Store total string size. */
X
X    /* Swap out the arguments into the given swap block */
X    bfree((char *)argbuf, 1);
X
X    return (0);
X}
X
X
X
Xchar *
Xrargs(ptr,blk,cnt)
Xregister char *ptr;
Xint blk;
Xint *cnt;
X{
X    struct s_argblk *argbuf;
X    register char **argv;  /* Address of users argv[], just below ptr */
X    register int n;
X    char *bread();
X
X    /* Read back the arguments */
X    argbuf = (struct s_argblk *)bread(SWAPDEV,udata.u_ptab->p_swap+blk, 0);
X
X    /* Move them into the users address space, at the very top */
X    ptr -= argbuf->a_arglen;
X    if (argbuf->a_arglen)
X	bcopy(argbuf->a_buf, ptr, argbuf->a_arglen);
X
X    /* Set argv to point below the argument strings */
X    argv = (char **)ptr - (argbuf->a_argc + 1);
X
X    /* Set each element of argv[] to point to its argument string */
X    argv[0] = ptr;
X    for (n=1; n < argbuf->a_argc; ++n)
X	argv[n] = argv[n-1] + strlen(argv[n-1]) + 1;
X    argv[argbuf->a_argc] = NULL;
X
X    if (cnt)
X	*cnt = argbuf->a_argc;
X
X    bfree((char *)argbuf, 0);
X    return (argv);
X}
X
X
X
X/**********************************
Xbrk(addr)
Xchar *addr;
X************************************/
X
X#define addr (char *)udata.u_argn
X
X_brk()
X{
X    char dummy;   /* A thing to take address of */
X
X    /* A hack to get approx val of stack ptr. */
X    if (addr < PROGBASE || (addr+64) >= (char *)&dummy)
X    {
X	udata.u_error = ENOMEM;
X	return(-1);
X    }
X    udata.u_break = addr;
X    return(0);
X}
X
X#undef addr
X
X
X
X/************************************
Xsbrk(incr)
Xuint16 incr;
X***************************************/
X
X#define incr (uint16)udata.u_argn
X
X_sbrk()
X{
X    register char *oldbrk;
X
X    udata.u_argn += (oldbrk = udata.u_break);
X    if (_brk())
X	return(-1);
X
X    return((int)oldbrk);
X}
X
X#undef incr
X
X
X
X/**************************************
Xwait(statloc)
Xint *statloc;
X****************************************/
X
X#define statloc (int *)udata.u_argn
X
X_wait()
X{
X    register ptptr p;
X    register int retval;
X
X    if (statloc > (int *)(&udata))
X    {
X	udata.u_error = EFAULT;
X	return(-1);
X    }
X
X    di();
X    /* See if we have any children. */
X    for (p=ptab;p < ptab+PTABSIZE; ++p)
X    {
X	if (p->p_status && p->p_pptr == udata.u_ptab && p != udata.u_ptab)
X	    goto ok;
X    }
X    udata.u_error = ECHILD;
X    ei();
X    return (-1);
X
Xok:
X    /* Search for an exited child; */
X    for (;;)
X    {
X	chksigs();
X	if (udata.u_cursig)
X	{
X	    udata.u_error = EINTR;
X	    return(-1);
X	}
X	di();
X	for(p=ptab;p < ptab+PTABSIZE; ++p)
X	{
X	    if (p->p_status == P_ZOMBIE && p->p_pptr == udata.u_ptab)
X	    {
X	        if (statloc)
X	            *statloc = p->p_exitval;
X	        p->p_status = P_EMPTY;
X	        retval = p->p_pid;
X
X	        /* Add in child's time info */
X	        /* It was stored on top of p_wait in the childs process
X	        table entry */
X	        addtick(&udata.u_cutime, &(p->p_wait));
X	        addtick(&udata.u_cstime, (char *)(&(p->p_wait)) +
X	                         sizeof(time_t));
X
X	        ei();
X	        return(retval);
X	    }
X	}
X	/* Nothing yet, so wait */
X	psleep(udata.u_ptab);
X    }
X
X}
X
X#undef statloc
X
X
X
X/**************************************
X_exit(val)
Xint16 val;
X**************************************/
X
X#define val (int16)udata.u_argn
X
X__exit()
X{
X    doexit(val,0);
X}
X
X#undef val
X
X
X
Xdoexit(val,val2)
Xint16 val;
Xint16 val2;
X{
X    register int16 j;
X    register ptptr p;
X
X    for (j=0; j < UFTSIZE; ++j)
X    {
X	ifnot (udata.u_files[j] & 0x80)  /* Portable equivalent of == -1 */
X	    doclose(j);
X    }
X
X/*    _sync();  /* Not necessary, but a good idea. */
X
X    di();
X    udata.u_ptab->p_exitval = (val<<8) | (val2 & 0xff);
X
X    /* Set child's parents to init */
X    for(p=ptab;p < ptab+PTABSIZE; ++p)
X    {
X	if (p->p_status && p->p_pptr == udata.u_ptab)
X	    p->p_pptr = initproc;
X    }
X    i_deref(udata.u_cwd);
X
X    /* Stash away child's execution tick counts in process table,
X    overlaying some no longer necessary stuff. */
X    addtick(&udata.u_utime,&udata.u_cutime);
X    addtick(&udata.u_stime,&udata.u_cstime);
X    bcopy(&udata.u_utime, &(udata.u_ptab->p_wait), 2 * sizeof(time_t));
X
X    /* Wake up a waiting parent, if any. */
X    if (udata.u_ptab != initproc)
X	wakeup((char *)udata.u_ptab->p_pptr);
X    udata.u_ptab->p_status = P_ZOMBIE;
X    ei();
X    swapin(getproc());
X    panic("doexit:won't exit");
X}
X
X
X_fork()
X{
X   return (dofork());
X}
X
X
X
X_pause()
X{
X    psleep(0);
X    udata.u_error = EINTR;
X    return(-1);
X}
X
X
X/*************************************
Xsignal(sig, func)
Xint16 sig;
Xint16 (*func)();
X***************************************/
X
X#define sig (int16)udata.u_argn1
X#define func (int (*)())udata.u_argn
X
X_signal()
X{
X    int retval;
X
X    di();
X    if (sig < 1 || sig == SIGKILL || sig >= NSIGS)
X    {
X	udata.u_error = EINVAL;
X	goto nogood;
X    }
X
X    if (func == SIG_IGN)
X	udata.u_ptab->p_ignored |= sigmask(sig);
X    else
X    {
X	if (func != SIG_DFL && ((char *)func < PROGBASE ||
X	       (struct u_data *)func >= &udata))
X	{
X	    udata.u_error = EFAULT;
X	    goto nogood;
X	}
X	udata.u_ptab->p_ignored &= ~sigmask(sig);
X    }
X    retval = udata.u_sigvec[sig];
X    udata.u_sigvec[sig] = func;
X    ei();
X    return(retval);
X
Xnogood:
X    ei();
X    return(-1);
X}
X
X#undef sig
X#undef func
X
X
X
X/**************************************
Xkill(pid, sig)
Xint16 pid;
Xint16 sig;
X*****************************************/
X
X#define pid (int16)udata.u_argn1
X#define sig (int16)udata.u_argn
X
X_kill()
X{
X    ptptr p;
X
X    if (sig <= 0 || sig > 15)
X	goto nogood;
X
X    for (p=ptab; p < ptab+PTABSIZE; ++p)
X    {
X	if (p->p_pid == pid)
X	{
X	    sendsig(p,sig);
X	    return(0);
X	}
X    }
X
Xnogood:
X    udata.u_error = EINVAL;
X    return(-1);
X}
X
X#undef pid
X#undef sig
X
X
X
X/********************************
Xalarm(secs)
Xuint16 secs;
X*********************************/
X
X#define secs (int16)udata.u_argn
X
X_alarm()
X{
X    int retval;
X
X    di();
X    retval = udata.u_ptab->p_alarm;
X    udata.u_ptab->p_alarm = secs;
X    ei();
X    return(retval);
X}
X
X#undef secs
X
EOF_scall2.c
echo 'Done'

echo -n 'Extracting process.c ... '
sed 's/^X//' > process.c << 'EOF_process.c'
X/**************************************************
XUZI (Unix Z80 Implementation) Kernel:  process.c
X***************************************************/
X
X
X#include "unix.h"
X#include "extern.h"
X
Xinit2()
X{
X    register char *j;
X    static char bootchar;
X    static char *arg[2] = { "init", NULL };
X    inoptr i_open(), n_open();
X    ptptr ptab_alloc();
X
X    bufinit();
X
X    /* Create the context for the first process */
X    newproc(udata.u_ptab = initproc = ptab_alloc());
X    initproc->p_status = P_RUNNING;
X
X    /* User's file table */
X    for (j=udata.u_files; j < (udata.u_files+UFTSIZE); ++j)
X	*j = -1;
X
X    /* Turn on the clock */
X    out(02,0xf1);
X    ei();
X
X    /* Wait until the clock has interrupted, to set tod
X    while (!tod.t_date) ;  /* Loop */
X    /*
X
X    /* Open the console tty device */
X    if (d_open(TTYDEV) != 0)
X	panic("no tty");
X
X    kprintf("boot: ");
X    udata.u_base = &bootchar;
X    udata.u_count = 1;
X    cdread(TTYDEV);
X    ROOTDEV = bootchar - '0';
X
X    /* Mount the root device */
X    if (fmount(ROOTDEV,NULLINODE))
X	panic("no filesys");
X
X    ifnot (root = i_open(ROOTDEV,ROOTINODE))
X	panic("no root");
X
X    i_ref(udata.u_cwd = root);
X    rdtime(&udata.u_time);
X
X    udata.u_argn2 = (int16)("/init");
X    udata.u_argn1 = (int16)(&arg[0]);
X    udata.u_argn = (int16)(&arg[1]);
X    _execve();
X/*
X    _execve("/init",&arg[0],&arg[1]);
X*/
X    panic("no /init");
X
X}
X
X
X/* psleep() puts a process to sleep on the given event.
XIf another process is runnable, it swaps out the current one
Xand starts the new one.
XNormally when psleep is called, the interrupts have already been
Xdisabled.   An event of 0 means a pause(), while an event equal
Xto the process's own ptab address is a wait().   */
X
Xpsleep(event)
Xchar *event;
X{
X    register dummy;  /* Force saving of registers */
X
X    di();
X    if (udata.u_ptab->p_status != P_RUNNING)
X	panic("psleep: voodoo");
X    if (!event)
X	udata.u_ptab->p_status = P_PAUSE;
X    else if (event == (char *)udata.u_ptab)
X	udata.u_ptab->p_status = P_WAIT;
X    else
X	udata.u_ptab->p_status = P_SLEEP;
X
X    udata.u_ptab->p_wait = event;
X
X    ei();
X
X    swapout();          /* Swap us out, and start another process */
X
X    /* Swapout doesn't return until we have been swapped back in */
X}
X
X
X/* wakeup() looks for any process waiting on the event,
Xand make them runnable */
X
Xwakeup(event)
Xchar *event;
X{
X    register ptptr p;
X
X    di();
X    for(p=ptab;p < ptab+PTABSIZE; ++p)
X    {
X	if (p->p_status > P_RUNNING && p->p_wait == event)
X	{
X	    p->p_status = P_READY;
X	    p->p_wait = (char *)NULL;
X	}
X    }
X    ei();
X}
X
X
X/* Getproc returns the process table pointer of a runnable process.
XIt is actually the scheduler.
XIf there are none, it loops.  This is the only time-wasting loop in the
Xsystem. */
X
Xptptr
Xgetproc()
X{
X    register status;
X    static ptptr pp = ptab;    /* Pointer for round-robin scheduling */
X
X    for (;;)
X    {
X	if (++pp >= ptab + PTABSIZE)
X	    pp = ptab;
X
X	di();
X	status = pp->p_status;
X	ei();
X
X	if (status == P_RUNNING)
X	    panic("getproc: extra running");
X	if (status == P_READY)
X	    return(pp);
X    }
X}
X
X/* Temp storage for swapout() */
Xchar *stkptr;
X
X
X/* Swapout swaps out the current process, finds another that is READY,
Xpossibly the same process, and swaps it in.
XWhen a process is restarted after calling swapout,
Xit thinks it has just returned from swapout(). */
X
X/* This function can have no arguments or auto variables */
Xswapout()
X{
X    static ptptr newp;
X    ptptr getproc();
X
X
X    /* See if any signals are pending */
X    chksigs();
X
X    /* Get a new process */
X    newp = getproc();
X
X    /* If there is nothing else to run, just return */
X    if (newp == udata.u_ptab)
X    {
X	udata.u_ptab->p_status = P_RUNNING;
X	return (runticks = 0);
X    }
X
X    ;
X    /* Save the stack pointer and critical registers */
X#asm
X	LD      HL,01   ;this will return 1 if swapped.
X	PUSH    HL      ;will be return value
X	PUSH    BC
X	PUSH    IX
X	LD      HL,0
X	ADD     HL,SP   ;get sp into hl
X	LD      (stkptr?),HL
X#endasm
X    udata.u_sp = stkptr;
X
X    swrite();
X    /* Read the new process in, and return into its context. */
X    swapin(newp);
X
X    /* We should never get here. */
X    panic("swapin failed");
X}
X
X
X/* This actually writes out the image */
Xswrite()
X{
X    blkno_t blk;
X    blk = udata.u_ptab->p_swap;
X
X    /* Start by writing out the user data. */
X
X    /* The user data is written so that it is packed to the top of one block */
X    swapwrite(SWAPDEV, blk, 512, ((char *)(&udata+1))-512 );
X
X    /* The user address space is written in two i/o operations,
X       one from 0x100 to the break, and then from the stack up. */
X    /* Notice that this might also include part or all of the user data,
X       but never anything above it. */
X
X    swapwrite(SWAPDEV,
X	        blk+1,
X	        (((char *)(&udata+1))-PROGBASE) & ~511,
X	        PROGBASE);
X
X}
X
X/* No automatics can be used past tempstack(); */
Xswapin(pp)
Xptptr pp;
X{
X    static blkno_t blk;
X    static ptptr newp;
X
X    di();
X    newp = pp;
X    blk = newp->p_swap;
X    ei();
X
X    tempstack();
X
X    swapread(SWAPDEV, blk, 512, ((char *)(&udata+1))-512 );
X
X    /* The user address space is read in two i/o operations,
X       one from 0x100 to the break, and then from the stack up. */
X    /* Notice that this might also include part or all of the user data,
X       but never anything above it. */
X
X    swapread(SWAPDEV,
X	        blk+1,
X	        (((char *)(&udata+1))-PROGBASE) & ~511,
X	        PROGBASE);
X
X    if (newp != udata.u_ptab)
X	panic("mangled swapin");
X    di();
X    newp->p_status = P_RUNNING;
X    runticks = 0;
X    ei();
X    /* Restore the registers */
X
X    stkptr = udata.u_sp;
X#asm
X	LD      HL,(stkptr?)
X	LD      SP,HL
X	POP     IX
X	POP     BC
X	POP     HL
X	LD      A,H
X	OR      L
X	RET             ;return into the context of the swapped-in process
X#endasm
X
X}
X
X
X/* Temp storage for dofork */
Xint16 newid;
X
X/* dofork implements forking.  */
X/* This function can have no arguments or auto variables */
X
Xdofork()
X{
X    static ptptr p;
X    ptptr ptab_alloc();
X
X    ifnot (p = ptab_alloc())
X    {
X	udata.u_error = EAGAIN;
X	return(-1);
X    }
X    di();
X    udata.u_ptab->p_status = P_READY; /* Parent is READY */
X    newid = p->p_pid;
X    ei();
X
X    /* Save the stack pointer and critical registers */
X    /* When the process is swapped back in, it will be as if
X    it returns with the value of the childs pid. */
X
X#asm
X	LD      HL,(newid?)
X	PUSH    HL
X	PUSH    BC
X	PUSH    IX
X	LD      HL,0
X	ADD     HL,SP   ;get sp into hl
X	LD      (stkptr?),HL
X#endasm
X
X    udata.u_sp = stkptr;
X    swrite();
X
X#asm
X	POP     HL              ;repair stack pointer
X	POP     HL
X	POP     HL
X#endasm
X
X    /* Make a new process table entry, etc. */
X    newproc(p);
X
X    di();
X    runticks = 0;
X    p->p_status = P_RUNNING;
X    ei();
X    return (0);  /* Return to child */
X}
X
X
X/* Newproc fixes up the tables for the child of a fork */
X
Xnewproc(p)
Xptptr p;    /* New process table entry */
X{
X    register char *j;
X
X    /* Note that ptab_alloc clears most of the entry */
X    di();
X    p->p_swap = (p - ptab) * 65  + 1;  /* Allow 65 blocks per process */
X    p->p_status = P_RUNNING;
X
X    p->p_pptr = udata.u_ptab;
X    p->p_ignored = udata.u_ptab->p_ignored;
X    p->p_uid = udata.u_ptab->p_uid;
X    udata.u_ptab = p;
X    bzero(&udata.u_utime,4*sizeof(time_t)); /* Clear tick counters */
X    ei();
X
X    rdtime(&udata.u_time);
X    i_ref(udata.u_cwd);
X    udata.u_cursig = udata.u_error = 0;
X
X    for (j=udata.u_files; j < (udata.u_files+UFTSIZE); ++j)
X	if (*j >= 0)
X	   ++of_tab[*j].o_refs;
X}
X
X
X
X/* This allocates a new process table slot, and fills
Xin its p_pid field with a unique number.  */
X
Xptptr
Xptab_alloc()
X{
X    register ptptr p;
X    register ptptr pp;
X    static int nextpid = 0;
X
X    di();
X    for(p=ptab;p < ptab+PTABSIZE; ++p)
X    {
X	if (p->p_status == P_EMPTY)
X	    goto found;
X    }
X    ei();
X    return(NULL);
X
Xfound:
X
X    /* See if next pid number is unique */
Xnogood:
X    if (nextpid++ > 32000)
X	nextpid = 1;
X    for (pp=ptab; pp < ptab+PTABSIZE; ++pp)
X    {
X	if (pp->p_status != P_EMPTY && pp->p_pid == nextpid)
X	    goto nogood;
X    }
X
X    bzero(p,sizeof(struct p_tab));
X    p->p_pid = nextpid;
X    p->p_status = P_FORKING;
X    ei();
X    return (p);
X}
X
X
X
X/* This is the clock interrupt routine.   Its job is to
Xincrement the clock counters, increment the tick count of the
Xrunning process, and either swap it out if it has been in long enough
Xand is in user space or mark it to be swapped out if in system space.
XAlso it decrements the alarm clock of processes.
XThis must have no automatic or register variables */
X
Xclk_int()
X{
X    static ptptr p;
X
X    ifnot (in(0xf0))    /* See if clock actually interrupted, and turn it off */
X	return(0);
X
X    /* Increment processes and global tick counters */
X    if (udata.u_ptab->p_status == P_RUNNING)
X	incrtick(udata.u_insys ? &udata.u_stime : &udata.u_utime);
X
X    incrtick(&ticks);
X
X    /* Do once-per-second things */
X
X    if (++sec == TICKSPERSEC)
X    {
X	/* Update global time counters */
X	sec = 0;
X
X	rdtod();  /* Update time-of-day */
X
X	/* Update process alarm clocks */
X	for (p=ptab; p < ptab+PTABSIZE; ++p)
X	{
X	    if (p->p_alarm)
X	        ifnot(--p->p_alarm)
X	            sendsig(p,SIGALRM);
X	}
X    }
X
X
X    /* Check run time of current process */
X    if (++runticks >= MAXTICKS && !udata.u_insys)    /* Time to swap out */
X    {
X	udata.u_insys = 1;
X	inint = 0;
X	udata.u_ptab->p_status = P_READY;
X	swapout();
X	di();
X	udata.u_insys = 0;      /* We have swapped back in */
X    }
X
X    return(1);
X}
X
X
X
Xextern int (*disp_tab[])();
X
Xstatic int j;
X
X/* No auto vars here, so carry flag will be preserved */
Xunix(argn3, argn2, argn1, argn, uret, callno)
Xint16 argn3, argn2, argn1, argn;
Xchar *uret;
Xint callno;
X{
X    udata.u_argn3 = argn3;
X    udata.u_argn2 = argn2;
X    udata.u_argn1 = argn1;
X    udata.u_argn = argn;
X    udata.u_retloc = uret;
X    udata.u_callno = callno;
X
X    udata.u_insys = 1;
X    udata.u_error = 0;
X    ei();
X
X#ifdef DEBUG
X    kprintf ("\t\t\t\t\tcall %d (%x, %x, %x)\n",callno,argn2,argn1,argn);
X#endif
X
X    /* Branch to correct routine */
X
X    udata.u_retval = (*disp_tab[udata.u_callno])();
X
X#ifdef DEBUG
X    kprintf("\t\t\t\t\t\tcall %d ret %x err %d\n",
X	udata.u_callno,udata.u_retval, udata.u_error);
X#endif
X
X
X    chksigs();
X    di();
X    if (runticks >= MAXTICKS)
X    {
X	udata.u_ptab->p_status = P_READY;
X	swapout();
X    }
X    ei();
X
X    udata.u_insys = 0;
X    calltrap();         /* Call trap routine if necessary */
X
X    /* If an error, return errno with carry set */
X
X    if (udata.u_error)
X    {
X	;
X#asm
X	LD      HL, (udata? + ?OERR)
X	POP     BC              ;restore frame pointer
X	PUSH    BC
X	POP     IX
X	SCF
X	RET
X#endasm
X	;
X    }
X
X    return(udata.u_retval);
X}
X
X
X
X/* This sees if the current process has any signals set, and deals with them */
Xchksigs()
X{
X    register j;
X
X    di();
X    ifnot (udata.u_ptab->p_pending)
X    {
X	ei();
X	return;
X    }
X
X    for (j=1; j < NSIGS; ++j)
X    {
X	ifnot (sigmask(j) & udata.u_ptab->p_pending)
X	    continue;
X	if (udata.u_sigvec[j] == SIG_DFL)
X	{
X	    ei();
X	    doexit(0,j);
X	}
X
X	if (udata.u_sigvec[j] != SIG_IGN)
X	{
X	    /* Arrange to call the user routine at return */
X	    udata.u_ptab->p_pending &= !sigmask(j);
X	    udata.u_cursig = j;
X	}
X    }
X    ei();
X}
X
X
Xsendsig(proc,sig)
Xptptr proc;
Xint16 sig;
X{
X    register ptptr p;
X
X    if (proc)
X	ssig(proc,sig);
X    else
X	for (p=ptab; p < ptab+PTABSIZE; ++p)
X	    if (p->p_status)
X	        ssig(p,sig);
X	
X}
X
Xssig(proc,sig)
Xregister ptptr proc;
Xint16 sig;
X{
X    register stat;
X
X    di();
X    ifnot(proc->p_status)
X	goto done;              /* Presumably was killed just now */
X
X    if (proc->p_ignored & sigmask(sig))
X	goto done;
X
X    stat = proc->p_status;
X    if (stat == P_PAUSE || stat == P_WAIT || stat == P_SLEEP)
X	proc->p_status = P_READY;
X
X    proc->p_wait = (char *)NULL;
X    proc->p_pending |= sigmask(sig);
Xdone:
X    ei();
X}
X
X
EOF_process.c
echo 'Done'

exit 0

Doug Braun				Intel Corp CAD
					408 765-4279

 / decwrl \
 | hplabs |
-| oliveb |- !intelca!mipos3!cadev4!dbraun
 | amd    |
 \ qantel /