home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_sys5 / unixkit.tgz / unixkit.tar / unixkit / lwp / kernel.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-23  |  16.9 KB  |  772 lines

  1. /* Non pre-empting synchronization kernel, using LWP on SunOS
  2.  * Portions Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. #include <stdio.h>
  5. #include <lwp/lwp.h>
  6. #include <lwp/lwpmachdep.h>
  7. #include <lwp/lwperror.h>
  8. #include <memory.h>
  9. #include <signal.h>
  10. #include "global.h"
  11. #include "mbuf.h"
  12. #include "proc.h"
  13. #include "timer.h"
  14. #include "socket.h"
  15. #include "daemon.h"
  16.  
  17.  
  18. #define KERNELLOG    /* keep a nice log of major kernel events */
  19. #define STACKDEBUG    /* silently test all processes for stack overrun */
  20. #undef TRACEDEBUG    /* one-line message for each major routine */
  21. #undef THREADDEBUG    /* Gobs of ps-like output constantly */
  22.  
  23.  
  24. struct proc *Curproc;        /* Currently running process */
  25. struct proc *Rdytab;        /* Processes ready to run (not including curproc) */
  26. struct proc *Waittab[PHASH];    /* Waiting process list */
  27. static struct mbuf *Killq;
  28.  
  29. static void addproc __ARGS((struct proc *entry));
  30. static void delproc __ARGS((struct proc *entry));
  31. static void startproc __ARGS((int pp, int pc));
  32.  
  33. #ifdef KERNELLOG
  34. #define KLOG_SIZE 32
  35. void kernellog();
  36. void kernel_segv();
  37. int klog_i;
  38. struct {
  39.     char *routine;        /* "psignal" */
  40.     char *detail;        /* "enter" */
  41.     char proc_name[32];    /* "display" */
  42.     int i;            /* interrupts */
  43. } klog[KLOG_SIZE];
  44. #define KL(qa, qb, qc) kernellog(qa, qb, qc)
  45. #else
  46. #define KL(qa, qb, qc)
  47. #endif
  48.  
  49. #define LWP_STACKSIZE  8192    /* requested stack size for all processes */
  50.  
  51. /* This is the macro that tests if a given process has run off the stack */
  52. #define LWP_TEST(q,t) {if(((q)->stksize)>0){if(*((q)->stackbottom)!=STACKBOT){printf("%s: LWP stack overflow!\n",t);abort();}}}
  53.  
  54. /* Create a process descriptor for the main function. Must be actually
  55.  * called from the main function!
  56.  */
  57. struct proc *
  58. mainproc(name)
  59. char *name;
  60. {
  61.     register struct proc *pp;
  62.  
  63.     /* Create process descriptor */
  64.     pp = (struct proc *)callocw(1,sizeof(struct proc));
  65.  
  66.     /* Find our own thread ID */
  67.     if(lwp_self(&pp->tid) < 0){
  68.         lwp_perror("lwp_self");
  69.         abort();
  70.     }
  71.     /* Multiplex the libc stuff (errno) */
  72.     if(lwp_libcset(pp->tid) < 0){
  73.         lwp_perror("lwp_libcset");
  74.         abort();
  75.     }
  76.     /* Create name */
  77.     pp->name = strdup(name);
  78.     pp->stksize = 0;
  79.  
  80.         /* Task initially runs with interrupts on */
  81.         pp->i_state = 1;
  82.  
  83.     /* Make current */
  84.     pp->state = READY;
  85.     Curproc = pp;
  86.  
  87.     return pp;
  88. }
  89. /* Create a new, ready process and return pointer to descriptor.
  90.  * The general registers are not initialized, but optional args are pushed
  91.  * on the stack so they can be seen by a C function.
  92.  */
  93. struct proc *
  94. newproc(name,stksize,pc,iarg,parg1,parg2,freeargs)
  95. char *name;        /* Arbitrary user-assigned name string */
  96. unsigned int stksize;    /* Stack size in words to allocate */
  97. void (*pc)();        /* Initial execution address */
  98. int iarg;        /* Integer argument (argc) */
  99. void *parg1;        /* Generic pointer argument #1 (argv) */
  100. void *parg2;        /* Generic pointer argument #2 (session ptr) */
  101. int freeargs;        /* If set, free arg list on parg1 at termination */
  102. {
  103.     register struct proc *pp;
  104.     int i, j, *w;
  105.  
  106.     /* Create process descriptor */
  107.     pp = (struct proc *)callocw(1,sizeof(struct proc));
  108.  
  109.     /* Create name */
  110.     pp->name = strdup(name);
  111.  
  112.     pp->stksize = LWP_STACKSIZE;
  113.     pp->stackbottom = (int *)malloc((pp->stksize) * sizeof(int));
  114.     pp->stack = (pp->stackbottom) + (pp->stksize)- 4;
  115.     pp->stack = pp->stack & 0xfffffff8;
  116.  
  117.         /* Task initially runs with interrupts on */
  118.         pp->i_state = 1;
  119.     pp->freeargs = freeargs;
  120.     pp->iarg = iarg;
  121.     pp->parg1 = parg1;
  122.     pp->parg2 = parg2;
  123.  
  124.     /* Inherit creator's input and output sockets */
  125.     usesock(Curproc->input);
  126.     pp->input = Curproc->input;
  127.     usesock(Curproc->output);
  128.     pp->output = Curproc->output;
  129.  
  130.     /* Clear out the rest of the fields */
  131.     pp->prev = pp->next = NULLPROC;
  132.     pp->outbuf = (struct mbuf *)NULL;
  133.  
  134.         /* Add to ready process table */
  135.         pp->state = READY;
  136.  
  137.     /* Initialize the stack (for paranoia purposes!) */
  138.     for(w=(pp->stackbottom); w<(pp->stack); w++) *w = STACKPAT;
  139.  
  140.     /* Initialize stack for high-water check */
  141.     *(pp->stackbottom) = STACKBOT;    /* test this each switch! */
  142.  
  143.         addproc(pp);
  144.  
  145.     if(lwp_create(&pp->tid, startproc, MINPRIO, 0, pp->stack, 2,
  146.               (int)pp,(int)pc) < 0) {
  147.          lwp_perror("lwp_create");
  148.          delproc(pp);
  149.          free(pp->name);
  150.          free((char *)pp->stackbottom);
  151.          free((char *)pp);
  152.          return NULLPROC;
  153.     }
  154.  
  155.     /* Multiplex the libc stuff (errno) */
  156.     if(lwp_libcset(pp->tid) < 0){
  157.         lwp_perror("lwp_libcset");
  158.         abort();
  159.     }
  160.     
  161. #ifdef TRACEDEBUG
  162.     printf("Added Process %s\n",pp->name);
  163. #endif
  164. #ifdef THREADDEBUG
  165.     debug_lwp();
  166. #endif
  167. #ifdef STACKDEBUG
  168.     lwp_stackscan();
  169. #endif
  170.     KL("addproc", "", pp);
  171.  
  172.     return pp;
  173. }
  174.  
  175. static void
  176. startproc(pp, pc)
  177. struct proc *pp;
  178. int pc;
  179. {
  180.      void (*func)();
  181.      func = (void (*)()) pc;
  182.      Curproc = (struct proc *) pp;
  183.      delproc (Curproc);
  184. #ifdef TRACEDEBUG
  185.     printf("Started Process %s\n",Curproc->name);
  186. #endif
  187. #ifdef THREADDEBUG
  188.     debug_lwp();
  189. #endif
  190. #ifdef STACKDEBUG
  191.     lwp_stackscan();
  192. #endif
  193.      KL("startproc","begin",pp);
  194.      (*func)(Curproc->iarg,Curproc->parg1,Curproc->parg2);
  195.      KL("startproc","end",pp);
  196.      killself();
  197. }
  198.  
  199. /* Free resources allocated to specified process. If a process wants to kill
  200.  * itself, the reaper is called to do the dirty work. This avoids some
  201.  * messy situations that would otherwise occur, like freeing your own stack.
  202.  */
  203. void
  204. killproc(pp)
  205. register struct proc *pp;
  206. {
  207.     int i;
  208.     char **argv;
  209.  
  210.     if(pp == NULLPROC)
  211.         return;
  212.     /* Don't check the stack here! Will cause infinite recursion if
  213.      * called from a stack error
  214.      */
  215.  
  216.     if(pp == Curproc)
  217.         killself();    /* Doesn't return */
  218.  
  219.     /* Close any open sockets */
  220.     freesock(pp);
  221.  
  222.     close_s(pp->input);
  223.     close_s(pp->output);
  224.  
  225.     /* Stop alarm clock in case it's running */
  226.     stop_timer(&pp->alarm);
  227.  
  228.     /* Alert everyone waiting for this proc to die */
  229.     psignal(pp,0);
  230.  
  231.     /* Remove from appropriate table */
  232.     delproc(pp);
  233.  
  234. #ifdef TRACEDEBUG
  235.     printf("Killed Process %s\n",pp->name);
  236. #endif
  237.         KL("killproc","",pp);
  238.     if(lwp_destroy(pp->tid) < 0){
  239.         lwp_perror("killproc: lwp_destroy:");
  240.         abort();
  241.     }
  242.  
  243.     /* Free allocated memory resources */
  244.     if(pp->freeargs){
  245.         argv = pp->parg1;
  246.         while(pp->iarg-- != 0){
  247.             free(*argv);
  248.             argv++;
  249.         }
  250.         free(pp->parg1);
  251.     }
  252.     free(pp->name);
  253.     free(pp->outbuf);
  254.     free((char *)pp->stackbottom);
  255.     free((char *)pp);
  256. }
  257.  
  258. /* Terminate current process by sending a request to the killer process.
  259.  * Automatically called when a process function returns. Does not return.
  260.  */
  261. void
  262. killself()
  263. {
  264.     register struct mbuf *bp;
  265.     bp = pushdown(NULLBUF,sizeof(Curproc));
  266.     memcpy(bp->data,(char *)&Curproc,sizeof(Curproc));
  267.     enqueue(&Killq,bp);
  268.     /* "Wait for me; I will be merciful and quick." */
  269.     for(;;)
  270.         lwp_suspend(SELF);
  271. }
  272.  
  273. /* Process used by processes that want to kill themselves */
  274. void
  275. killer(i,v1,v2)
  276. int i;
  277. void *v1;
  278. void *v2;
  279. {
  280.     struct proc *pp;
  281.     struct mbuf *bp;
  282.  
  283.     for(;;){
  284.         while(Killq == NULLBUF)
  285.             pwait(&Killq);
  286.         bp = dequeue(&Killq);
  287.         pullup(&bp,(char *)&pp,sizeof(pp));
  288.         free_p(bp);
  289.         if(pp != Curproc)    /* We're immortal */
  290.             killproc(pp);
  291.     }                        
  292. }
  293.  
  294. /* Inhibit a process from running */
  295. void
  296. suspend(pp)
  297. struct proc *pp;
  298. {
  299.     if(pp == NULLPROC)
  300.         return;
  301. #ifdef TRACEDEBUG
  302.     printf("Suspended Process %s\n",pp->name);
  303. #endif
  304.         KL("suspend","",pp);
  305.     if(pp != Curproc)
  306.         delproc(pp);    /* Running process isn't on any list */
  307.     pp->state |= SUSPEND;
  308.     if(pp != Curproc)
  309.         addproc(pp);    /* pwait will do it for us */
  310.     else
  311.         if(lwp_suspend(SELF) < 0){
  312.             lwp_perror("suspend: lwp_suspend");
  313.             abort();
  314.         }
  315. }
  316. /* Restart suspended process */
  317. void
  318. resume(pp)
  319. struct proc *pp;
  320. {
  321.     if(pp == NULLPROC)
  322.         return;
  323. #ifdef TRACEDEBUG
  324.     printf("Resumed Process %s\n",pp->name);
  325. #endif
  326.     KL("resume","",pp);
  327.     delproc(pp);    /* Can't be Curproc! */
  328.     pp->state &= ~SUSPEND;
  329.     addproc(pp);
  330. }
  331.  
  332. /* Wakeup waiting process, regardless of event it's waiting for. The process
  333.  * will see a return value of "val" from its pwait() call.
  334.  */
  335. void
  336. alert(pp,val)
  337. struct proc *pp;
  338. int val;
  339. {
  340.     if(pp == NULLPROC)
  341.         return;
  342. #ifdef    notdef
  343.     if((pp->state & WAITING) == 0)
  344.         return;
  345. #endif
  346. #ifdef TRACEDEBUG
  347.     printf("Alerted Process %s\n",pp->name);
  348. #endif
  349.     KL("alert","",pp);
  350.     if(pp != Curproc)
  351.         delproc(pp);
  352.     pp->state &= ~WAITING;
  353.     pp->retval = val;
  354.     pp->event = 0;
  355.     if(pp != Curproc)
  356.         addproc(pp);
  357.     if(lwp_resume(pp->tid) < 0){
  358.         lwp_perror("alert: lwp_resume");
  359.         abort();
  360.     }
  361. }
  362.  
  363. /* Post a wait on a specified event and give up the CPU until it happens. The
  364.  * null event is special: it means "I don't want to block on an event, but let
  365.  * somebody else run for a while". It can also mean that the present process
  366.  * is terminating; in this case the wait never returns.
  367.  *
  368.  * Pwait() returns 0 if the event was signaled; otherwise it returns the
  369.  * arg in an alert() call. Pwait must not be called from interrupt level.
  370.  *
  371.  */
  372. int
  373. pwait(event)
  374. void *event;
  375. {
  376.     register struct proc *oldproc;
  377.     int tmp;
  378.     struct proc *pp;
  379.     
  380. #ifdef TRACEDEBUG
  381.     if(event){
  382.         printf("PWAIT: (%s)  event=%x\n",Curproc->name,event);
  383.     } else {
  384.         printf("PWAIT: (%s)  NULL\n",Curproc->name);
  385.     }
  386. #endif
  387. #ifdef THREADDEBUG
  388.     debug_lwp();
  389. #endif
  390. #ifdef STACKDEBUG
  391.     lwp_stackscan();
  392. #endif
  393.     pp = Curproc;
  394.     KL("pwait","enter",pp);
  395.     pp->i_state = istate();
  396.     Curproc->event = event;
  397.     if(event != NULL) {
  398.          Curproc->state = WAITING; /* Post wait for specified event */
  399.     }
  400.     addproc(Curproc);
  401.     restore(1);
  402.     LWP_TEST(Curproc,"pwait");
  403.     if(Curproc->event == NULL){
  404.          /* Special case; just give up the processor. */
  405.          if(lwp_yield(THREADNULL) < 0){
  406.         lwp_perror("pwait: lwp_yield");
  407.         abort();
  408.          }
  409.     } else {
  410.          if(lwp_suspend(SELF) < 0){
  411.         lwp_perror("pwait: lwp_suspend");
  412.         abort();
  413.          }
  414.     }
  415.     Curproc = pp;
  416.     LWP_TEST(Curproc,"pwait");
  417.     KL("pwait","exit",pp);
  418.     delproc(Curproc);
  419.     /* At this point, we're running in the newly dispatched task */
  420.     tmp = Curproc->retval;
  421.     Curproc->retval = 0;
  422.     dirps();
  423.     restore(Curproc->i_state);
  424.     return tmp;
  425. }
  426.  
  427. /* Make ready the first 'n' processes waiting for a given event. The ready
  428.  * processes will see a return value of 0 from pwait().  Note that they don't
  429.  * actually get control until we explicitly give up the CPU ourselves through
  430.  * a pwait(). Psignal may be called from interrupt level. It returns the
  431.  * number of processes that were woken up.
  432.  */
  433. int
  434. psignal(event,n)
  435. void *event;    /* Event to signal */
  436. int n;        /* Max number of processes to wake up */
  437. {
  438.     register struct proc *pp;
  439.     struct proc *pnext;
  440.     int i_state;
  441.     unsigned int hashval;
  442.     int cnt = 0;
  443.  
  444. #ifdef TRACEDEBUG
  445.     if(event){
  446.         printf("PSIGNAL: (%s)  event=%x; n=%d\n",Curproc->name, event, n);
  447.     } else {
  448.         printf("PSIGNAL: (%s)  NULL\n",Curproc->name);
  449.     }
  450. #endif
  451. #ifdef STACKDEBUG
  452.     lwp_stackscan();
  453. #endif
  454.     if(event == NULL)
  455.         return 0;        /* Null events are invalid */
  456.  
  457.     /* n = 0 means "signal everybody waiting for this event" */
  458.     if(n == 0)
  459.         n = 65535;
  460.  
  461.     hashval = phash(event);
  462.     i_state = dirps();
  463.     for(pp = Waittab[hashval];n != 0 && pp != NULLPROC;pp = pnext){
  464.         pnext = pp->next;
  465.         if(pp->event == event){
  466.             delproc(pp);
  467.             pp->state &= ~WAITING;
  468.             pp->retval = 0;
  469.             pp->event = NULL;
  470.             addproc(pp);
  471.             if(lwp_resume(pp->tid) < 0){
  472.                 lwp_perror("psignal: lwp_resume");
  473.                 abort();
  474.             }
  475.             LWP_TEST(pp,"psignal");
  476.             KL("psignal","signaled",pp);
  477.             n--;
  478.             cnt++;
  479.         }
  480.     }
  481.     restore(i_state);
  482.     return cnt;
  483. }
  484.  
  485. /* Rename a process */
  486. void
  487. chname(pp,newname)
  488. struct proc *pp;
  489. char *newname;
  490. {
  491.     free(pp->name);
  492.     pp->name = strdup(newname);
  493. #ifdef TRACEDEBUG
  494.     printf("Renamed a process to %s\n",pp->name);
  495. #endif
  496.     KL("chname","",pp);
  497. }
  498. /* Remove a process entry from the appropriate table */
  499. static void
  500. delproc(entry)
  501. register struct proc *entry;    /* Pointer to entry */
  502. {
  503.     int i_state;
  504.  
  505.     if(entry == NULLPROC){
  506. #ifdef TRACEDEBUG
  507.         printf("Warning: attempt to delete a null process!\n");
  508. #endif
  509.         return;
  510.     }
  511.  
  512.     i_state = dirps();
  513.     if(entry->next != NULLPROC)
  514.         entry->next->prev = entry->prev;
  515.     if(entry->prev != NULLPROC){
  516.         entry->prev->next = entry->next;
  517.     } else {
  518.         switch(entry->state){
  519.         case READY:
  520.             Rdytab = entry->next;
  521.             break;
  522.         case WAITING:
  523.             Waittab[phash(entry->event)] = entry->next;
  524.             break;
  525.         }
  526.     }
  527.     entry->next = NULLPROC;
  528.     entry->prev = NULLPROC;
  529.     restore(i_state);
  530. }
  531. /* Append proc entry to end of appropriate list */
  532. static void
  533. addproc(entry)
  534. register struct proc *entry;    /* Pointer to entry */
  535. {
  536.     register struct proc *pp;
  537.     struct proc **head;
  538.     int i_state;
  539.  
  540.     if(entry == NULLPROC){
  541. #ifdef TRACEDEBUG
  542.         printf("Warning: attempt to add a null process!\n");
  543. #endif
  544.         return;
  545.     }
  546.  
  547.     i_state = dirps();
  548.     switch(entry->state){
  549.     case READY:
  550.         head = &Rdytab;
  551.         break;
  552.     case WAITING:
  553.         head = &Waittab[phash(entry->event)];
  554.         break;
  555.     }
  556.     entry->next = NULLPROC;
  557.     if(*head == NULLPROC){
  558.         /* Empty list, stick at beginning */
  559.         entry->prev = NULLPROC;
  560.         *head = entry;
  561.     } else {
  562.         /* Find last entry on list */
  563.         for(pp = *head;pp->next != NULLPROC;pp = pp->next)
  564.             ;
  565.         pp->next = entry;
  566.         entry->prev = pp;
  567.     }
  568.     restore(i_state);
  569. }
  570.  
  571. /* ps() will show strange values for the stack usage of the main process.
  572.    This is beacuse we do not fill the stack space of the main process
  573.    with STACKPAT. */
  574.  
  575.  
  576. /* Print process table info
  577.  * Since things can change while ps is running, the ready proceses are
  578.  * displayed last. This is because an interrupt can make a process ready,
  579.  * but a ready process won't spontaneously become unready. Therefore a
  580.  * process that changes during ps may show up twice, but this is better
  581.  * than not having it showing up at all.
  582.  */
  583. int
  584. ps(argc,argv,pppp)
  585. int argc;
  586. char **argv;
  587. void *pppp;
  588. {
  589.     register struct proc *pp;
  590.     int i, used, *p;
  591.  
  592.     tprintf("PID       SP        stksize   maxstk    event     fl  in out name\n");
  593.     for(i=0;i<PHASH;i++){
  594.         for(pp = Waittab[i];pp != NULLPROC;pp = pp->next){
  595.             if(pp->stksize > 0){
  596.                 for(p=pp->stackbottom+1;*p==STACKPAT;p++);
  597.                 used = pp->stack - p;
  598.             } else used = 0;
  599.             if(tprintf("%-10lx%-10lx%-10u%-10u%-10lx%c%c%c %2d %2d  %s\n",
  600.              ptol(pp),ptol(pp->stack),pp->stksize,used,
  601.              ptol(pp->event),
  602.              pp->i_state ? 'I' : ' ',
  603.              (pp->state & WAITING) ? 'W' : ' ',
  604.              (pp->state & SUSPEND) ? 'S' : ' ',
  605.              pp->input,pp->output,
  606.              pp->name) == EOF)
  607.                 return 0;
  608.         }
  609.     }
  610.     for(pp = Rdytab;pp != NULLPROC;pp = pp->next){
  611.         if(pp->stksize > 0){
  612.             for(p=pp->stackbottom+1;*p==STACKPAT;p++);
  613.             used = pp->stack - p;
  614.         } else used = 0;
  615.         if(tprintf("%-10lx%-10lx%-10u%-10u          %c%c%c %2d %2d  %s\n",
  616.          ptol(pp),ptol(pp->stack),pp->stksize,used,
  617.          pp->i_state ? 'I' : ' ',
  618.          (pp->state & WAITING) ? 'W' : ' ',
  619.          (pp->state & SUSPEND) ? 'S' : ' ',
  620.          pp->input,pp->output,
  621.          pp->name) == EOF)
  622.             return 0;
  623.     }
  624.     if(Curproc != NULLPROC){
  625.         if(Curproc->stksize > 0){
  626.             for(p=Curproc->stackbottom+1;*p==STACKPAT;p++);
  627.             used = Curproc->stack - p;
  628.         } else used = 0;
  629.         tprintf("%-10lx%-10lx%-10u%-10u          %c   %2d %2d  %s\n",
  630.          ptol(Curproc),ptol(Curproc->stack),Curproc->stksize,used,
  631.          istate() ? 'I' : ' ',
  632.          Curproc->input,Curproc->output,
  633.          Curproc->name);
  634.     }
  635.     return 0;
  636. }
  637.  
  638. void kinit()
  639. {
  640.     if(pod_setmaxpri(MINPRIO + 2) < 0){
  641.         lwp_perror("kinit: pod_setmaxpri");
  642.         abort();
  643.     }
  644.  
  645.     if(lwp_setpri(SELF, MINPRIO) < 0){
  646.         lwp_perror("kinit: lwp_setpri");
  647.         abort();
  648.     }
  649.  
  650. #ifdef KERNELLOG
  651.     for(klog_i=0;klog_i<KLOG_SIZE;klog_i++)klog[klog_i].routine=NULL;
  652.     klog_i = 0;
  653.     (void) signal(SIGSEGV, kernel_segv);
  654.     (void) signal(SIGUSR1, kernel_segv);    /* for debugging :-) */
  655. #endif
  656. }
  657.  
  658.  
  659.  
  660. phash(event)
  661. void *event;
  662. {
  663.     register unsigned x;
  664.  
  665.     x = (unsigned) event;
  666.  
  667.     /* If PHASH is a power of two, this will simply mask off the
  668.      * higher order bits
  669.      */
  670.     return x % PHASH;
  671. }
  672.  
  673.  
  674. #ifdef KERNELLOG
  675. void
  676. kernellog(r, d, pp)
  677. char *r;
  678. char *d;
  679. struct proc *pp;
  680. {
  681.     if(r==NULL)return;
  682.  
  683.     klog[klog_i].routine = r;
  684.  
  685.     if(d)klog[klog_i].detail = d;
  686.     else klog[klog_i].detail = "";
  687.  
  688.     if(pp)strcpy(klog[klog_i].proc_name, pp->name);
  689.     else  strcpy(klog[klog_i].proc_name, "?");
  690.  
  691.     klog[klog_i].i = istate();
  692.  
  693.     klog_i++;
  694.     if(klog_i>=KLOG_SIZE)klog_i = 0;
  695. }
  696.  
  697. void
  698. kernel_segv()
  699. {
  700.     int i;
  701.  
  702.     fprintf(stderr,"Signal: SEGV\n");
  703.     fprintf(stderr,"attempting to dump kernel log:\n");
  704.     for(i=0;i<KLOG_SIZE;i++){
  705.         fprintf(stderr,"%2d: %s:%s (%s) interrupts:%d\n",i,
  706.             klog[klog_i].routine,
  707.             klog[klog_i].detail,
  708.             klog[klog_i].proc_name,
  709.             klog[klog_i].i);
  710.         klog_i++;
  711.         if(klog_i>=KLOG_SIZE)klog_i = 0;
  712.     }
  713.     fprintf(stderr,"Waiting for dbx attach; my pid is %d\n",getpid());
  714.     fflush(stderr);
  715.     for(;;)sleep(1);
  716. }
  717.  
  718. #endif
  719.  
  720. #ifdef THREADDEBUG
  721. int
  722. debug_lwp()
  723. {
  724.     int num_threads, i, j;
  725.     thread_t vec[256], me;
  726.     statvec_t statvec;
  727.  
  728.     num_threads = lwp_enumerate(vec, 256);
  729.  
  730.     if(lwp_self(&me)< 0){
  731.         lwp_perror("debug_lwp: lwp_self");
  732.     }
  733.  
  734.     printf("debug_lwp:\n");
  735.     for(i=0;i<num_threads;i++){
  736.         if(lwp_getstate(vec[i], &statvec) < 0){
  737.             lwp_perror("debug_lwp: lwp_getstate");
  738.         } else {
  739.             printf("(%3d) ",i);
  740.             if (SAMETHREAD(me, vec[i])) printf("(me) ");
  741.              else printf("     ");
  742.             printf("%8x/%02d %d ",vec[i].thread_id,
  743.                 vec[i].thread_key, statvec.stat_prio);
  744.             printf("\n");
  745.         }
  746.  
  747.     }
  748.     return 0;
  749. }
  750. #endif
  751.  
  752. #ifdef STACKDEBUG
  753. int
  754. lwp_stackscan()
  755. {
  756.     register struct proc *pp;
  757.     int i, *j;
  758.  
  759.     for(i=0;i<PHASH;i++){
  760.         for(pp = Waittab[i];pp != NULLPROC;pp = pp->next)
  761.                 LWP_TEST(pp,"lwp_stackscan (waitlist)");
  762.     }
  763.  
  764.     for(pp = Rdytab;pp != NULLPROC;pp = pp->next)
  765.                 LWP_TEST(pp,"lwp_stackscan (readylist)");
  766.  
  767.     if(Curproc != NULLPROC)LWP_TEST(Curproc,"lwp_stackscan (run)");
  768.  
  769.     return 0;
  770. }
  771. #endif
  772.