home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
turbopas
/
concr4.arc
/
CPEXEC.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1988-04-17
|
6KB
|
173 lines
(****************************************************************************
Program : Concurrent Programming Executive
Author : J.F.J. Passant
Version : 1.00
Date : December 3, 1986
Modified : March 31, 1987
Author : Gary Black
Purpose : Correct bug in TaskSwitch
Version : 1.01
Modified : April 17, 1988
Author : Steve Fox
Purpose : Modify for use under TP 4.0
Version : 2.0
*****************************************************************************)
{$S-} { Stack checking off }
Unit CpExec;
Interface
Uses
TPCrt;
procedure ClaimInput;
procedure ReleaseInput;
procedure Delay(ms: word);
procedure TaskInstall(address: Pointer; size: word;
var task: word; var heap: pointer);
procedure TaskRemove(task: word; sp: pointer; size: word);
procedure TaskWindow(X1, Y1, X2, Y2, FAttr, HAttr, WAttr: byte;
cursor: boolean; title: string);
procedure TaskSwitch;
{============================================================================}
Implementation
const
InputBusy : boolean = False;
FrameSize = 18; { Context frame size }
MaxTask = 15; { Highest numbered task }
type
TaskArea = array[1..FrameSize] of word; { Start of context frame }
StackPointer = ^TaskArea;
var
ActiveTasks : array[0..MaxTask] of byte; { Active task flags }
StackSize : array[0..MaxTask] of word; { Size of stack allocated }
SPTable : array[0..MaxTask] of Pointer; { Active task stack pointers }
CurrentTask : word; { Currently active task }
{$I TPINLINE.INC}
(***************************** Support Routines *****************************)
procedure ClaimInput;
{ Wait for keyboard }
begin
while InputBusy do
TaskSwitch; { Wait until task releases input }
InputBusy := True
end;
procedure ReleaseInput;
{ Release keyboard for another task to use }
begin
InputBusy := False
end;
procedure Delay(ms: word);
{ Delay task for <ms> milliseconds.
The resolution of this operation is limited to approximately 55 ms (one
clock tick). }
const
TicsMSec = 0.01820648193; { Ticks per millisecond }
TicsDay = 1573040; { Ticks per day }
var
CurrentTime: LongInt absolute $0040:$006C; { Ticks since midnight }
timer: LongInt;
begin
timer := CurrentTime + round(ms * TicsMSec) mod TicsDay;
while (CurrentTime < timer) or (CurrentTime > (timer + 1092)) do
TaskSwitch
end;
procedure TaskError(msg: string; val: word);
{ Display a fatal error message and terminate the program. }
begin
write(msg);
if val = -1
then writeln
else writeln(val:1);
write('--- Program Terminated ---');
halt(1)
end;
(**************************** Task Installation *****************************)
procedure TaskInstall(address: Pointer; size: word;
var task: word; var heap: pointer);
{ Install task number <task> at <address> and allocate <size> bytes for its
stack. The stack is initialized, ready for <TaskSwitch> to activate the
task. }
var
sp: StackPointer;
begin
task := 1;
while (task <= MaxTask) and (ActiveTasks[task] = 1) do
Inc(task);
if task > MaxTask
then TaskError('Too many tasks ', task);
if MaxAvail < size
then TaskError('Not enough memory to install task ', task);
StackSize[task] := size;
GetMem(sp, size); { Point <sp> to top of stack }
heap := sp;
sp := Normalized(sp);
sp := Normalized(ptr(Seg(sp^), Ofs(sp^) + size - SizeOf(TaskArea)));
SPTable[task] := sp; { Save the task stack pointer }
FillChar(sp^, SizeOf(TaskArea), #0); { Initialize the task registers }
sp^[FrameSize ] := Seg(address^); { IP }
sp^[FrameSize - 1] := Ofs(address^);
sp^[FrameSize - 2] := $0200; { Flags, interrupts enabled }
sp^[FrameSize - 3] := DSeg; { DS }
ActiveTasks[task] := 1 { Task enabled }
end;
procedure TaskRemove(task: word; sp: pointer; size: word);
{ Remove a previously installed task }
begin
if CurrentTask <> task
then
begin
ActiveTasks[task] := 0;
FreeMem(sp, size)
end
end;
procedure TaskWindow(X1, Y1, X2, Y2, Fattr, HAttr, WAttr: byte;
cursor: boolean; title: string);
{ Prepare a portion of the screen for a task }
begin
FrameWindow(X1, Y1, X2, Y2, FAttr, HAttr, title);
Window(succ(X1), succ(Y1), pred(X2), pred(Y2));
TextColor(WAttr and $0F);
TextBackground(WAttr shr 4);
if not cursor
then HiddenCursor
end;
(****************************** Task Switching ******************************)
procedure TaskSwitch; external;
{ The task switcher }
{$L CPEXEC.OBJ} { External assembly code }
(**************************** Unit Initialization ***************************)
begin
FillChar(ActiveTasks, SizeOf(ActiveTasks), #0); { Disable all tasks }
ActiveTasks[0] := 1; { Activate main program (task 0) }
CurrentTask := 0 { and make it current }
End.