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];
};
IocbType:
TYPE =
RECORD[
next: LONG POINTER TO IocbType,
rest: SEQUENCE COMPUTED CARDINAL OF WORD
];