home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
listings
/
v_08_10
/
8n10122a
< prev
next >
Wrap
Text File
|
1990-08-29
|
18KB
|
552 lines
#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 error and 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 first 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);
}