-- File: QueueLocked.mesa, Last Edit: HGM October 15, 1979 8:01 PM

-- Copyright Xerox Corporation 1979, 1980

DIRECTORY
StatsDefs: FROM "StatsDefs" USING [StatIncr],
CommUtilDefs: FROM "CommUtilDefs" USING [GetReturnFrame],
DriverDefs: FROM "DriverDefs" USING [
freeQueueLock, freeQueue, firstBuffer,
doDebug, doSee, doStats, Glitch],
PupDefs: FROM "PupDefs", -- EXPORTs
BufferDefs: FROM "BufferDefs" USING [
Buffer, PupBuffer, RppBuffer, Queue],
DriverTypes: FROM "D
riverTypes" USING [bufferSeal, queueSeal];

QueueLocked: MONITOR LOCKS DriverDefs.freeQueueLock
IMPORTS StatsDefs, CommUtilDefs, DriverDefs
EXPORTS DriverDefs, PupDefs, BufferDefs
SHARES BufferDefs =
BEGIN OPEN DriverDefs, BufferDefs;

bufferSize: PUBLIC CARDINAL;

QueueScrambled: PUBLIC ERROR = CODE;
QueueSealBroken: PUBLIC ERROR = CODE;
BufferSealBroken: PUBLIC ERROR = CODE;
Fre
eQueueNotInitialized: PUBLIC ERROR = CODE;

-
- NB: Caller must protect his own Queues.

EnqueuePup: PUBLIC PROCED
URE [Queue, PupBuffer] = LOOPHOLE[Enqueue];
EnqueueRpp: PUBLIC PROCED
URE [Queue, RppBuffer] = LOOPHOLE[Enqueue];
Enqueue: PUBLIC PROCEDURE [q: Queue, b: Buffer] =
BEGIN
IF q=NIL OR b=NIL OR b.queue#NIL THEN Glitch[QueueScrambled];
IF doDebug AND q.seal#DriverTypes.queueSeal THEN Glitch[QueueSealBroken];
IF doDebug AND b.seal#DriverTypes.bufferSeal THEN Glitch[BufferSealBroken];
IF doDebug AND q.length#0
AND (q.first=NIL OR q.last=NIL) THEN Glitch[QueueScrambled];
IF doDebug AND q.length>256 THEN Glitch[QueueScrambled];
b.next ← NIL;
IF doStats THEN StatsDefs.StatIncr[statEnqueue];
IF q.first=NIL THEN q.first←b ELSE q.last↑.next←b;
q.last ← b;
b.
queue ← q;
q.length ← q.length+1;
END;

DequeuePup: PUBLIC PROCEDURE [Queu
e] RETURNS [PupBuffer] = LOOPHOLE[Dequeue];
DequeueRpp: PUBLIC PROCEDURE [Queu
e] RETURNS [RppBuffer] = LOOPHOLE[Dequeue];
Dequeue: PUBLIC PROCEDURE [q: Queue] RETURNS [b: Buffer] =
BEGIN
IF q=NIL THEN Glitch[QueueScrambled];
IF doDebug AND q.seal#DriverTypes.queueSeal THEN Glitch[QueueSealBroken];
IF (b←q.first)=NIL THEN
BEGIN
IF doDebug AND q.length#0 THEN Glitch[QueueScrambled];
IF doStats THEN StatsDefs.StatIncr[statDequeueNIL];
RETURN;
END;
IF (q.first←q.first.next)=NIL THEN q.last←NIL;
IF doDebug AND q.length>256 THEN Glitch[QueueScrambled];
q.length ← q.length-1;
IF doStats THEN StatsDefs.StatIncr[statDequeue];
IF b.queue#q THEN Glitch[QueueScrambled];
b.queue ← NIL;
b.next ← NIL;
IF doDebug AND b.seal#DriverTypes.bufferSeal THEN Glitch[BufferSealBroken];
IF doDebug AND q.length#0
AND (q.first=NIL OR q.last
=NIL) THEN Glitch[QueueScrambled];
END;


-- This routine is only used by device dri
vers to get buffers to read things into.
-- NB: b.length is
setup for the size of the buffer, including ALL of the encapsulation. All device drivers must fudge things themsleves since they do not use all of the encapsulation field.
GetInputBuffer: PUBLIC ENTRY PROCEDURE RETURNS [b: Buffer] =
BEGIN
IF doDebug AND firstBuffer=NIL THEN Glitch[FreeQueueNotInitialized];
b ← Dequeue[@freeQueue];
IF b#NIL THEN
BEGIN
b.length ← bufferSize;
IF doDebug OR doSee THEN b.type ← raw;
IF doDebug THEN b.debug ← CommUtilDefs.GetReturnFrame[].accesslink;
END;
END;

END. -- QueueLocked