-- ByteBltTestImpl.mesa
-- last modified May 20, 1983 2:24 PM by Taft

DIRECTORY
ByteBltDefs,
csD: FROM "CoreStreamDefs",
Inline,
IODefs,
LaurelExecDefs,
Process,
RandomCard;

ByteBltTestImpl: MONITOR
IMPORTS ByteBltDefs, csD, Inline, IODefs,
LaurelExecDefs, Process, RandomCard =
BEGIN

length: CARDINAL = 1000;
initial, test: PACKED ARRAY [0..length) OF Byte;
Byte: TYPE = [0..255];

Initialize: PROCEDURE =
BEGIN
FOR i: CARDINAL IN [0..length) DO
initial[i] ← i MOD 256;
ENDLOOP;
END;

Test: PROCEDURE [source, dest, count: CARDINAL] =
BEGIN
Inline.COPY[to: @test, from: @initial, nwords: length/2];
[] ← ByteBltDefs.ByteBlt[
to: [@test, dest, dest+count], from: [@test, source, source+count]];
FOR i: CARDINAL IN [0..length) DO
correct: Byte = initial[IF i IN [dest..dest+count) THEN i-dest+source ELSE i];
actual: Byte = test[i];
IF actual#correct THEN SIGNAL Failed;
ENDLOOP;
END;

Failed: SIGNAL = CODE;

WaitForKey: ENTRY PROCEDURE =
BEGIN
waiting ← TRUE;
WHILE waiting DO WAIT finishWaiting; ENDLOOP;
END;

KeyProcess: PROCEDURE =
BEGIN
NotifyWaiter: ENTRY PROCEDURE = {waiting ← FALSE; BROADCAST finishWaiting};
DO
[] ← IODefs.ReadChar[];
IF waiting THEN NotifyWaiter[]
ELSE {pleaseStop ← TRUE; EXIT};
ENDLOOP;
END;

keyProcess: PROCESS;
pleaseStop: BOOLEAN ← FALSE;
waiting: BOOLEAN ← FALSE;
finishWaiting: CONDITION;

DiskProcess: PROCEDURE =
BEGIN OPEN csD;
nChunks: CARDINAL = 512;
bytesPerChunk: CARDINAL = 512;
data: PACKED ARRAY [0..bytesPerChunk) OF [0..255];
sh: StreamHandle = OpenFromName[name: "ByteBltTest.temp$", type: byte, mode: write];
UNTIL pleaseStop DO
IF waiting THEN WaitForKey[];
IODefs.WriteChar[’W];
FOR i: CARDINAL IN [0..bytesPerChunk) DO data[i] ← i; ENDLOOP;
THROUGH [0..nChunks) DO
WriteBlock[sh: sh, from: @data, start: 0, nItems: bytesPerChunk];
Process.Yield[];
ENDLOOP;
SetPosition[sh, 0];
IF waiting THEN WaitForKey[];
IODefs.WriteChar[’R];
THROUGH [0..nChunks) DO
[] ← ReadBlock[sh: sh, to: @data, start: 0, nItems: bytesPerChunk];
Process.Yield[];
ENDLOOP;
SetPosition[sh, 0];
ENDLOOP;
Close[sh];
END;

diskProcess: PROCESS;

iterations: LONG CARDINAL ← 0;

LaurelExecDefs.MakeMenuCommandCallable[newMail];
LaurelExecDefs.MakeMenuCommandCallable[user];
LaurelExecDefs.MakeMenuCommandCallable[mailFile];
LaurelExecDefs.MakeMenuCommandCallable[display];
LaurelExecDefs.MakeMenuCommandCallable[delete];
LaurelExecDefs.MakeMenuCommandCallable[undelete];
LaurelExecDefs.MakeMenuCommandCallable[moveTo];
LaurelExecDefs.MakeMenuCommandCallable[copy];

IODefs.WriteString["Type any character to stop. ""."" = 100 iterations,"L];
IODefs.WriteLine[" ""R"" and ""W"" are disk read/write passes."L];

Initialize[];

keyProcess ← FORK KeyProcess[];
diskProcess ← FORK DiskProcess[];

UNTIL pleaseStop DO
source: CARDINAL ← RandomCard.Choose[0, length-1];
dest: CARDINAL ← RandomCard.Choose[0, length-1];
count: CARDINAL ← RandomCard.Choose[1, MIN[length-source, length-dest]];
Test[source, dest, count !
Failed => {
IODefs.WriteLine["Test failed! Type any character to continue."];
WaitForKey[];
CONTINUE}];
iterations ← iterations+1;
Process.Yield[];
IF iterations MOD 100 = 0 THEN IODefs.WriteChar[’.];
ENDLOOP;

JOIN keyProcess;
JOIN diskProcess;

END.