mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
7.4 KiB
289 lines
7.4 KiB
/*++
|
|
|
|
Copyright(c) 1995 Microsoft Corporation
|
|
|
|
MODULE NAME
|
|
table.c
|
|
|
|
ABSTRACT
|
|
Generic hash table manipulation routines.
|
|
|
|
AUTHOR
|
|
Anthony Discolo (adiscolo) 28-Jul-1995
|
|
|
|
REVISION HISTORY
|
|
|
|
--*/
|
|
|
|
#include <ndis.h>
|
|
#include <cxport.h>
|
|
#include <tdi.h>
|
|
#include <tdikrnl.h>
|
|
#include <tdistat.h>
|
|
#include <tdiinfo.h>
|
|
#include <acd.h>
|
|
#include <acdapi.h>
|
|
|
|
#include "acddefs.h"
|
|
#include "mem.h"
|
|
#include "debug.h"
|
|
|
|
//
|
|
// The maximum number of allocated
|
|
// objects we allocate from outside
|
|
// our zones.
|
|
//
|
|
#define MAX_ALLOCATED_OBJECTS 100
|
|
|
|
//
|
|
// Rounding up macro.
|
|
//
|
|
#define ROUNDUP(n, b) (((n) + ((b) - 1)) & ~((b) - 1))
|
|
|
|
//
|
|
// Map an object type to a zone.
|
|
//
|
|
#define OBJECT_INFO(fObject) \
|
|
(fObject < ACD_OBJECT_MAX) ? &AcdObjectInfoG[fObject] : &AcdObjectInfoG[ACD_OBJECT_MAX]
|
|
|
|
//
|
|
// The spin lock for this module.
|
|
//
|
|
KSPIN_LOCK AcdMemSpinLockG;
|
|
|
|
//
|
|
// Zone-based object information. One zone
|
|
// per object type.
|
|
//
|
|
typedef struct _OBJECT_INFORMATION {
|
|
ZONE_HEADER zone;
|
|
ULONG ulSize; // object size
|
|
ULONG ulTag; // ExAllocateFromPoolWithTag() tag
|
|
ULONG ulCurrent; // # currently allocated in zone
|
|
ULONG ulTotal; // total # zone allocations
|
|
} OBJECT_INFORMATION, *POBJECT_INFORMATION;
|
|
|
|
OBJECT_INFORMATION AcdObjectInfoG[ACD_OBJECT_MAX + 1];
|
|
|
|
//
|
|
// Pool-based object allocation. This is for
|
|
// objects that don't fit into any of the zones,
|
|
// or when the zone is full.
|
|
//
|
|
typedef struct _POOL_INFORMATION {
|
|
ULONG cbMin; // minimum size
|
|
ULONG cbMax; // maximum size
|
|
ULONG ulCurrent; // # current allocations
|
|
ULONG ulTotal; // total allocations
|
|
ULONG ulFailures; // total failures
|
|
} POOL_INFORMATION, *PPOOL_INFORMATION;
|
|
|
|
POOL_INFORMATION AcdPoolInfoG;
|
|
|
|
|
|
|
|
VOID
|
|
InitializeObjectAllocator()
|
|
{
|
|
NTSTATUS status;
|
|
PVOID pMem;
|
|
ULONG ulSize;
|
|
|
|
KeInitializeSpinLock(&AcdMemSpinLockG);
|
|
//
|
|
// Initialize zone 0 (ACD_OBJECT_CONNECTION).
|
|
//
|
|
AcdObjectInfoG[ACD_OBJECT_CONNECTION].ulTag = 'NdcA';
|
|
AcdObjectInfoG[ACD_OBJECT_CONNECTION].ulSize =
|
|
ROUNDUP(sizeof (ACD_CONNECTION), 8);
|
|
ulSize = PAGE_SIZE;
|
|
pMem = ExAllocatePoolWithTag(
|
|
NonPagedPool,
|
|
ulSize,
|
|
AcdObjectInfoG[ACD_OBJECT_CONNECTION].ulTag);
|
|
ASSERT(pMem != NULL);
|
|
status = ExInitializeZone(
|
|
&AcdObjectInfoG[ACD_OBJECT_CONNECTION].zone,
|
|
AcdObjectInfoG[ACD_OBJECT_CONNECTION].ulSize,
|
|
pMem,
|
|
ulSize);
|
|
IF_ACDDBG(ACD_DEBUG_MEMORY) {
|
|
AcdPrint((
|
|
"InitializeObjectAllocator: zone 0 created: blksiz=%d, size=%d (status=%d)\n",
|
|
AcdObjectInfoG[ACD_OBJECT_CONNECTION].ulSize,
|
|
ulSize,
|
|
status));
|
|
}
|
|
//
|
|
// Initialize zone 1 (ACD_OBJECT_COMPLETION).
|
|
//
|
|
AcdObjectInfoG[ACD_OBJECT_MAX].ulTag = 'MdcA';
|
|
//
|
|
// Allow for up to 6 parameters to a completion
|
|
// request (6 used by tcpip.sys).
|
|
//
|
|
AcdObjectInfoG[ACD_OBJECT_MAX].ulSize =
|
|
ROUNDUP(sizeof (ACD_COMPLETION) + (6 * sizeof (PVOID)), 8);
|
|
ulSize = ROUNDUP(6 * AcdObjectInfoG[ACD_OBJECT_MAX].ulSize, PAGE_SIZE),
|
|
pMem = ExAllocatePoolWithTag(
|
|
NonPagedPool,
|
|
ulSize,
|
|
AcdObjectInfoG[ACD_OBJECT_MAX].ulTag);
|
|
ASSERT(pMem != NULL);
|
|
status = ExInitializeZone(
|
|
&AcdObjectInfoG[ACD_OBJECT_MAX].zone,
|
|
AcdObjectInfoG[ACD_OBJECT_MAX].ulSize,
|
|
pMem,
|
|
ulSize);
|
|
IF_ACDDBG(ACD_DEBUG_MEMORY) {
|
|
AcdPrint((
|
|
"InitializeObjectAllocator: zone 1 created: blksiz=%d size=%d (status=%d)\n",
|
|
AcdObjectInfoG[ACD_OBJECT_MAX].ulSize,
|
|
ulSize,
|
|
status));
|
|
}
|
|
//
|
|
// Initialize the pool info.
|
|
//
|
|
AcdPoolInfoG.cbMin = 0xffffffff;
|
|
AcdPoolInfoG.cbMax = 0;
|
|
AcdPoolInfoG.ulCurrent = 0;
|
|
AcdPoolInfoG.ulTotal = 0;
|
|
AcdPoolInfoG.ulFailures = 0;
|
|
} // InitializeObjectAllocator
|
|
|
|
|
|
|
|
PVOID
|
|
AllocateObjectMemory(
|
|
IN ULONG fObject
|
|
)
|
|
{
|
|
KIRQL irql;
|
|
POBJECT_INFORMATION pObjectInfo = OBJECT_INFO(fObject);
|
|
PVOID pObject;
|
|
ULONG cbBytes = 0, ulTag;
|
|
static ULONG nAllocations = 0;
|
|
|
|
KeAcquireSpinLock(&AcdMemSpinLockG, &irql);
|
|
//
|
|
// If the zone is full, or the object
|
|
// size is greater than the zone object size,
|
|
// then use the pool allocator.
|
|
//
|
|
if (fObject > pObjectInfo->zone.BlockSize) {
|
|
cbBytes = fObject;
|
|
ulTag = 'PdcA';
|
|
}
|
|
else if (ExIsFullZone(&pObjectInfo->zone)) {
|
|
cbBytes = pObjectInfo->ulSize;
|
|
ulTag = pObjectInfo->ulTag;
|
|
}
|
|
if (cbBytes) {
|
|
//
|
|
// Limit memory usage under stress.
|
|
// If we have more than 100 outstanding
|
|
// requests, then we start dropping
|
|
// them.
|
|
//
|
|
if (AcdPoolInfoG.ulCurrent < MAX_ALLOCATED_OBJECTS)
|
|
pObject = ExAllocatePoolWithTag(NonPagedPool, cbBytes, ulTag);
|
|
else {
|
|
pObject = NULL;
|
|
AcdPoolInfoG.ulFailures++;
|
|
goto done;
|
|
}
|
|
if (cbBytes < AcdPoolInfoG.cbMin)
|
|
AcdPoolInfoG.cbMin = cbBytes;
|
|
if (cbBytes > AcdPoolInfoG.cbMax)
|
|
AcdPoolInfoG.cbMax = cbBytes;
|
|
AcdPoolInfoG.ulCurrent++;
|
|
AcdPoolInfoG.ulTotal++;
|
|
IF_ACDDBG(ACD_DEBUG_MEMORY) {
|
|
AcdPrint((
|
|
"AllocateObjectMemory: allocated type %d from pool: pObject=0x%x\n",
|
|
fObject,
|
|
pObject));
|
|
}
|
|
}
|
|
else {
|
|
pObject = ExAllocateFromZone(&pObjectInfo->zone);
|
|
pObjectInfo->ulCurrent++;
|
|
pObjectInfo->ulTotal++;
|
|
IF_ACDDBG(ACD_DEBUG_MEMORY) {
|
|
AcdPrint((
|
|
"AllocateObjectMemory: allocated type %d from zone: pObject=0x%x\n",
|
|
fObject,
|
|
pObject));
|
|
}
|
|
}
|
|
#if DBG
|
|
IF_ACDDBG(ACD_DEBUG_MEMORY) {
|
|
INT i;
|
|
|
|
if (!(++nAllocations % 10)) {
|
|
for (i = 0; i <= ACD_OBJECT_MAX; i++) {
|
|
AcdPrint((
|
|
"Zone %d: ulCurrent=%d, ulTotal=%d\n",
|
|
i,
|
|
AcdObjectInfoG[i].ulCurrent,
|
|
AcdObjectInfoG[i].ulTotal));
|
|
}
|
|
AcdPrint((
|
|
"Pool: ulCurrent=%d, ulTotal=%d\n",
|
|
AcdPoolInfoG.ulCurrent,
|
|
AcdPoolInfoG.ulTotal));
|
|
}
|
|
}
|
|
#endif
|
|
done:
|
|
KeReleaseSpinLock(&AcdMemSpinLockG, irql);
|
|
|
|
return pObject;
|
|
} // AllocateObjectMemory
|
|
|
|
|
|
|
|
VOID
|
|
FreeObjectMemory(
|
|
IN PVOID pObject
|
|
)
|
|
{
|
|
KIRQL irql;
|
|
INT i;
|
|
POBJECT_INFORMATION pObjectInfo;
|
|
|
|
KeAcquireSpinLock(&AcdMemSpinLockG, &irql);
|
|
for (i = 0; i <= ACD_OBJECT_MAX; i++) {
|
|
pObjectInfo = &AcdObjectInfoG[i];
|
|
|
|
if (ExIsObjectInFirstZoneSegment(&pObjectInfo->zone, pObject)) {
|
|
ExFreeToZone(&pObjectInfo->zone, pObject);
|
|
pObjectInfo->ulCurrent--;
|
|
IF_ACDDBG(ACD_DEBUG_MEMORY) {
|
|
AcdPrint((
|
|
"FreeObjectMemory: freed type %d into zone: pObject=0x%x\n",
|
|
i,
|
|
pObject));
|
|
}
|
|
goto done;
|
|
}
|
|
}
|
|
ExFreePool(pObject);
|
|
AcdPoolInfoG.ulCurrent--;
|
|
IF_ACDDBG(ACD_DEBUG_MEMORY) {
|
|
AcdPrint((
|
|
"FreeObjectMemory: freed into pool: pObject=0x%x\n",
|
|
pObject));
|
|
}
|
|
done:
|
|
KeReleaseSpinLock(&AcdMemSpinLockG, irql);
|
|
} // FreeObjectMemory
|
|
|
|
|
|
|
|
VOID
|
|
FreeObjectAllocator()
|
|
{
|
|
// Apparently, we can't do this?
|
|
} // FreeObjectAllocator
|