[NTOSKRNL] Add a non paged memory dumper in case of low memory situation.
authorPierre Schweitzer <pierre@reactos.org>
Tue, 5 Dec 2017 22:19:11 +0000 (23:19 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Tue, 5 Dec 2017 22:19:11 +0000 (23:19 +0100)
Its purpose is to dump the non paged consumption, tag by tag,
to allow tracking potential faulting driver in case ReactOS starts lacking memory.
This will look like what !poolused outputs, even though it doesn't deal with paged pool.

Thanks to Thomas for his kind review and improvement suggestions.

CORE-14048

ntoskrnl/mm/ARM3/expool.c

index 73a229d..2b7effd 100644 (file)
@@ -460,6 +460,79 @@ ExpComputePartialHashForAddress(IN PVOID BaseAddress)
     return (Result >> 24) ^ (Result >> 16) ^ (Result >> 8) ^ Result;
 }
 
     return (Result >> 24) ^ (Result >> 16) ^ (Result >> 8) ^ Result;
 }
 
+FORCEINLINE
+BOOLEAN
+ExpTagAllowPrint(CHAR Tag)
+{
+    if ((Tag >= 'a' && Tag <= 'z') ||
+        (Tag >= 'A' && Tag <= 'Z') ||
+        Tag == ' ')
+    {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+VOID
+MiDumpNonPagedPoolConsumers(VOID)
+{
+    USHORT i;
+
+    DPRINT1("---------------------\n");
+    DPRINT1("Out of memory dumper!\n");
+
+    //
+    // We'll extract allocations for all the tracked pools
+    //
+    for (i = 0; i < PoolTrackTableSize; ++i)
+    {
+        PPOOL_TRACKER_TABLE TableEntry;
+
+        TableEntry = &PoolTrackTable[i];
+
+        //
+        // We only care about non paged
+        //
+        if (TableEntry->NonPagedBytes != 0)
+        {
+            //
+            // If there's a tag, attempt to do a pretty print
+            //
+            if (TableEntry->Key != 0 && TableEntry->Key != TAG_NONE)
+            {
+                CHAR Tag[4];
+
+                //
+                // Extract each 'component' and check whether they are printable
+                //
+                Tag[0] = TableEntry->Key & 0xFF;
+                Tag[1] = TableEntry->Key >> 8 & 0xFF;
+                Tag[2] = TableEntry->Key >> 16 & 0xFF;
+                Tag[3] = TableEntry->Key >> 24 & 0xFF;
+
+                if (ExpTagAllowPrint(Tag[0]) && ExpTagAllowPrint(Tag[1]) && ExpTagAllowPrint(Tag[2]) && ExpTagAllowPrint(Tag[3]))
+                {
+                    //
+                    // Print in reversed order to match what is in source code
+                    //
+                    DPRINT1("Tag: '%c%c%c%c', Size: %ld\n", Tag[3], Tag[2], Tag[1], Tag[0], TableEntry->NonPagedBytes);
+                }
+                else
+                {
+                    DPRINT1("Tag: %x, Size: %ld\n", TableEntry->Key, TableEntry->NonPagedBytes);
+                }
+            }
+            else
+            {
+                DPRINT1("Anon, Size: %ld\n", TableEntry->NonPagedBytes);
+            }
+        }
+    }
+
+    DPRINT1("---------------------\n");
+}
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 VOID
 /* PRIVATE FUNCTIONS **********************************************************/
 
 VOID
@@ -1641,6 +1714,14 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
         Entry = MiAllocatePoolPages(OriginalType, NumberOfBytes);
         if (!Entry)
         {
         Entry = MiAllocatePoolPages(OriginalType, NumberOfBytes);
         if (!Entry)
         {
+            //
+            // If non paged backed, display current consumption
+            //
+            if ((OriginalType & BASE_POOL_TYPE_MASK) == NonPagedPool)
+            {
+                MiDumpNonPagedPoolConsumers();
+            }
+
             //
             // Must succeed pool is deprecated, but still supported. These allocation
             // failures must cause an immediate bugcheck
             //
             // Must succeed pool is deprecated, but still supported. These allocation
             // failures must cause an immediate bugcheck
@@ -1967,6 +2048,14 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
     Entry = MiAllocatePoolPages(OriginalType, PAGE_SIZE);
     if (!Entry)
     {
     Entry = MiAllocatePoolPages(OriginalType, PAGE_SIZE);
     if (!Entry)
     {
+        //
+        // If non paged backed, display current consumption
+        //
+        if ((OriginalType & BASE_POOL_TYPE_MASK) == NonPagedPool)
+        {
+            MiDumpNonPagedPoolConsumers();
+        }
+
         //
         // Must succeed pool is deprecated, but still supported. These allocation
         // failures must cause an immediate bugcheck
         //
         // Must succeed pool is deprecated, but still supported. These allocation
         // failures must cause an immediate bugcheck