home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
turbom2
/
m2fst.lbr
/
XFERDEMO.MZD
/
XFERDEMO.MOD
Wrap
Text File
|
1987-09-10
|
4KB
|
143 lines
MODULE xferdemo;
(* (C) Copyright 1987 Fitted Software Tools. All rights reserved. *)
(*
This is a small example showing the use of the coroutine handling
capabilities in this Modula-2 system.
*)
FROM SYSTEM IMPORT ASSEMBLER, ADDRESS, NEWPROCESS, TRANSFER, IOTRANSFER;
FROM Storage IMPORT ALLOCATE;
FROM System IMPORT GetVector, ResetVector, TermProcedure;
FROM InOut IMPORT Write, WriteCard, WriteLn;
VAR SysPrtScr :ADDRESS; (* original PrtSc ISR *)
SysClock :ADDRESS; (* original clock ISR *)
ProcSpace :POINTER TO CHAR; (* pointers to processes workspaces *)
ClockSpace :POINTER TO CHAR;
StopSpace :POINTER TO CHAR;
p1, p2 :ADDRESS; (* coroutine (process) pointers *)
p3, p4 :ADDRESS;
p5, p6 :ADDRESS;
ticks :CARDINAL; (* tick counter *)
xfers :CARDINAL; (* transfers performed during run *)
done :BOOLEAN; (* terminate flag *)
PROCEDURE clock;
(*
this is the clock process.
it increments 'ticks' on every clock interrupt.
from the time that this process starts until such time as
the program terminates, the system timer will not be updated,
as this routine ruthlessly steals the clock interrupts from DOS.
it would have been much better to run this process off interrupt
1CH, but in that case we would not have to send the EOI to the
8259 chip, making this exercise a little less instructive.
*)
BEGIN
LOOP
IOTRANSFER( p3, p4, 8 );
INC(ticks);
ASM (* send EOI to 8259 *)
MOV AL, 20H (* the 8259 interrupt controller will *)
OUT 20H, AL (* prevent all interrupt at or below *)
(* our level until we send it an EOI *)
END; (* command *)
END;
END clock;
PROCEDURE putT;
(*
this is a process that works hand in hand with the main process.
it alternately outputs a 'T' or a 't' and resumes the main process.
*)
BEGIN
LOOP
Write('T');
TRANSFER( p2, p1 );
Write('t');
TRANSFER( p2, p1 );
END;
END putT;
PROCEDURE stop;
(*
this process will signal the main process that the user wishes
to terminate the program by setting 'done' to TRUE whenever
the user presses the PrtSC key generating a 'print screen'
interrupt.
we do not simply terminate the program with a RETURN, because we
may be in DOS when the interrupt occurs.
*)
BEGIN
LOOP
IOTRANSFER( p5, p6, 5 );
done := TRUE;
END;
END stop;
PROCEDURE end;
(*
this is the procedure to be executed on program termination.
we MUST restore the interrupt vectors that we have stolen.
*)
BEGIN
ResetVector( 5, SysPrtScr );
ResetVector( 8, SysClock );
END end;
BEGIN
done := FALSE;
ticks := 0;
xfers := 0;
GetVector( 5, SysPrtScr ); (* get the original values of the *)
GetVector( 8, SysClock ); (* interrupt vectors that we will use *)
TermProcedure( end ); (* and install 'end' to execute on *)
(* program termination *)
(* now, create the new processes *)
ALLOCATE( ProcSpace, 512 );
NEWPROCESS( putT, ProcSpace, 512, p2 );
ALLOCATE( ClockSpace, 512 );
NEWPROCESS( clock, ClockSpace, 512, p3 );
ALLOCATE( StopSpace, 512 );
NEWPROCESS( stop, StopSpace, 512, p5 );
(* start the 'stop' process *)
TRANSFER( p6, p5 );
(* start the 'clock' process *)
TRANSFER( p4, p3 );
(*
this is the main loop of the main process.
on every loop, the 'done' flag is checked and, if it is not time
to stop, we write out the value of ticks and reactivate the 'putT'
process.
*)
WHILE NOT done DO
WriteCard( ticks, 6 );
TRANSFER( p1, p2 );
INC( xfers );
END;
WriteLn; WriteCard( xfers, 4 ); WriteLn;
END xferdemo.