365 lines
8.1 KiB
C
365 lines
8.1 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1995 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
inc\ppool.h
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Structures and #defines for managing NDIS_BUFFER pools. This is
|
||
|
merely a reformatted version of SteveC's l2tp\bpool.h
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
|
||
|
#ifndef __BPOOL_H__
|
||
|
#define __BPOOL_H__
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Data structures
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
//
|
||
|
// Buffer pool control block. A buffer pool prevents fragmentation of the
|
||
|
// non-paged memory pool by allocating the memory for a group of buffers in a
|
||
|
// single contiguous block. At user's option, the buffer pool routines may
|
||
|
// allocate a pool of NDIS_BUFFER buffer descriptors and associate each with
|
||
|
// the memory buffers sliced from the contiguous block. This allows the
|
||
|
// buffer to be reused while the virtual->physical memory mapping is performed
|
||
|
// only once. All necessary pool growth and shrinkage is handled internally.
|
||
|
//
|
||
|
|
||
|
|
||
|
typedef struct _BUFFER_POOL
|
||
|
{
|
||
|
//
|
||
|
// Size in bytes of an individual buffer in the pool.
|
||
|
//
|
||
|
|
||
|
ULONG ulBufferSize;
|
||
|
|
||
|
//
|
||
|
// The optimal number of buffers to allocate in each buffer block.
|
||
|
//
|
||
|
|
||
|
ULONG ulBuffersPerBlock;
|
||
|
|
||
|
//
|
||
|
// Maximum number of individual buffers that may be allocated in the
|
||
|
// entire pool or 0 for unlimited.
|
||
|
//
|
||
|
|
||
|
ULONG ulMaxBuffers;
|
||
|
|
||
|
//
|
||
|
// Current number of individual buffers allocated in the entire pool.
|
||
|
//
|
||
|
|
||
|
ULONG ulCurBuffers;
|
||
|
|
||
|
//
|
||
|
// Garbage collection occurs after this many calls to FreeBufferToPool.
|
||
|
//
|
||
|
|
||
|
ULONG ulFreesPerCollection;
|
||
|
|
||
|
//
|
||
|
// Number of calls to FreeBufferToPool since a garbage collection.
|
||
|
//
|
||
|
|
||
|
ULONG ulFreesSinceCollection;
|
||
|
|
||
|
//
|
||
|
// Indicates an NDIS_BUFFER is to be associated with each individual
|
||
|
// buffer in the pool.
|
||
|
//
|
||
|
|
||
|
BOOLEAN fAssociateNdisBuffer;
|
||
|
|
||
|
//
|
||
|
// True if we allocate a whole page of memory
|
||
|
//
|
||
|
|
||
|
BOOLEAN fAllocatePage;
|
||
|
|
||
|
//
|
||
|
// Memory identification tag for allocated blocks.
|
||
|
//
|
||
|
|
||
|
ULONG ulTag;
|
||
|
|
||
|
//
|
||
|
// Head of the double linked list of BUFFER_BLOCKs. Access to the list
|
||
|
// is protected with 'lock' in this structure.
|
||
|
//
|
||
|
|
||
|
LIST_ENTRY leBlockHead;
|
||
|
|
||
|
//
|
||
|
// Head of the double linked list of free BUFFER_HEADs. Each BUFFER_HEAD
|
||
|
// in the list is ready to go, i.e. it preceeds it's already allocated
|
||
|
// memory buffer and, if appropriate, has an NDIS_BUFFER associated with
|
||
|
// it.
|
||
|
// Access to the list is protected by 'lock' in this structure.
|
||
|
// Interlocked push/pop is not used because (a) the list of blocks and the
|
||
|
// list of buffers must lock each other and (b) double links are necessary
|
||
|
// for garbage collection.
|
||
|
//
|
||
|
|
||
|
LIST_ENTRY leFreeBufferHead;
|
||
|
|
||
|
//
|
||
|
// This lock protects this structure and both the list of blocks and the
|
||
|
// list of buffers.
|
||
|
//
|
||
|
|
||
|
RT_LOCK rlLock;
|
||
|
|
||
|
}BUFFER_POOL, *PBUFFER_POOL;
|
||
|
|
||
|
//
|
||
|
// Header of a single block of buffers from a buffer pool. The BUFFER_HEAD of
|
||
|
// the first buffer immediately follows.
|
||
|
//
|
||
|
|
||
|
typedef struct _BUFFER_BLOCK
|
||
|
{
|
||
|
//
|
||
|
// Link to the prev/next buffer block header in the buffer pool's list.
|
||
|
//
|
||
|
|
||
|
LIST_ENTRY leBlockLink;
|
||
|
|
||
|
//
|
||
|
// NDIS's handle of the pool of NDIS_BUFFER descriptors associated with
|
||
|
// this block, or NULL if none. (Note: With the current NT implementation
|
||
|
// of NDIS_BUFFER as MDL this is always NULL).
|
||
|
//
|
||
|
|
||
|
NDIS_HANDLE nhNdisPool;
|
||
|
|
||
|
//
|
||
|
// Back pointer to the buffer pool.
|
||
|
//
|
||
|
|
||
|
PBUFFER_POOL pPool;
|
||
|
|
||
|
//
|
||
|
// Number of individual buffers in this block on the free list.
|
||
|
//
|
||
|
|
||
|
ULONG ulFreeBuffers;
|
||
|
|
||
|
}BUFFER_BLOCK, *PBUFFER_BLOCK;
|
||
|
|
||
|
#define ALIGN8_BLOCK_SIZE (ALIGN_UP(sizeof(BUFFER_BLOCK), ULONGLONG))
|
||
|
|
||
|
//
|
||
|
// Header of an individual buffer. The buffer memory itself immediately
|
||
|
// follows.
|
||
|
//
|
||
|
|
||
|
typedef struct _BUFFER_HEAD
|
||
|
{
|
||
|
//
|
||
|
// Links to prev/next buffer header in the buffer pool's free list.
|
||
|
//
|
||
|
|
||
|
LIST_ENTRY leFreeBufferLink;
|
||
|
|
||
|
#if LIST_DBG
|
||
|
|
||
|
BOOLEAN bBusy;
|
||
|
LIST_ENTRY leListLink;
|
||
|
ULONG ulAllocFile;
|
||
|
ULONG ulAllocLine;
|
||
|
ULONG ulFreeFile;
|
||
|
ULONG ulFreeLine;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Back link to owning buffer block header.
|
||
|
//
|
||
|
|
||
|
PBUFFER_BLOCK pBlock;
|
||
|
|
||
|
//
|
||
|
// NDIS buffer descriptor of this buffer. This is NULL unless the pool is
|
||
|
// initialized with the 'fAssociateNdisBuffer' option.
|
||
|
//
|
||
|
|
||
|
PNDIS_BUFFER pNdisBuffer;
|
||
|
|
||
|
}BUFFER_HEAD, *PBUFFER_HEAD;
|
||
|
|
||
|
#define ALIGN8_HEAD_SIZE (ALIGN_UP(sizeof(BUFFER_HEAD), ULONGLONG))
|
||
|
|
||
|
#if LIST_DBG
|
||
|
|
||
|
#define NotOnList(p) \
|
||
|
(((p)->leListLink.Flink == NULL) && ((p)->leListLink.Blink == NULL))
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#define BUFFER_FROM_HEAD(p) (PBYTE)((ULONG_PTR)(p) + ALIGN8_HEAD_SIZE)
|
||
|
|
||
|
#define HEAD_FROM_BUFFER(p) (PBUFFER_HEAD)((ULONG_PTR)(p) - ALIGN8_HEAD_SIZE)
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Interface prototypes and inline definitions
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
VOID
|
||
|
InitBufferPool(
|
||
|
OUT PBUFFER_POOL pPool,
|
||
|
IN ULONG ulBufferSize,
|
||
|
IN ULONG ulMaxBuffers,
|
||
|
IN ULONG ulBuffersPerBlock,
|
||
|
IN ULONG ulFreesPerCollection,
|
||
|
IN BOOLEAN fAssociateNdisBuffer,
|
||
|
IN ULONG ulTag
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
FreeBufferPool(
|
||
|
IN PBUFFER_POOL pPool
|
||
|
);
|
||
|
|
||
|
|
||
|
#if !LIST_DBG
|
||
|
|
||
|
BOOLEAN
|
||
|
GetBufferListFromPool(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN ULONG ulNumBuffersNeeded,
|
||
|
OUT PLIST_ENTRY pleList
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
FreeBufferListToPool(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN PLIST_ENTRY pleList
|
||
|
);
|
||
|
|
||
|
PBYTE
|
||
|
GetBufferFromPool(
|
||
|
IN PBUFFER_POOL pPool
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
FreeBufferToPoolEx(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN PBYTE pbyBuffer,
|
||
|
IN BOOLEAN fGarbageCollection
|
||
|
);
|
||
|
|
||
|
NTSTATUS
|
||
|
GetBufferChainFromPool(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN OUT PNDIS_PACKET pnpPacket,
|
||
|
IN ULONG ulBufferLength,
|
||
|
OUT NDIS_BUFFER **ppnbFirstBuffer,
|
||
|
OUT VOID **ppvFirstData
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
FreeBufferChainToPool(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN PNDIS_PACKET pnpPacket
|
||
|
);
|
||
|
|
||
|
#else
|
||
|
|
||
|
#define GetBufferListFromPool(a,b,c) GETLIST((a),(b),(c),__FILE_SIG__,__LINE__)
|
||
|
|
||
|
BOOLEAN
|
||
|
GETLIST(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN ULONG ulNumBuffersNeeded,
|
||
|
OUT PLIST_ENTRY pleList,
|
||
|
IN ULONG ulFileSig,
|
||
|
IN ULONG ulLine
|
||
|
);
|
||
|
|
||
|
#define FreeBufferListToPool(a,b) FREELIST((a),(b),__FILE_SIG__,__LINE__)
|
||
|
|
||
|
VOID
|
||
|
FREELIST(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN PLIST_ENTRY pleList,
|
||
|
IN ULONG ulFileSig,
|
||
|
IN ULONG ulLine
|
||
|
);
|
||
|
|
||
|
#define GetBufferFromPool(a) GET((a),__FILE_SIG__,__LINE__)
|
||
|
|
||
|
PBYTE
|
||
|
GET(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN ULONG ulFileSig,
|
||
|
IN ULONG ulLine
|
||
|
);
|
||
|
|
||
|
#define FreeBufferToPoolEx(a,b,c) FREE((a),(b),(c),__FILE_SIG__,__LINE__)
|
||
|
|
||
|
VOID
|
||
|
FREE(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN PBYTE pbyBuffer,
|
||
|
IN BOOLEAN fGarbageCollection,
|
||
|
IN ULONG ulFileSig,
|
||
|
IN ULONG ulLine
|
||
|
);
|
||
|
|
||
|
#define GetBufferChainFromPool(a,b,c,d,e) GETCHAIN((a),(b),(c),(d),(e),__FILE_SIG__,__LINE__)
|
||
|
|
||
|
NTSTATUS
|
||
|
GETCHAIN(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN OUT PNDIS_PACKET pnpPacket,
|
||
|
IN ULONG ulBufferLength,
|
||
|
OUT NDIS_BUFFER **ppnbFirstBuffer,
|
||
|
OUT VOID **ppvFirstData,
|
||
|
IN ULONG ulFileSig,
|
||
|
IN ULONG ulLine
|
||
|
);
|
||
|
|
||
|
#define FreeBufferChainToPool(a,b) FREECHAIN((a),(b),__FILE_SIG__,__LINE__)
|
||
|
|
||
|
VOID
|
||
|
FREECHAIN(
|
||
|
IN PBUFFER_POOL pPool,
|
||
|
IN PNDIS_PACKET pnpPacket,
|
||
|
IN ULONG ulFileSig,
|
||
|
IN ULONG ulLine
|
||
|
);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#define FreeBufferToPool(p,b) FreeBufferToPoolEx((p),(b), TRUE)
|
||
|
|
||
|
PNDIS_BUFFER
|
||
|
GetNdisBufferFromBuffer(
|
||
|
IN PBYTE pbyBuffer
|
||
|
);
|
||
|
|
||
|
ULONG
|
||
|
BufferSizeFromBuffer(
|
||
|
IN PBYTE pbyBuffer
|
||
|
);
|
||
|
|
||
|
PNDIS_BUFFER
|
||
|
PoolHandleForNdisCopyBufferFromBuffer(
|
||
|
IN PBYTE pbyBuffer
|
||
|
);
|
||
|
|
||
|
|
||
|
#endif // __BPOOL_H__
|