home *** CD-ROM | disk | FTP | other *** search
- /* Machine or compiler-dependent portions of kernel
- * Turbo-C version for PC
- *
- * Copyright 1991 Phil Karn, KA9Q
- */
- #include <stdio.h>
- #include <dos.h>
- #include "global.h"
- #include "proc.h"
- #include "pc.h"
- #include "commands.h"
-
- static char *Taskers[] = {
- "",
- "DoubleDos",
- "DesqView",
- "Windows",
- };
-
-
- static oldNull;
-
- /* Template for contents of jmp_buf in Turbo C */
- struct env {
- unsigned sp;
- unsigned ss;
- unsigned flag;
- unsigned cs;
- unsigned ip;
- unsigned bp;
- unsigned di;
- unsigned es;
- unsigned si;
- unsigned ds;
- };
-
- static int chkintstk __ARGS((void));
- static int stkutil __ARGS((struct proc *pp));
-
- void
- kinit()
- {
- int i;
-
- /* Initialize interrupt stack for high-water-mark checking */
- for(i=0;i<512;i++)
- Intstk[i] = STACKPAT;
-
- /* Remember location 0 pattern to detect null pointer derefs */
- oldNull = *(unsigned short *)NULL;
-
- }
- /* Print process table info
- * Since things can change while ps is running, the ready proceses are
- * displayed last. This is because an interrupt can make a process ready,
- * but a ready process won't spontaneously become unready. Therefore a
- * process that changes during ps may show up twice, but this is better
- * than not having it showing up at all.
- */
- int
- ps(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register struct proc *pp;
- register struct env *ep;
- int i;
-
- tprintf("Uptime %s Stack %x max intstk %u",tformat(secclock()),
- getss(),chkintstk());
- if(Mtasker != 0){
- tprintf(" Running under %s",Taskers[Mtasker]);
- }
- tprintf("\n");
-
- tprintf("PID SP stksize maxstk event fl in out name\n");
-
- for(pp = Susptab;pp != NULLPROC;pp = pp->next){
- ep = (struct env *)&pp->env;
- if(tprintf("%-10lx%-10lx%-10u%-10u%-10lx%c%c%c %3d %3d %s\n",
- ptol(pp),
- ptol(MK_FP(ep->ss,ep->sp)),
- pp->stksize,
- stkutil(pp),
- ptol(pp->event),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->input, pp->output,
- pp->name) == EOF)
- return 0;
- }
- for(i=0;i<PHASH;i++){
- for(pp = Waittab[i];pp != NULLPROC;pp = pp->next){
- ep = (struct env *)&pp->env;
- if(tprintf("%-10lx%-10lx%-10u%-10u%-10lx%c%c%c %2d %2d %s\n",
- ptol(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
- ptol(pp->event),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->input,pp->output,
- pp->name) == EOF)
- return 0;
- }
- }
- for(pp = Rdytab;pp != NULLPROC;pp = pp->next){
- ep = (struct env *)&pp->env;
- if(tprintf("%-10lx%-10lx%-10u%-10u %c%c%c %2d %2d %s\n",
- ptol(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
- pp->i_state ? 'I' : ' ',
- (pp->state & WAITING) ? 'W' : ' ',
- (pp->state & SUSPEND) ? 'S' : ' ',
- pp->input,pp->output,
- pp->name) == EOF)
- return 0;
- }
- if(Curproc != NULLPROC){
- ep = (struct env *)&Curproc->env;
- tprintf("%-10lx%-10lx%-10u%-10u %c %2d %2d %s\n",
- ptol(Curproc),ptol(MK_FP(ep->ss,ep->sp)),Curproc->stksize,
- stkutil(Curproc),
- Curproc->i_state ? 'I' : ' ',
- Curproc->input,Curproc->output,
- Curproc->name);
- }
- return 0;
- }
- static int
- stkutil(pp)
- struct proc *pp;
- {
- unsigned i;
- register int16 *sp;
-
- i = pp->stksize;
- for(sp = pp->stack;*sp == STACKPAT && sp < pp->stack + pp->stksize;sp++)
- i--;
- return i;
- }
- /* Return number of used words in interrupt stack. Note hardwired value
- * for stack size; this is also found in the various .asm files
- */
- static int
- chkintstk()
- {
- register int i;
- register int16 *cp;
-
- for(i=512,cp = Intstk; i != 0 && *cp == STACKPAT; cp++)
- i--;
- return i;
- }
-
- /* Verify that stack pointer for current process is within legal limits;
- * also check that no one has dereferenced a null pointer
- */
- void
- chkstk()
- {
- int16 *sbase;
- int16 *stop;
- int16 *sp;
-
- sp = MK_FP(_SS,_SP);
- if(_SS == _DS){
- /* Probably in interrupt context */
- return;
- }
- sbase = Curproc->stack;
- if(sbase == NULL)
- return; /* Main task -- too hard to check */
-
- stop = sbase + Curproc->stksize;
- if(sp < sbase || sp >= stop){
- printf("Stack violation, process %s\n",Curproc->name);
- printf("SP = %lx, legal stack range [%lx,%lx)\n",
- ptol(sp),ptol(sbase),ptol(stop));
- fflush(stdout);
- killself();
- }
- if(*(unsigned short *)NULL != oldNull){
- printf("WARNING: Location 0 smashed, process %s\n",Curproc->name);
- *(unsigned short *)NULL = oldNull;
- fflush(stdout);
- }
- }
- /* Machine-dependent initialization of a task */
- void
- psetup(pp,iarg,parg1,parg2,pc)
- struct proc *pp; /* Pointer to task structure */
- int iarg; /* Generic integer arg */
- void *parg1; /* Generic pointer arg #1 */
- void *parg2; /* Generic pointer arg #2 */
- void (*pc)(); /* Initial execution address */
- {
- register int *stktop;
- register struct env *ep;
-
- /* Set up stack to make it appear as if the user's function was called
- * by killself() with the specified arguments. When the user returns,
- * killself() automatically cleans up.
- *
- * First, push args on stack in reverse order, simulating what C
- * does just before it calls a function.
- */
- stktop = (int *)(pp->stack + pp->stksize);
- #ifdef LARGEDATA
- *--stktop = FP_SEG(parg2);
- #endif
- *--stktop = FP_OFF(parg2);
- #ifdef LARGEDATA
- *--stktop = FP_SEG(parg1);
- #endif
- *--stktop = FP_OFF(parg1);
- *--stktop = iarg;
-
- /* Now push the entry address of killself(), simulating the call to
- * the user function.
- */
- #ifdef LARGECODE
- *--stktop = FP_SEG(killself);
- #endif
- *--stktop = FP_OFF(killself);
-
- /* Set up task environment. Note that for Turbo-C, the setjmp
- * sets the interrupt enable flag in the environment so that
- * interrupts will be enabled when the task runs for the first time.
- * Note that this requires newproc() to be called with interrupts
- * enabled!
- */
- setjmp(pp->env);
- ep = (struct env *)&pp->env;
- ep->ss = FP_SEG(stktop);
- ep->sp = FP_OFF(stktop);
- ep->cs = FP_SEG(pc); /* Doesn't hurt in small model */
- ep->ip = FP_OFF(pc);
- /* Task initially runs with interrupts on */
- pp->i_state = 1;
- }
- unsigned
- phash(event)
- void *event;
- {
- register unsigned x;
-
- /* Fold the two halves of the pointer */
- x = FP_SEG(event) ^ FP_OFF(event);
-
- /* If PHASH is a power of two, this will simply mask off the
- * higher order bits
- */
- return x % PHASH;
- }
-