home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / KSUBR.C < prev    next >
C/C++ Source or Header  |  1994-08-26  |  13KB  |  432 lines

  1. /* Machine or compiler-dependent portions of kernel
  2.  * Turbo-C version for PC
  3.  * Copyright 1991 Phil Karn, KA9Q
  4.  */
  5. #ifdef MSDOS
  6. #include <dos.h>
  7. #endif
  8. #include "global.h"
  9. #include "proc.h"
  10. #ifndef UNIX
  11. #include "pc.h"
  12. #endif
  13. #include "commands.h"
  14. #include "socket.h"
  15.   
  16. #ifdef MSDOS
  17. char *Taskers[] = {
  18.     "",
  19.     "DoubleDos",
  20.     "DesqView",
  21.     "Windows",
  22.     "DOS 5/6",
  23.     "OS/2 DOS",
  24.     "DPMI"
  25. };
  26.   
  27. static oldNull;
  28.   
  29. /* Template for contents of jmp_buf in Turbo C */
  30. struct env {
  31.     unsigned        sp;
  32.     unsigned        ss;
  33.     unsigned        flag;
  34.     unsigned        cs;
  35.     unsigned        ip;
  36.     unsigned        bp;
  37.     unsigned        di;
  38.     unsigned        es;
  39.     unsigned        si;
  40.     unsigned        ds;
  41. };
  42. #endif
  43.   
  44. #ifdef UNIX
  45. /*
  46.  * There are several different ways to implement jmp_buf's.  We use macros to
  47.  * extract the fields.  Note that these must expand into lvalues, because we
  48.  * load them during process initialization.  Current code only uses _SP and
  49.  * _PC; this may change.
  50.  *
  51.  * I should fold the DOS code into this, but then I need to worry about
  52.  * segments.  No thanks.
  53.  */
  54.   
  55. #ifdef M_UNIX
  56. /*
  57.  * I am unsure of these; the i386 contents are not documented in 3.2.2.  I
  58.  * guessed at them by comparing "info regs" with the contents of a jmp_buf
  59.  * immediately after a setjmp().
  60.  */
  61. #define _PC(p) (p->env[5])
  62. #define _SP(p) (p->env[4])
  63. #define _BP(p) (p->env[3])
  64. #endif
  65.   
  66. #ifdef linux
  67. #define _PC(p) (p->env->__pc)
  68. #define _SP(p) (p->env->__sp)
  69. #define _BP(p) (p->env->__bp)
  70. #endif
  71.   
  72. #endif
  73.   
  74. #ifndef UNIX
  75. static int chkintstk __ARGS((void));
  76. #endif
  77.   
  78. void
  79. kinit()
  80. {
  81. #ifndef UNIX
  82.     int i;
  83.   
  84.     /* Initialize interrupt stack for high-water-mark checking */
  85.     for(i=0;i<512;i++)
  86.         Intstk[i] = STACKPAT;
  87.   
  88.     /* Remember location 0 pattern to detect null pointer derefs */
  89.     oldNull = *(unsigned short *)NULL;
  90. #endif
  91. }
  92. /* Print process table info
  93.  * Since things can change while ps is running, the ready proceses are
  94.  * displayed last. This is because an interrupt can make a process ready,
  95.  * but a ready process won't spontaneously become unready. Therefore a
  96.  * process that changes during ps may show up twice, but this is better
  97.  * than not having it showing up at all.
  98.  */
  99. int
  100. ps(argc,argv,p)
  101. int argc;
  102. char *argv[];
  103. void *p;
  104. {
  105.     register struct proc *pp;
  106. #ifndef UNIX
  107.     register struct env *ep;
  108. #endif
  109.     int i;
  110.   
  111. #ifdef UNIX
  112.     tprintf("Uptime %s",tformat(secclock()));
  113. #else
  114.     tprintf("Uptime %s Stack %x max intstk %u psp %04x",tformat(secclock()),
  115.     getss(),chkintstk(),_psp);
  116.     if(Mtasker != 0){
  117.         tprintf("\nRunning under %s",Taskers[Mtasker]);
  118.     }
  119. #endif
  120.     tputs("\n");
  121.   
  122. #ifdef UNIX
  123.     tputs("PID      SP       maxstk   stksize  event    fl  in  out  name\n");
  124.   
  125.     for (pp = Susptab; pp != NULLPROC; pp = pp->next)
  126.     {
  127.         if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d %3d  %s\n",
  128.             pp, _SP(pp), pp->stksize, stkutil(pp), pp->event,
  129.             pp->i_state ? 'I' : ' ',
  130.             (pp->state & WAITING) ? 'W' : ' ',
  131.             (pp->state & SUSPEND) ? 'S' : ' ',
  132.             pp->input, pp->output, pp->name) == EOF)
  133.             return 0;
  134.     }
  135.     for (i = 0; i < PHASH; i++)
  136.     {
  137.         for (pp = Waittab[i]; pp != NULLPROC; pp = pp->next)
  138.         {
  139.             if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d %3d  %s\n",
  140.                 pp, _SP(pp), pp->stksize, stkutil(pp),
  141.                 pp->event,
  142.                 pp->i_state ? 'I' : ' ',
  143.                 (pp->state & WAITING) ? 'W' : ' ',
  144.                 (pp->state & SUSPEND) ? 'S' : ' ',
  145.                 pp->input, pp->output, pp->name) == EOF)
  146.                 return 0;
  147.         }
  148.     }
  149.     for (pp = Rdytab; pp != NULLPROC; pp = pp->next)
  150.     {
  151.         if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d %3d  %s\n",
  152.             pp, _SP(pp), pp->stksize, stkutil(pp),
  153.             pp->event,
  154.             pp->i_state ? 'I' : ' ',
  155.             (pp->state & WAITING) ? 'W' : ' ',
  156.             (pp->state & SUSPEND) ? 'S' : ' ',
  157.             pp->input, pp->output, pp->name) == EOF)
  158.             return 0;
  159.     }
  160.     if( Curproc != NULLPROC)
  161.     {
  162.         if (tprintf("%8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %c%c%c %3d %3d  %s\n",
  163.             Curproc, _SP(Curproc), Curproc->stksize,
  164.             stkutil(Curproc), Curproc->event,
  165.             Curproc->i_state ? 'I' : ' ',
  166.             (Curproc->state & WAITING) ? 'W' : ' ',
  167.             (Curproc->state & SUSPEND) ? 'S' : ' ',
  168.             Curproc->input, Curproc->output,
  169.             Curproc->name) == EOF)
  170.             return 0;
  171.     }
  172.   
  173. #else /* UNIX */
  174.   
  175.     tputs("PID  SP        maxstk    stksize   event     fl  in  out  name\n");
  176.   
  177.     for(pp = Susptab;pp != NULLPROC;pp = pp->next){
  178.         ep = (struct env *)&pp->env;
  179.         if(tprintf("%4.4x %-10lx%-10u%-10u%-10lx%c%c%c %3d %3d  %s\n",
  180.             FP_SEG(pp),
  181.             ptol(MK_FP(ep->ss,ep->sp)),
  182.             pp->stksize,
  183.             stkutil(pp),
  184.             ptol(pp->event),
  185.             pp->i_state ? 'I' : ' ',
  186.             (pp->state & WAITING) ? 'W' : ' ',
  187.             (pp->state & SUSPEND) ? 'S' : ' ',
  188.             pp->input, pp->output,
  189.             pp->name) == EOF)
  190.             return 0;
  191.     }
  192.     for(i=0;i<PHASH;i++){
  193.         for(pp = Waittab[i];pp != NULLPROC;pp = pp->next){
  194.             ep = (struct env *)&pp->env;
  195.             if(tprintf("%4.4x %-10lx%-10u%-10u%-10lx%c%c%c %2d %2d  %s\n",
  196.                 FP_SEG(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
  197.                 ptol(pp->event),
  198.                 pp->i_state ? 'I' : ' ',
  199.                 (pp->state & WAITING) ? 'W' : ' ',
  200.                 (pp->state & SUSPEND) ? 'S' : ' ',
  201.                 pp->input,pp->output,
  202.                 pp->name) == EOF)
  203.                 return 0;
  204.         }
  205.     }
  206.     for(pp = Rdytab;pp != NULLPROC;pp = pp->next){
  207.         ep = (struct env *)&pp->env;
  208.         if(tprintf("%4.4x %-10lx%-10u%-10u          %c%c%c %2d %2d  %s\n",
  209.             FP_SEG(pp),ptol(MK_FP(ep->ss,ep->sp)),pp->stksize,stkutil(pp),
  210.             pp->i_state ? 'I' : ' ',
  211.             (pp->state & WAITING) ? 'W' : ' ',
  212.             (pp->state & SUSPEND) ? 'S' : ' ',
  213.             pp->input,pp->output,
  214.             pp->name) == EOF)
  215.             return 0;
  216.     }
  217.     if(Curproc != NULLPROC){
  218.         ep = (struct env *)&Curproc->env;
  219.         tprintf("%4.4x %-10lx%-10u%-10u          %c   %2d %2d  %s\n",
  220.         FP_SEG(Curproc),ptol(MK_FP(ep->ss,ep->sp)),Curproc->stksize,
  221.         stkutil(Curproc),
  222.         Curproc->i_state ? 'I' : ' ',
  223.         Curproc->input,Curproc->output,
  224.         Curproc->name);
  225.     }
  226.   
  227. #endif /* UNIX */
  228.   
  229.     return 0;
  230. }
  231. int
  232. stkutil(pp)
  233. struct proc *pp;
  234. {
  235.     unsigned i;
  236.     register int16 *sp;
  237.   
  238. #ifdef UNIX
  239.     if (pp->stack == 0xC0000000) /* can't check system stack, dynamic */
  240.         return pp->stksize;
  241. #endif
  242.     i = pp->stksize;
  243.     for(sp = pp->stack;*sp == STACKPAT && sp < pp->stack + pp->stksize;sp++)
  244.         i--;
  245.     return i;
  246. }
  247. /* Return number of used words in interrupt stack. Note hardwired value
  248.  * for stack size; this is also found in the various .asm files
  249.  */
  250. #ifndef UNIX
  251. static int
  252. chkintstk()
  253. {
  254.     register int i;
  255.     register int16 *cp;
  256.   
  257.     for(i=512,cp = Intstk; i != 0 && *cp == STACKPAT; cp++)
  258.         i--;
  259.     return i;
  260. }
  261. #endif
  262.   
  263. /* Verify that stack pointer for current process is within legal limits;
  264.  * also check that no one has dereferenced a null pointer
  265.  */
  266. #ifdef UNIX
  267. static void
  268. __chkstk_internal(spp)
  269. int16 spp;
  270. {
  271.     int16 *sp, *sbase, *stop;
  272.   
  273.     sp = &spp;      /* close enough for government work */
  274.     sbase = Curproc->stack;
  275.     if(sbase == NULL)
  276.         return; /* Main task -- too hard to check */
  277.     stop = sbase + Curproc->stksize;
  278.     if(sp < sbase || sp >= stop){
  279.         printf("Stack violation, process %s\n",Curproc->name);
  280.         printf("SP = %lx, legal stack range [%lx,%lx)\n",
  281.         ptol(sp),ptol(sbase),ptol(stop));
  282.         fflush(stdout);
  283.         killself();
  284.     }
  285. }
  286. #endif
  287.   
  288. void
  289. chkstk()
  290. {
  291. #ifdef UNIX
  292.     __chkstk_internal(0);   /* must have an argument to take address of */
  293. #else
  294.     int16 *sbase;
  295.     int16 *stop;
  296.     int16 *sp;
  297. #ifdef MULTITASK
  298.     extern int Nokeys;              /* indicates we are shelled out [pc.c]*/
  299. #endif
  300.   
  301.     sp = MK_FP(_SS,_SP);
  302.     if(_SS == _DS){
  303.         /* Probably in interrupt context */
  304.         return;
  305.     }
  306.     sbase = Curproc->stack;
  307.     if(sbase == NULL)
  308.         return; /* Main task -- too hard to check */
  309.   
  310.     stop = sbase + Curproc->stksize;
  311.     if(sp < sbase || sp >= stop){
  312.         printf("Stack violation, process %s\n",Curproc->name);
  313.         printf("SP = %lx, legal stack range [%lx,%lx)\n",
  314.         ptol(sp),ptol(sbase),ptol(stop));
  315.         fflush(stdout);
  316.         killself();
  317.     }
  318.     if(*(unsigned short *)NULL != oldNull){
  319. #ifdef MULTITASK
  320.         if(!Nokeys)     /* don't complain if we are shelled out */
  321. #endif
  322.             printf("WARNING: Location 0 smashed, process %s\n",Curproc->name);
  323.         *(unsigned short *)NULL = oldNull;
  324.         fflush(stdout);
  325.     }
  326. #endif /* UNIX */
  327. }
  328. /* Machine-dependent initialization of a task */
  329. void
  330. psetup(pp,iarg,parg1,parg2,pc)
  331. struct proc *pp;        /* Pointer to task structure */
  332. int iarg;               /* Generic integer arg */
  333. void *parg1;            /* Generic pointer arg #1 */
  334. void *parg2;            /* Generic pointer arg #2 */
  335. void (*pc) __ARGS((int,void *,void *));           /* Initial execution address */
  336. {
  337.     register int *stktop;
  338. #ifndef UNIX
  339.     register struct env *ep;
  340. #endif
  341.   
  342.     /* Set up stack to make it appear as if the user's function was called
  343.      * by killself() with the specified arguments. When the user returns,
  344.      * killself() automatically cleans up.
  345.      *
  346.      * First, push args on stack in reverse order, simulating what C
  347.      * does just before it calls a function.
  348.      */
  349.     stktop = (int *)(pp->stack + pp->stksize);
  350. #ifdef LINUX
  351.     *--stktop = 0;      /* dummy stack frame to terminate backtrace */
  352.     *--stktop = 0;
  353. #ifdef LITTLE_ENDIAN
  354.     *--stktop = (((unsigned long) parg2 & 0xFFFF0000) >> 16) & 0x0000FFFF;
  355.     *--stktop = ((unsigned long) parg2 & 0x0000FFFF);
  356.     *--stktop = (((unsigned long) parg1 & 0xFFFF0000) >> 16) & 0x0000FFFF;
  357.     *--stktop = ((unsigned long) parg1 & 0x0000FFFF);
  358.     *--stktop = (((unsigned long) iarg & 0xFFFF0000) >> 16) & 0x0000FFFF;
  359.     *--stktop = ((unsigned long) iarg & 0x0000FFFF);
  360.     *--stktop = (((unsigned long) killself & 0xFFFF0000) >> 16) & 0x0000FFFF;
  361.     *--stktop = ((unsigned long) killself & 0x0000FFFF);
  362. #else
  363.     *--stktop = ((unsigned long) parg2 & 0x0000FFFF);
  364.     *--stktop = (((unsigned long) parg2 & 0xFFFF0000) >> 16) & 0x0000FFFF;
  365.     *--stktop = ((unsigned long) parg1 & 0x0000FFFF);
  366.     *--stktop = (((unsigned long) parg1 & 0xFFFF0000) >> 16) & 0x0000FFFF;
  367.     *--stktop = ((unsigned long) iarg & 0x0000FFFF);
  368.     *--stktop = (((unsigned long) iarg & 0xFFFF0000) >> 16) & 0x0000FFFF;
  369.     *--stktop = ((unsigned long) killself & 0x0000FFFF);
  370.     *--stktop = (((unsigned long) killself & 0xFFFF0000) >> 16) & 0x0000FFFF;
  371. #endif
  372. #else /* UNIX */
  373.   
  374. #ifdef  LARGEDATA
  375.     *--stktop = FP_SEG(parg2);
  376. #endif
  377.     *--stktop = FP_OFF(parg2);
  378. #ifdef  LARGEDATA
  379.     *--stktop = FP_SEG(parg1);
  380. #endif
  381.     *--stktop = FP_OFF(parg1);
  382.     *--stktop = iarg;
  383.   
  384.     /* Now push the entry address of killself(), simulating the call to
  385.      * the user function.
  386.      */
  387. #ifdef  LARGECODE
  388.     *--stktop = FP_SEG(killself);
  389. #endif
  390.     *--stktop = FP_OFF(killself);
  391. #endif
  392.   
  393.     /* Set up task environment. Note that for Turbo-C, the setjmp
  394.      * sets the interrupt enable flag in the environment so that
  395.      * interrupts will be enabled when the task runs for the first time.
  396.      * Note that this requires newproc() to be called with interrupts
  397.      * enabled!
  398.      */
  399.     setjmp(pp->env);
  400. #ifdef UNIX
  401.     _SP(pp) = stktop;
  402.     _BP(pp) = stktop;
  403.     _PC(pp) = pc;
  404. #else
  405.     ep = (struct env *)&pp->env;
  406.     ep->ss = FP_SEG(stktop);
  407.     ep->sp = FP_OFF(stktop);
  408.     ep->cs = FP_SEG(pc);    /* Doesn't hurt in small model */
  409.     ep->ip = FP_OFF(pc);
  410. #endif
  411.     /* Task initially runs with interrupts on */
  412.     pp->i_state = 1;
  413. }
  414. unsigned
  415. phash(event)
  416. void *event;
  417. {
  418.     register unsigned x;
  419.   
  420.     /* Fold the two halves of the pointer */
  421. #ifdef UNIX
  422.     x = (unsigned) event;
  423. #else
  424.     x = FP_SEG(event) ^ FP_OFF(event);
  425. #endif
  426.   
  427.     /* If PHASH is a power of two, this will simply mask off the
  428.      * higher order bits
  429.      */
  430.     return x % PHASH;
  431. }
  432.