Listing 2

/* ************************** */
/* Multi-threading functions */

#include <setjmp.h>
#define TSTACKSIZE 200     /* Stack space reseved in each thread in words */
#define MAXTHREAD 20         /* Max No of concurrent threads */
#define SPINDX 1           /* Index of stack pointer into env */
#define NULL 0
static struct threaddat {
      int    *env ;         /* Environment pointer */
      int    (*tfp)() ;     /* Thread function pointer */
      int    state ;        /* 0 Waiting 1 running -1 terminated */
            } threaddata[MAXTHREAD] ;
/* Globals for thread() */
static jmp buf envroot ;        /* root environment */
static int threadnum = -1 ;     /* Number of threads */
static int threadindx ;            /* Thread indexer */
/* Takes a NULL terminated list of function pointers, sets up
   the global parameters above and the root environment and then
   calls threadrun() to define and run the function threads. */
thread(fplist)
int (*fplist)() ;
{
  int  (**fplptr)() ;
  void threadrun() ;
  if (threadnum == -1)
   { fplptr = &fplist ;
     threadnum = 0 ;
     while (*fplptr != NULL)
        threaddata(threadnum++).tfp = *fplptr++ ;
     threadindx = 0 ;
     if (!setjmp(envroot))
        threadrun() ;       /* define thread environments recursivly */
                             /* then run them to extinction */
  }
}
/* recusivly defines thread environments then runs in round robin */
void threadrun()
{
  jmp_buf envthread ;
  int stackspace[TSTACKSIZE) ;
  if (threadindx < threadnum)
    { if (setjmp(envthread))
       { /* Will arrive here by longjmp for function dispatch */
         (*threaddata[threadindx].tfp)() ;     /* Start thread */
         threaddata[threadindx].state = -1 ;   /* terminated */
         threadswitch() ;
         printf("Multi-threading error - terminating ) ;
         exit(1) ;
        }
       else
        {
/* Global pointer to thread env */
        threaddata[threadindx].env = envthread ;
/* Thread state to waiting to run */
        threaddata[threadindx].state = 0 ;
/* Modify env value for stack with a little margin for luck */
        envthread[SPINDX] = (int) &stackspace[TSTACKSIZE-5] ;
        threadrun(++threadindx) ;  /* Recusive call for next thread env */
      }
   }
  else                            /* Run threads in round robin */
   {
/* Start the ball rolling with thread 1 */
       threadindx = 0 ;
       longjmp(threaddata[threadindx].env, -1) ;
   }
}
/* Thread switcher : Will switch to next available function thread in list.
   If function threads have all terminated will terminate the threads
   environment and return to the root enviroment */
threadswitch()
{ int i ;
  if (threadnum != -1)

  {
  if (threaddata[threadindx].state != -1)
    threaddata[threadindx] .state = 0 ;
  if (!setjmp(threaddata[threadindx].env))
  {
    for (i=1; i <= threadnum; i++)
      { if (++threadindx >= threadnum)
          threadindx = 0 ;
        if (!threaddata[threadindx].state)
          { threaddata[threadindx].state = 1 ;
            longjmp(threaddata[threadindx].env, -1) ;
          }
        }
      threadnum = -1 ;
      longjmp(envroot, -1 ) ;
    }
  }
}