summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/acd/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/tdi/acd/mem.c')
-rw-r--r--private/ntos/tdi/acd/mem.c289
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