Listing 3 (CSIM.C)

#include  <alloc.h>
#include  <bios.h>
#include  <dos.h>
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  "csimint.h"

int start_kb_process(void (*task)(void), int stacksize)
{
  int proc_id;
  set_kb_process = 1;
  proc_id = start_process(task, stacksize);
  set_kb_process = 0;
  return(proc_id);
}

int start_process(void (*task)(void), int stacksize)
{
  char *stack;
  struct _simprocessT *process;
  int *off_seg = (int *)&stack;
  unsigned int stackbytes;
  int oldinit;
  
  /*  Check to see if tack handler has been installed */
  
  if (getvect(_INTRPT_) != task_handler)
     /*  if it has not been installed, attempt to    */
     
     if (install_handler())
       /* if it doesn't install, report err & exit */
     {
        printf("error installing task handler \n");
        exit_processing(1);
     }
  if (stacksize > 0x0fdf)
    /* Max stack size in paragraphs (SEGMENT counts) */
  {
      printf("stack size error: proc id : %d",
            totalprocs);
      exit_processing(2);
  }
  stackbytes = stacksize * 16;
  
  /* Setup Process header and stack               */
  
  process = (struct_simprocessT *
           )calloc(sizeof(struct _simprocessT) +
                  stackbytes, 1);
  /* make sure there was enough memory              */
  if (process == NULL)
     return(2);
  
  stack = (char *)(process + 1);
  
  /* 'Normalize' the bottom of stack pointer, that is
     make sure the offset is less then 16, as would be
     the case if the program where compiled in the huge
     memory model */
  if (off_seg[0] > 16)
     for (; off_seg[0] > 16;
         off_seg[1]++, off_seg[0] -= 16)
         ;
  /* remember, the stack actually starts high and
     builds its way down, so put the pointer at the top.*/
  stack += stackbytes - 1;
  
  /* finish setup of stack and base pointers           */
  
  process->reg_sp = FP_OFF(stack);
  process->reg_ss = FP_SEG(stack);
  
  process->reg_bp = FP_OFF(stack);
  
  process->proc_id = totalprocs++;
  process->init = 1;
  
  /*  Setup start jump                                  */
  process->reg_cs = FP_SEG(task);
  process->reg_ip = FP_OFF(task);
  /*  link into current processes                       */
  if (processlist == NULL)
  {
     processlist = process;
     processlist->next = process;
     processlist->prev = process;
  }
  else
  {
     process->prev = processlist;
     process->next = processlist->next;
     process->next->prev = process;
     processlist->next = process;
     processlist = process;
  }
  if (set_kb_process)
     kbprocess = processlist;
 /*  make sure we can get back to where we were...    */
 glbl_ss = _SS;
 glbl sp=  _SP;
 glbl_bp = _BP;
 oldinit = _sim_init_val;
 
 /*  tell the task handler what routine the
     process uses   */
  
 glbl_fc = task;
 
 /*  tell the task handler that this proc is initing */
 
 _sim_init_val = 1;
 
 /*  set up the new stak and base pointers and ...   */
 _SS = process->reg_ss;
 _SP = process->reg_sp;
 _BP = process->reg_bp;
 
 /*  have the task_handle do the rest                */
 geninterrupt(_INTRPT_);
 
 _SS = glbl_ss;
 _SP = glbl_sp;
 _BP = glbl_bp;
 glbl_fc = NULL;
 _sim_init_val = oldinit;
 processlist = processlist->prev;
 return(0);

}

void stop_process(int process_id)
{
 struct_simprocessT *process;
 int go;
 
 go = 1;
 process = processlist;
 
 while (go)
 {
  if (process_id == process->proc_id)
  { 
   
   process->status.kill_flag = 1;
   process->start_time = _sim_system_time;
   go = 0;
  }
  if (process->next == processlist)
  {
   if (go)
    printf(
     "\nattempted to stop non-existant proc\n");
   
   go = 0;
  }
  else
  {
   process = process->next;
  }
 }
}

void sim_start(void)
{
 _sim_init_val = 0;
 _last_update_time = *systimer;
 geninterrupt(_INTRPT_);
}

void exit_processing(int condition)
{
 struct_simprocessT *pholder;
 setvect(_INTRPT_, old_vector);
 printf("Exit processing, code : %d\n", condition);
 processlist->prev->next = NULL;
 do
 {
     pholder = processlist;
     processlist = processlist->next;
     free(pholder);
 } while (processlist != NULL);
 exit(condition);
}

