diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/tdi/acd/mem.c | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/private/ntos/tdi/acd/mem.c b/private/ntos/tdi/acd/mem.c new file mode 100644 index 000000000..e3c9166c1 --- /dev/null +++ b/private/ntos/tdi/acd/mem.c @@ -0,0 +1,289 @@ +/*++ + +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 |