home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 306_01 / thread.c < prev    next >
C/C++ Source or Header  |  1991-02-21  |  5KB  |  102 lines

  1. /*********** THREAD.C COPYRIGHT 1989 GREGORY COLVIN ************
  2. This program may be distributed free with this copyright notice.
  3. ***************************************************************/
  4. #include "thread.h"
  5.  
  6.        ThTabl Threads=0;        /* table of threads           */
  7.        Thread ThCurr;           /* currently executing thread */
  8. static int    N_Threads;        /* number of threads in table */
  9. static Thread Free;             /* first thread on free list  */
  10. static char  *Stack;            /* bottom of stack for init   */
  11. static void (*Root)(Thread);    /* for temporary use for exec */
  12.  
  13. static void init(int n,int size)        /* recurse for ThInit */
  14. { Thread id;
  15.   if (!Stack) {                         /* start new thread   */
  16.     Stack= (char *)&size;               /* at top of stack    */
  17.     if (id= setjmp(Threads[n].init)) {  /* set entry point    */
  18.       (*Root)(id);                      /* call root function */
  19.       ThExit(ThNext());                 /* fell off thread    */
  20.     }
  21.   }
  22.   if (Stack - (char *)&size < size)     /* if not enough stack*/
  23.     init(n,size);                       /* push more stack    */
  24.   else {                                /* done with a thread */
  25.     Threads[n].stack= (char *)&size;    /* save top of stack  */
  26.     Stack= 0 ;                          /* flag for new thread*/
  27.     if (n < N_Threads) {                /* if not done        */
  28.       Threads[n].free= n+1;             /* link to free list  */
  29.       init(++n,size);                   /* push more stack    */
  30.     }
  31.   }
  32.   Threads[n].free = 0;                  /* end of free list   */
  33.   longjmp(Threads[1].jump,1);           /* return to ThInit   */
  34. }
  35. int ThInit(int n,int size)      /* create n size byte threads */
  36. { assert (!Threads);                    /* must be free       */
  37.   assert (n >= 2);                      /* must be plural     */
  38.   Threads=                              /* create table       */
  39.     (ThTabl)calloc(n,sizeof *Threads);
  40.   if (!Threads)
  41.     return 0;                           /* not enough memory  */
  42.   Threads--;                            /* will index from 1  */
  43.   if (setjmp(Threads[1].jump)){         /* become thread 1    */
  44.     Threads[1].free= 0;                 /* take off free list */
  45.     return n;                           /* return to thread 1 */
  46.   }
  47.   N_Threads= n, ThCurr= 1, Free= 2;     /* initialize globals */
  48.   init(1,size);                         /* initialize stack   */
  49. }
  50.  
  51. Thread ThNew(void(*f)(Thread))  /* fork and exec new thread   */
  52. { Thread parent, fork;
  53.   ThProbe();                            /* stack probe        */
  54.   assert(f);                            /* prevent crash      */
  55.   fork= Free;                           /* fork to free thread*/
  56.   if (fork == 0)
  57.     return 0;                           /* error, none free   */
  58.   Free= Threads[fork].free;             /* take off free list */
  59.   Threads[fork].free= 0;
  60.   parent= ThCurr;                       /* current is parent  */
  61.   ThCurr= fork;                         /* will run fork next */
  62.   if (setjmp(Threads[parent].jump))     /* put parent to sleep*/
  63.     return fork;                        /* parent is awake    */
  64.   Root= f;                              /* who to call        */
  65.   longjmp(Threads[fork].init,parent);   /* exec root in init  */
  66. }
  67.  
  68. Thread ThNext(void)             /* find next runnable thread  */
  69. { Thread id= ThCurr;                    /* start from self    */
  70.   do id %= N_Threads;                   /* circle round table */
  71.   while (Threads[++id].free);           /* until we find life */
  72.   return id;                            /* next might be self */
  73. }
  74.  
  75. Thread ThJump(Thread id)        /* jump to another thread     */
  76. { Thread jumper, caller;
  77.   ThProbe();                            /* stack probe        */
  78.   assert(id > 0 && id <= N_Threads);    /* prevent crash      */
  79.   assert(ThLive(id) && id != ThCurr);   /* no go dead or self */
  80.   caller= ThCurr;                       /* where we came from */
  81.   ThCurr= id;                           /* where we are going */
  82.   if (jumper=setjmp(Threads[caller].jump))
  83.     return jumper;                      /* return who jumped  */
  84.   longjmp(Threads[id].jump,caller);     /* context switch     */
  85. }
  86.  
  87. void ThExit(Thread id)          /* exit to another thread     */
  88. { ThProbe();                            /* stack probe        */
  89.   assert(id > 0 && id <= N_Threads);    /* prevent crash      */
  90.   assert(ThLive(id) && id != ThCurr);   /* no go dead or self */
  91.   Threads[ThCurr].free= Free;           /* put on free list   */
  92.   Free= ThCurr;                         /* where we came from */
  93.   ThCurr= id;                           /* where we are going */
  94.   longjmp(Threads[id].jump,Free);       /* context switch     */
  95. }
  96.  
  97. void ThFree()                   /* free the thread table      */
  98. {   assert (Threads);                   /* prevent crash      */
  99.     free(Threads+1);                    /* goodbye            */
  100.     Threads= 0, N_Threads= 0;           /* can init again     */
  101. }
  102.