-- File: PoolCool.mesa,  Last Edit: HGM  October 15, 1979  8:07 PM
-- Copyright  Xerox Corporation 1979, 1980
DIRECTORY
  CommUtilDefs: FROM "CommUtilDefs" USING [
    AllocateHyperspace, FreeHyperspace, InitializeMonitor],
  DriverDefs: FROM "DriverDefs" USING [doDebug, Glitch],
  BufferDefs: FROM "BufferDefs" USING [
    Buffer, BufferObject, BufferPool, Dequeue, Enqueue,
    QueueInitialize, QueueCleanup, ReturnFreeBuffer],
  DriverTypes: FROM "DriverTypes" USING [unsealed, bufferSeal, bufferPoolSeal];
PoolCool: PROGRAM
  IMPORTS CommUtilDefs, DriverDefs, BufferDefs
  EXPORTS BufferDefs
  SHARES BufferDefs =
BEGIN OPEN DriverDefs, BufferDefs;
-- size of a buffer without any data
rawOverhead: CARDINAL = SIZE[raw BufferDefs.BufferObject];
-- 1 extra for checksum
pupOverhead: CARDINAL = SIZE[pupWords pup BufferDefs.BufferObject]+1;
overhead: CARDINAL =  MAX[
    pupOverhead,
    SIZE[rppWords rpp BufferDefs.BufferObject]+1];
BufferPoolSealBroken: PUBLIC ERROR = CODE;
BufferPoolMake: PUBLIC PROCEDURE [
    pool: BufferPool, numberOfBuffers, dataWordsPerBuffer: CARDINAL] =
  BEGIN
  b: Buffer;
  i: CARDINAL;
  pool↑ ← [
    LOCK: ,
    freeQueue: ,
    seal: DriverTypes.bufferPoolSeal,
    freeQueueNotEmpty: ,
    total: numberOfBuffers, reserve: 0, send: 0, recveive: 0,
    dataWordsPerBuffer: dataWordsPerBuffer,
    firstBuffer: NIL,
    bufferSize: big,
    wordsPerBuffer: dataWordsPerBuffer+overhead ];
  pool.firstBuffer ←
    CommUtilDefs.AllocateHyperspace[pool.wordsPerBuffer*numberOfBuffers];
  CommUtilDefs.InitializeMonitor[@pool.LOCK];
  QueueInitialize[@pool.freeQueue];
  b ← pool.firstBuffer;
  FOR i IN [0..numberOfBuffers) DO
    b.iocbChain ← b.userData ← NIL;
    b.allNets ← b.bypassZeroNet ← FALSE;
    b.type ← raw;
    b.size ← big;
    b.pupLength ← b.length ← 0;
    b.bufferNumber ← i;
    b.pupType ← pt177;
    b.queue ← NIL;
    b.pool ← pool;
    b.next ← NIL;
    IF doDebug THEN b.seal ← DriverTypes.bufferSeal;
    b.requeueProcedure ← ReturnFreeBuffer;
    Enqueue[@pool.freeQueue,b];
    b ← b+pool.wordsPerBuffer;
    ENDLOOP;
  END;
BufferPoolDestroy: PUBLIC PROCEDURE [pool: BufferPool] =
  BEGIN
  UNTIL Dequeue[@pool.freeQueue]=NIL DO ENDLOOP;
  QueueCleanup[@pool.freeQueue];
  CommUtilDefs.FreeHyperspace[pool.firstBuffer];
  IF doDebug THEN pool.seal ← DriverTypes.unsealed;
  END;
EnumerateBuffersInPool: PUBLIC PROCEDURE [pool: BufferPool, proc: PROCEDURE[Buffer]] =
  BEGIN OPEN pool;
  wordsPerBuffer: CARDINAL;
  b: BufferDefs.Buffer ← firstBuffer;
  i: CARDINAL;
  IF doDebug AND seal=DriverTypes.bufferPoolSeal THEN Glitch[BufferPoolSealBroken];
  wordsPerBuffer ← dataWordsPerBuffer+overhead;
  FOR i IN [0..total) DO
    proc[b];
    b ← b+wordsPerBuffer;
    ENDLOOP;
  END;
END.  -- PoolCool