windows-nt/Source/XPSP1/NT/net/rras/ip/nathlp/dll/buffer.cpp

257 lines
4.7 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1998, Microsoft Corporation
Module Name:
buffer.c
Abstract:
This module contains code for buffer-management.
Author:
Abolade Gbadegesin (aboladeg) 2-Mar-1998
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
LIST_ENTRY NhpBufferQueue;
LONG NhpBufferQueueLength;
CRITICAL_SECTION NhpBufferQueueLock;
PNH_BUFFER
NhAcquireFixedLengthBuffer(
VOID
)
/*++
Routine Description:
This routine is invoked to acquire an I/O buffer.
If no buffer is available on the buffer queue, a new one is obtained.
Arguments:
none.
Return Value:
PNH_BUFFER - the buffer allocated
--*/
{
PNH_BUFFER Buffer;
PLIST_ENTRY Link;
EnterCriticalSection(&NhpBufferQueueLock);
if (!IsListEmpty(&NhpBufferQueue)) {
Link = RemoveHeadList(&NhpBufferQueue);
LeaveCriticalSection(&NhpBufferQueueLock);
InterlockedDecrement(&NhpBufferQueueLength);
Buffer = CONTAINING_RECORD(Link, NH_BUFFER, Link);
Buffer->Type = NhFixedLengthBufferType;
return Buffer;
}
LeaveCriticalSection(&NhpBufferQueueLock);
Buffer = NH_ALLOCATE_BUFFER();
if (Buffer) {
Buffer->Type = NhFixedLengthBufferType;
}
return Buffer;
} // NhAcquireFixedLengthBuffer
PNH_BUFFER
NhAcquireVariableLengthBuffer(
ULONG Length
)
/*++
Routine Description:
This routine is invoked to acquire an I/O buffer of non-standard size.
If the length requested is less than or equal to 'NH_BUFFER_SIZE',
a buffer from the shared buffer-queue is returned.
Otherwise, a buffer is especially allocated for the caller.
Arguments:
Length - the length of the buffer required.
Return Value:
PNH_BUFFER - the buffer allocated.
--*/
{
PNH_BUFFER Buffer;
if (Length <= NH_BUFFER_SIZE) {
return NhAcquireFixedLengthBuffer();
}
Buffer = reinterpret_cast<PNH_BUFFER>(
NH_ALLOCATE(FIELD_OFFSET(NH_BUFFER, Buffer[Length]))
);
if (Buffer) { Buffer->Type = NhVariableLengthBufferType; }
return Buffer;
} // NhAcquireVariableLengthBuffer
PNH_BUFFER
NhDuplicateBuffer(
PNH_BUFFER Bufferp
)
/*++
Routine Description:
This routine creates a duplicate of the given buffer,
including both its data and its control information.
N.B. Variable-length buffers cannot be duplicated by this routine.
Arguments:
Bufferp - the buffer to be duplicated
Return Value:
PNH_BUFFER - a pointer to the duplicate
--*/
{
PNH_BUFFER Duplicatep;
ASSERT(Bufferp->Type == NhFixedLengthBufferType);
if (!(Duplicatep = NhAcquireBuffer())) { return NULL; }
*Duplicatep = *Bufferp;
return Duplicatep;
} // NhDuplicateBuffer
ULONG
NhInitializeBufferManagement(
VOID
)
/*++
Routine Description:
This routine readies the buffer-management for operation.
Arguments:
none.
Return Value:
ULONG - Win32 status code.
--*/
{
ULONG Error = NO_ERROR;
InitializeListHead(&NhpBufferQueue);
NhpBufferQueueLength = 0;
__try {
InitializeCriticalSection(&NhpBufferQueueLock);
} __except(EXCEPTION_EXECUTE_HANDLER) {
NhTrace(
TRACE_FLAG_BUFFER,
"NhInitializeBufferManagement: exception %d creating lock",
Error = GetExceptionCode()
);
}
return Error;
} // NhInitializeBufferManagement
VOID
NhReleaseBuffer(
PNH_BUFFER Bufferp
)
/*++
Routine Description:
This routine is called to release a buffer to the buffer queue.
It attempts to place the buffer on the queue for re-use, unless
the queue is full in which case the buffer is immediately freed.
Arguments:
Bufferp - the buffer to be released
Return Value:
none.
--*/
{
if (NhpBufferQueueLength > NH_MAX_BUFFER_QUEUE_LENGTH ||
Bufferp->Type != NhFixedLengthBufferType) {
NH_FREE_BUFFER(Bufferp);
} else {
EnterCriticalSection(&NhpBufferQueueLock);
InsertHeadList(&NhpBufferQueue, &Bufferp->Link);
LeaveCriticalSection(&NhpBufferQueueLock);
InterlockedIncrement(&NhpBufferQueueLength);
}
} // NhReleaseBuffer
VOID
NhShutdownBufferManagement(
VOID
)
/*++
Routine Description:
This routine cleans up resources used by the buffer-management module.
It assumes the list will not be accessed while the clean up is in progress.
Arguments:
none.
Return Value:
none.
--*/
{
PLIST_ENTRY Link;
PNH_BUFFER Bufferp;
while (!IsListEmpty(&NhpBufferQueue)) {
Link = RemoveHeadList(&NhpBufferQueue);
Bufferp = CONTAINING_RECORD(Link, NH_BUFFER, Link);
NH_FREE_BUFFER(Bufferp);
}
DeleteCriticalSection(&NhpBufferQueueLock);
NhpBufferQueueLength = 0;
} // NhShutdownBufferManagement