https://git.reactos.org/?p=reactos.git;a=commitdiff;h=149e1a261013c5c3b24ab…
commit 149e1a261013c5c3b24ab1c5ee82517646c3740f
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Tue Dec 5 23:19:11 2017 +0100
[NTOSKRNL] Add a non paged memory dumper in case of low memory situation.
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 | 89 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/ntoskrnl/mm/ARM3/expool.c b/ntoskrnl/mm/ARM3/expool.c
index 73a229d431..2b7effdea3 100644
--- a/ntoskrnl/mm/ARM3/expool.c
+++ b/ntoskrnl/mm/ARM3/expool.c
@@ -460,6 +460,79 @@ ExpComputePartialHashForAddress(IN PVOID BaseAddress)
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
@@ -1641,6 +1714,14 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
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
@@ -1967,6 +2048,14 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
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