/*------------------------------------------------------------------------ * getstk -- allocate stack memory, returning address of topmost WORD *------------------------------------------------------------------------ */ WORD *getstk(unsigned int nbytes) { STATWORD ps; struct mblock *p, *q; /* q follows p along memlist */ struct mblock *fits, *fitsq=NULL; WORD len; disable(ps); if (nbytes == 0) { restore(ps); return( (WORD *)SYSERR ); } nbytes = (unsigned int) roundew(nbytes); fits = (struct mblock *) NULL; q = &memlist; for (p = q->mnext ; p !=(struct mblock *) NULL ; q = p,p = p->mnext) if ( p->mlen >= nbytes) { fitsq = q; fits = p; } if (fits == (struct mblock *) NULL) { restore(ps); return( (WORD *)SYSERR ); } if (nbytes == (len = fits->mlen) ) { fitsq->mnext = fits->mnext; } else { fits->mlen -= nbytes; } fits = (struct mblock *) ((WORD) fits + len - sizeof(WORD)); *((WORD *) fits) = nbytes; restore(ps); return( (WORD *) fits); }
//procedure address //stack size in words //proccess priority > 0 //name (for debugging) //number of args //argments SYSCALL create(int *procaddr,int ssize,int priority,char *name,int nargs,int args) { int pid; /* stores new process id */ struct pentry *pptr; /* pointer to proc. table entry */ int *saddr; /* stack address */ sigset_t ps; /* saved processor status */ disable(ps); ssize = roundew(ssize); pid = newpid(); if ((ssize < MINSTK) || (pid == SYSERR) || (priority < 1)) { restore(ps); return(SYSERR); } if ((int)(saddr = getstk(ssize)) == SYSERR) { proctab[pid].pstate=PRFREE; //free pid restore(ps); return(SYSERR); } numproc++; pptr = &proctab[pid]; pptr->pstate = PRSUSP; strcpy(pptr->pname,name); pptr->pprio = priority; pptr->pbase = (int) saddr; pptr->pstklen = ssize; pptr->psem = 0; pptr->phasmsg = FALSE; pptr->plimit = (int)(saddr - ssize + 1); pptr->pargs = nargs; pptr->posix_ctxt = posix_ctxt_init; pptr->posix_ctxt.uc_stack.ss_size = ssize; pptr->posix_ctxt.uc_stack.ss_sp = (void*)((int) saddr - ssize + 1); pptr->posix_ctxt.uc_stack.ss_flags = 0; pptr->posix_ctxt.uc_link = &return_ctxt; switch (nargs) { case 0: makecontext(&(pptr->posix_ctxt),(void *)procaddr,0); break; case 1: makecontext(&(pptr->posix_ctxt),(void *)procaddr,1,args); break; case 2: makecontext(&(pptr->posix_ctxt),(void *)procaddr,2,args,*(&args+1)); break; case 3: makecontext(&(pptr->posix_ctxt),(void *)procaddr,3,args,*(&args+1),*(&args+2)); break; } restore(ps); return(pid); }
//------------------------------------------------------------------------ // freemem -- free a memory block, returning it to memlist //------------------------------------------------------------------------ SYSCALL freemem(void *b, size_t size) { int ps; struct mblock *p, *prev, *block = (struct mblock *)b; intptr_t top; if (size == 0 || (intptr_t)block > (intptr_t)maxaddr || (intptr_t)block < (intptr_t)&end) return SYSERR; size = (size_t)roundew(size); ps = disable(); for (p = memlist.mnext, prev = &memlist; p != NULL && p < block; prev = p, p = p->mnext); top = prev->mlen + (intptr_t)prev; if (top > (intptr_t)block && (prev != &memlist || p != NULL) && ((intptr_t)block + size) > (intptr_t)p) { restore(ps); return SYSERR; } if (prev != &memlist && top == (intptr_t)block) prev->mlen += size; else { block->mlen = size; block->mnext = p; prev->mnext = block; prev = block; } if ((prev->mlen + (intptr_t)prev) == (intptr_t)p) { prev->mlen += p->mlen; prev->mnext = p->mnext; } restore(ps); return OK; }
/*------------------------------------------------------------------------ * create - create a process to start running a procedure *------------------------------------------------------------------------ */ pid32 create_9_4( void *procaddr, /* procedure address */ uint32 ssize, /* stack size in words */ pri16 priority, /* process priority > 0 */ char *name, /* name (for debugging) */ uint32 nargs, /* number of args that follow */ ... ) { uint32 savsp, *pushsp; intmask mask; /* interrupt mask */ pid32 pid; /* stores new process id */ struct procent *prptr; /* pointer to proc. table entry */ int32 i; uint32 *a; /* points to list of args */ uint32 *saddr; /* stack address */ mask = disable(); if (ssize < MINSTK) ssize = MINSTK; ssize = (uint32) roundew(ssize); if (((saddr = (uint32 *)getstk_new(ssize)) == (uint32 *)SYSERR ) || (pid=newpid()) == SYSERR || priority < 1 ) { restore(mask); return SYSERR; } prcount++; prptr = &proctab[pid]; /* initialize process table entry for new process */ prptr->prstate = PR_SUSP; /* initial state is suspended */ prptr->prprio = priority; prptr->prstkbase = (char *)saddr; prptr->prstklen = ssize; prptr->prname[PNMLEN-1] = NULLCH; for (i=0 ; i<PNMLEN-1 && (prptr->prname[i]=name[i])!=NULLCH; i++) ; prptr->prsem = -1; prptr->prparent = (pid32)getpid(); prptr->prhasmsg = FALSE; /* set up initial device descriptors for the shell */ prptr->prdesc[0] = CONSOLE; /* stdin is CONSOLE device */ prptr->prdesc[1] = CONSOLE; /* stdout is CONSOLE device */ prptr->prdesc[2] = CONSOLE; /* stderr is CONSOLE device */ /* Initialize stack as if the process was called */ *saddr = STACKMAGIC; savsp = (uint32)saddr; /* push arguments */ a = (uint32 *)(&nargs + 1); /* start of args */ a += nargs -1; /* last argument */ for ( ; nargs > 4 ; nargs--) /* machine dependent; copy args */ *--saddr = *a--; /* onto created process' stack */ *--saddr = (long)procaddr; for(i = 11; i >= 4; i--) *--saddr = 0; for(i = 4; i > 0; i--) { if(i <= nargs) *--saddr = *a--; else *--saddr = 0; } *--saddr = (long)INITRET; /* push on return address */ *--saddr = (long)0x00000053; /* CPSR, A, F bits set, */ /* Supervisor mode */ prptr->prstkptr = (char *)saddr; restore(mask); return pid; /* The following entries on the stack must match what ctxsw */ /* expects a saved process state to contain: ret address, */ /* ebp, interrupt mask, flags, registerss, and an old SP */ *--saddr = (long)procaddr; /* Make the stack look like it's*/ /* half-way through a call to */ /* ctxsw that "returns" to the */ /* new process */ *--saddr = savsp; /* This will be register ebp */ /* for process exit */ savsp = (uint32) saddr; /* start of frame for ctxsw */ *--saddr = 0x00000200; /* New process runs with */ /* interrupts enabled */ /* Basically, the following emulates a x86 "pushal" instruction */ *--saddr = 0; /* %eax */ *--saddr = 0; /* %ecx */ *--saddr = 0; /* %edx */ *--saddr = 0; /* %ebx */ *--saddr = 0; /* %esp; value filled in below */ pushsp = saddr; /* remember this location */ *--saddr = savsp; /* %ebp (while finishing ctxsw) */ *--saddr = 0; /* %esi */ *--saddr = 0; /* %edi */ *pushsp = (unsigned long) (prptr->prstkptr = (char *)saddr); restore(mask); return pid; }
//------------------------------------------------------------------------ // sysinit -- initialize all Xinu data structures and devices //------------------------------------------------------------------------ static int sysinit(void) { static int (*nulluserp)() = &nulluser; static uword *nulluserpp = (uword *)&nulluserp; struct pentry *pptr; struct mblock *mptr; // initialize system variables numproc = 0; nextproc = NPROC - 1; nextsem = NSEM - 1; nextqueue = NPROC; // q[0..NPROC-1] are processes // initialize free memory list memlist.mnext = mptr = (struct mblock *)roundew(&end); mptr->mnext = (struct mblock *)NULL; mptr->mlen = (uword)truncew((uintptr_t)maxaddr - NULLSTK - (uintptr_t)&end); // initialize process table for (int k = 0; k < NPROC; k++) proctab[k].pstate = PRFREE; // initialize null process entry pptr = &proctab[NULLPROC]; pptr->pstate = PRCURR; pptr->pprio = 0; strlcpy(pptr->pname, "prnull", PNMLEN); pptr->plimit = ((char *)maxaddr) - NULLSTK - sizeof(uword); pptr->pbase = (char *)maxaddr; *((uword *)pptr->pbase) = MAGIC; pptr->paddr = (char *)(*nulluserpp); pptr->phasmsg = FALSE; pptr->pargs = 0; currpid = NULLPROC; // initialize semaphores for (int k = 0; k < NSEM; k++) { struct sentry *sptr = &semaph[k]; sptr->sstate = SFREE; sptr->sqtail = 1 + (sptr->sqhead = newqueue()); } // initialize ready list rdyhead = newqueue(); rdytail = 1 + rdyhead; // initialize memory marking _mkinit(); // initialize r.t.clock clkinit(); // initialize disk buffers dskdbp = mkpool(DBUFSIZ, NDBUFF); dskrbp = mkpool(DREQSIZ, NDREQ); // initialize devices for (int k = 0; k < NDEVS; k++) init(k); return OK; }
/*------------------------------------------------------------------------ * create - create a process to start running a procedure *------------------------------------------------------------------------ */ SYSCALL create(int (*procaddr)(), int ssize, int priority, char *name, int nargs, ...) { va_list ap; unsigned long savsp, *pushsp; STATWORD ps; int pid; /* stores new process id */ struct pentry *pptr; /* pointer to proc. table entry */ int i; unsigned long *saddr, *uarg; /* stack address */ unsigned long *getstk(); int INITRET(); va_start(ap, nargs); disable(ps); if (ssize < MINSTK) ssize = MINSTK; ssize = (int) roundew(ssize); if (((saddr = (unsigned long *)getstk(ssize)) == (unsigned long *)SYSERR ) || (pid=newpid()) == SYSERR || priority < 1 ) { restore(ps); va_end(ap); return SYSERR; } numproc++; pptr = &proctab[pid]; pptr->fildes[0] = 0; /* stdin set to console */ pptr->fildes[1] = 0; /* stdout set to console */ pptr->fildes[2] = 0; /* stderr set to console */ for (i=3; i < _NFILE; i++) /* others set to unused */ pptr->fildes[i] = FDFREE; pptr->pstate = PRSUSP; for (i=0 ; i<PNMLEN && (int)(pptr->pname[i]=name[i])!=0 ; i++) ; pptr->pprio = priority; pptr->pbase = (long) saddr; pptr->pstklen = ssize; pptr->psem = 0; pptr->phasmsg = FALSE; pptr->plimit = pptr->pbase - ssize + sizeof (long); pptr->pirmask[0] = 0; pptr->pnxtkin = BADPID; pptr->pdevs[0] = pptr->pdevs[1] = BADDEV; /* Bottom of stack */ *saddr = MAGIC; savsp = (unsigned long)saddr; /* push arguments */ pptr->pargs = nargs; uarg = saddr - nargs; saddr = uarg; /* end of args for after the copy */ for (; nargs > 0 ; nargs--) *uarg++ = va_arg(ap, unsigned long); *--saddr = (long)INITRET; /* push on return address */ *--saddr = pptr->paddr = (long)procaddr; /* where we "ret" to */ *--saddr = savsp; /* fake frame ptr for procaddr */ savsp = (unsigned long) saddr; /* this must match what ctxsw expects: flags, regs, old SP */ /* emulate 386 "pushal" instruction */ *--saddr = 0; *--saddr = 0; /* %eax */ *--saddr = 0; /* %ecx */ *--saddr = 0; /* %edx */ *--saddr = 0; /* %ebx */ *--saddr = 0; /* %esp; fill in below */ pushsp = saddr; *--saddr = savsp; /* %ebp */ *--saddr = 0; /* %esi */ *--saddr = 0; /* %edi */ *pushsp = pptr->pesp = (unsigned long)saddr; restore(ps); va_end(ap); return pid; }