EtherTesterStorageImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Willie-Sue, December 5, 1986 2:27:26 pm PST
lifted from EtherTesterPilot.mesa, AOF, 26-Sep-83 16:45:40
DIRECTORY
EtherTesterOps,
NewEthernetFace USING [controlBlockSize],
VM USING [AddressForPageNumber, Interval, lowCore, PagesForWords, SimpleAllocate, SwapIn];
EtherTesterStorageImpl: PROGRAM
IMPORTS NewEthernetFace, VM
EXPORTS EtherTesterOps
= BEGIN
maintain buffers, in ascending size order
BufferObj: TYPE = REF BufferType;
BufferType: TYPE = RECORD[
next: BufferObj ← NIL,
size: CARDINAL,
available: BOOLFALSE,
buffer: LONG POINTER
];
bufferChain: BufferObj;
AllocateOneBuffer: PUBLIC PROC[size: CARDINAL] RETURNS [b: LONG POINTER] = {
this: BufferObj ← NIL;
interval: VM.Interval;
Clear: PROC = {
p: LONG POINTER ← this.buffer;
THROUGH [0..size) DO p^ ← 0; p ← p + 1; ENDLOOP;
this.available ← FALSE;
};
FOR this ← bufferChain, this.next UNTIL this = NIL DO
IF this.size >= size AND this.available THEN
{ Clear[]; RETURN[this.buffer] };
ENDLOOP;
we fell off the end or the chain is empty - allocate a new one and insert it in the appropriate place in the chain
this ← NEW[BufferType ← [size: size, buffer: NIL] ];
interval ← VM.SimpleAllocate[VM.PagesForWords[size]];
VM.SwapIn[interval: interval, kill: TRUE, pin: TRUE];
this.buffer ← VM.AddressForPageNumber[interval.page];
Clear[];
IF bufferChain = NIL THEN bufferChain ← this
ELSE {
prev: BufferObj ← NIL;
FOR now: BufferObj ← bufferChain, now.next UNTIL now = NIL DO
IF now.size >= size THEN { -- insert this before now
IF prev = NIL THEN bufferChain ← this ELSE prev.next ← this;
this.next ← now;
RETURN[this.buffer];
};
prev ← now;
ENDLOOP;
prev.next ← this;  -- largest so far
};
RETURN[this.buffer];
};
FreeOneBuffer: PUBLIC PROC[b: LONG POINTER] = {
FOR this: BufferObj ← bufferChain, this.next UNTIL this = NIL DO
IF this.buffer = b THEN { this.available ← TRUE; RETURN };
ENDLOOP;
};
maintian IOCB's
IocbType: TYPE = RECORD[
next: LONG POINTER TO IocbType,
rest: SEQUENCE COMPUTED CARDINAL OF WORD
];
iocbChain: LONG POINTER TO IocbType ← NIL;
AllocateOneIOCB: PUBLIC PROC RETURNS [iocb: LONG POINTER] = {
IF iocbChain # NIL THEN
{ iocb ← iocbChain; iocbChain ← iocbChain.next}
ELSE iocb ← VM.lowCore.NEW[IocbType[NewEthernetFace.controlBlockSize]];
};
FreeOneIOCB: PUBLIC PROC[iocbPtr: LONG POINTER] = {
i: LONG POINTER TO IocbType = LOOPHOLE[iocbPtr];
i.next← iocbChain; iocbChain← i;
};
END.