DIRECTORY Driver USING [Buffer, BufferObject, Network, wordsInIocb], Process USING [Detach, priorityBackground, SetPriority], SafeStorage USING [EnableFinalization, EstablishFinalization, FinalizationQueue, FQNext, NewFQ, PinObject], VM USING [lowCore]; DriverImpl: CEDAR MONITOR IMPORTS Process, SafeStorage, VM EXPORTS Driver = { Buffer: TYPE = Driver.Buffer; Network: TYPE = Driver.Network; IOCB: TYPE = ARRAY [0..Driver.wordsInIocb) OF WORD; Next: PROC [b: Driver.Buffer] RETURNS [Driver.Buffer] = TRUSTED INLINE { RETURN[LOOPHOLE[b.ovh.next]]; }; buffers: Buffer _ NIL; totalBuffersCreated: INT _ 0; totalBuffersAlloced: INT _ 0; freeBuffers: INT _ 0; AllocBuffer: PUBLIC PROC RETURNS [buffer: Buffer] = { buffer _ AllocBufferInner[]; IF buffer # NIL THEN { buffer.ovh.next _ NIL; RETURN; }; buffer _ NEW[Driver.BufferObject]; SafeStorage.PinObject[buffer]; TRUSTED { iocb: LONG POINTER TO IOCB _ LOOPHOLE[VM.lowCore.NEW[IOCB]]; buffer.ovh.iocb _ iocb; iocb^ _ ALL[0]; }; CountNewBuffer[buffer]; buffer.ovh.next _ NIL; SafeStorage.EnableFinalization[buffer]; }; AllocBufferInner: PUBLIC ENTRY PROC RETURNS [buffer: Buffer] = { IF buffers = NIL THEN RETURN[NIL]; buffer _ buffers; buffers _ Next[buffers]; totalBuffersAlloced _ totalBuffersAlloced.SUCC; freeBuffers _ freeBuffers.PRED; }; CountNewBuffer: PUBLIC ENTRY PROC [buffer: Buffer] = { totalBuffersCreated _ totalBuffersCreated.SUCC; totalBuffersAlloced _ totalBuffersAlloced.SUCC; }; FreeBuffer: PUBLIC ENTRY PROC [b: Buffer] = { b.ovh.next _ buffers; IF b.ovh.socket # NIL THEN ERROR; TRUSTED { buffers _ NARROW[LOOPHOLE[b, REF ANY]]; }; freeBuffers _ freeBuffers.SUCC; }; NoThankYou: PUBLIC PROC [network: Network, b: Buffer, bytes: NAT] RETURNS [Buffer] = { RETURN[b]; }; droppedBuffers: INT _ 0; BufferFinalizer: PROC = { Process.SetPriority[Process.priorityBackground]; DO b: Buffer _ NARROW[SafeStorage.FQNext[bfq]]; SafeStorage.EnableFinalization[b]; FreeBuffer[b]; b _ NIL; droppedBuffers _ droppedBuffers.SUCC; ENDLOOP; }; DropTest: PROC [n: NAT _ 100] = { FOR i: NAT IN [0..n) DO [] _ AllocBuffer[]; ENDLOOP; }; bfq: SafeStorage.FinalizationQueue _ SafeStorage.NewFQ[]; SafeStorage.EstablishFinalization[type: CODE[Driver.BufferObject], npr: 0, fq: bfq]; TRUSTED { Process.Detach[FORK BufferFinalizer[]]; }; }. šDriverImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Hal Murray, May 4, 1986 8:58:25 pm PDT Buffer allocation This is where buffers actually get created. Beware: D0s and DLions have buffer alignment constraints. If anybody wants to run this code on D0s, the microcode should be fixed. DLions (luckily) only require that the first 3 words of the buffer be on the same page. For now, a BufferObject is big enough so that the Allocator gives each one a separate clump of pages. If that ever changes, don't be surprised by obscure troubles. Discard unwanted packets This lives here since this module is already reasonably hot. Finalization Κΰ˜codešœ™Kšœ Οmœ1™