int install_handler(void)
{
 void *new_vector;
 
 _sim_init_val = 2;
 old_vector = getvect(_INTRPT_);
 setvect(_INTRPT_, task_handler);
 new_vector = getvect(_INTRPT_);
 if (new_vector == old_vector)
  return(1);
 return(0);
void interrupt task_handler(unsigned bp, unsigned di,
                       unsigned si, unsigned ds,
                       unsigned es, unsigned dx,
                       unsigned cx, unsigned bx,
                       unsigned ax, unsigned ip,
                       unsigned cs, unsigned flags)
{
 int notfound;
 struct_simprocessT *procpntr;

 if (_sim_init_val == 2)
        /*  if this ever happens, it means that the task
        handler was installed before it should have
        been, so de-install it and stop the program  */
 {
  exit_processing(10);
 }
 if (_sim_init_val == 0)  /*  sim_start has been run */
 {
    processlist->reg_bp = _BP;
    processlist->reg_sp = _SP;
    processlist->reg_ss = _SS;
  
  if (processlist->status.kill_flag)
  {
   if (processlist == kbprocess)
      /*  You can,t kill the kbproc                */
      processlist->status.kill_flag = 0;
   else
   {
    if (processlist->next == processlist)
       /*  no more procs                          */
       exit_processing(20);

    /*  break list                               */
    processlist->prev->next =
       processlist->next;

    /*  move in front of break                   */
    processlist = processlist->prev;
    
    /*  free dead proc                           */
    free(processlist->next->prev);
    
    /*  fix break                                */
    processlist->next->prev = processlist;
   }
  }
  if ((kbprocess != NULL) && (bioskey(1)))
     processlist = kbprocess;
  else
  {
     if (_sim_time_ratio ! = 0.0)
     {
       for (notfound = 1; notfound;)
       {
         if ((kbprocess != NULL) &&
            (bioskey(1)))
         {
            processlist = kbprocess;
            notfound = 0;
         }
         else
         {
            processlist = processlist->next;
            if ((*systimer -
                 _last_update_time) >
                (1 /_sim_time_ratio))
            {
                _sim_system_time +=
                    (*systimer -
                     _last_update_time) *
                    _sim_time_ratio;
                _last_update_time = *systimer;
            }
            if ((processlist->start_time <=
                 _sim_system_time) &&
                (processlist->status.
                 wait_flag == 0))
                notfound = 0;
         }
       }
       _sim_system_time = processlist->start_time;
   }
   else
   {
       if (processlist->status.wait_flag)
       {
         for (procpntr = processlist->next;
             procpntr &&
             (procpntr->status.wait_flag) &&
             (procpntr->status.kill_flag);)
         {
             procpntr = procpntr->next;
             if (procpntr == processlist)
                procpntr = NULL;
                }
                if (procpntr == NULL)
                {
                   fprintf(stderr, "waitlock\n");
                   exit_processing(1);
                }
                _sim_system_time =
                   procpntr->start_time;
         }
         else
                _sim_system_time =
                   processlist->start_time;
         procpntr = processlist->next;
         while (procpntr != processlist)
         {
             if ((!procpntr->status.wait_flag) &&
                (_sim_system_time >
                procpntr->start_time))
                _sim_system_time =
                procpntr->start_time;
             procpntr = procpntr->next;
         }
         processlist = processlist->next;
         while ((processlist->status.wait_flag  ||
                processlist->status.kill_flag)     ||
                (processlist->start_time >
                _sim_system_time))
             processlist = processlist->next;
         _last_update_time = *systimer;
       }
     }
     CurrentTime = _sim_system_time / 18.2;
     disable();
     _SP = processlist->reg_sp;
     _SS = processlist->reg_ss;
     _BP = processlist->reg_bp;
     enable();

     if (processlist->init == 1)
      /*  process is in its 1st step, so initialize it */
     {
       ax = processlist->reg_ax;
       bx = processlist->reg_bx;
       cx = processlist->reg_cx;
       dx = processlist->reg_dx;
       es = processlist->reg_es;
       ds = processlist->reg_ds;
       si = processlist->reg_si;
       di = processlist->reg_di;
       bp = processlist->reg_bp;
       ip = processlist->reg_ip;
       cs = processlist->reg_cs;
       flags = processlist->reg_flag;
       processlist->init = 0;
      }
     }
     else  /*  sim_start has not been run  */
     {
      if (_sim_init_val == 1)
      {
       processlist->reg_ax = ax;
       processlist->reg_bx = bx;
       processlist->reg_cx = cx;
       processlist->reg_dx = dx;
       processlist->reg_es = es;
       processlist->reg_ds = ds;
       processlist->reg_si = si;
       processlist->reg_di = di;
       processlist->reg_ip = FP_OFF(glbl_fc);
       processlist->reg_cs = FP_SEG(glbl_fc);
       processlist->reg_flag = flags;
       processlist->reg_bp = _BP;
       processlist->reg_sp = SP;
       processlist->reg_ss = _SS;
       processlist->init = 1;
       cs = cs;
       ip = ip;
       bp = bp;
       }
      }
     }

     int set_time_ratio(float ratio)
     {
      _sim_time_ratio = ratio;
      return(0);
     }

     int my_process_id(void)
     {
      return(processlist->proc_id);
     }

     int wait_until_time(long unsigned starttime)
     {
      if (starttime < (_sim_system_time / 18.2))
      {
         printf("Waiting for a time that is past in %d",
                processlist->proc_id);
         exit_processing(-1);
      }
      wait_for_time(float)(starttime * 18.2 -
                        _sim_system_time) / 18.2);
      return(0);
     }
     int wait_for_time(float delaytime)
     {
      if (_sim_time_ratio == 0)
      {
         processlist->start_time = _sim_system_time +
            delaytime * 18.2;
     }
     else
         processlist->start_time = _sim_system_time +
         (long)(18.2 * delaytime);

      geninterrupt(_INTRPT_);
      return(0);
     }
     
     int init_post(char *postname)
     {
         struct _postT *post;
         
         for (post = postlist; post != NULL; post = post->next)
         {
            if (strcmp((char *)&post->name, postname) == 0)
                return(post->handle);
         }
         post = (struct _postT *)calloc(sizeof(struct _postT),
                                   1);
         if (post == NULL)
            return(- 1);

         post->handle = totalposts++;
         post->value = NULL;
         strcpy((char *)&post->name, postname);
         
         post->waiting = calloc(1, sizeof(void *));
         post->waiting[0] = NULL;
         
         post->next = postlist;
         post->prev = NULL;
         
         postlist->prev = post;
         postlist = post;
         return(post->handle);
     }
     int set_post(int posthandle, void *pointer)
     {
         struct _postT *post;
         struct _simprocessT *procpntr;
         int loop;
         for (post = postlist; post != NULL; post = post->next)
         {
           if (post->handle == posthandle)
           {
             if (post->value != NULL)
             {
                 wait_for_time(0);
                 if (post->value != NULL)
                     return(post->handle);
             }
             if (post->waiting[0] != NULL)
             {
                 post->waiting[0]->status.wait_flag = 0;
                 post->waiting[0]->start_time =
                     _sim_system_time;
                 loop = 0;
                 procpntr = processlist->next;
                 while (procpntr != processlist)
                {
                   if ((procpntr->status.wait_flag) &&
                       (procpntr->waitpost == post))
                   {
                       post->waiting[loop] = procpntr;
                       loop++;
                   }
                   procpntr = procpntr->next;
                }
                post->waiting[loop] = NULL;
         }
         post ->value = pointer;
         wait_for_time(0);
         return(0);
       }
     }
     return(-posthandle);
   }
   
   void *get_post(int posthandle)
   {
     struct _postT *post;
     void *ret;
     
     for (post = postlist; post != NULL; post = post->next)
     {
       if (post->handle == posthandle)
       {
         ret = post->value;
         
         if (ret == NULL)
           return(ret);

         post->value = NULL;
         return(ret);
       }
     }
     return(NULL);
   }

   void *wait_post(int posthandle)
   {
     struct _postT *post;
     void *ret;
     int loop;

     for (post = postlist; post != NULL; post = post->next)
     {
       if (post->handle == posthandle)
       {
         ret = post->value;
         
         if (ret == NULL)
         {
           for (loop = 0; post->waiting[loop]; )
             loop++;
           post->waiting = realloc(post->waiting,
                               (loop + 2) *
                               sizeof(void *));
           post->waiting[loop] = processlist;
           post->waiting[loop + 1] = NULL;
           while (ret == NULL)
           {
             processlist->status.wait_flag = 1;
             processlist->waitpost = postlist;
             wait_for_time(0);
             ret = post->value;
             post->value = NULL;
         }
         processlist->waitpost = NULL;
         return(ret);
       }
       post->value = NULL;
       return(ret);
     }
   }
   return(NULL);
 }