#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);
}