ReactOS  0.4.9-dev-717-g6d91262
expool.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
#include <mm/ARM3/miarm.h>
Include dependency graph for expool.c:

Go to the source code of this file.

Classes

struct  _POOL_DPC_CONTEXT
 

Macros

#define NDEBUG
 
#define MODULE_INVOLVED_IN_ARM3
 
#define POOL_BIG_TABLE_ENTRY_FREE   0x1
 
#define POOL_ENTRY(x)   (PPOOL_HEADER)((ULONG_PTR)(x) - sizeof(POOL_HEADER))
 
#define POOL_FREE_BLOCK(x)   (PLIST_ENTRY)((ULONG_PTR)(x) + sizeof(POOL_HEADER))
 
#define POOL_BLOCK(x, i)   (PPOOL_HEADER)((ULONG_PTR)(x) + ((i) * POOL_BLOCK_SIZE))
 
#define POOL_NEXT_BLOCK(x)   POOL_BLOCK((x), (x)->BlockSize)
 
#define POOL_PREV_BLOCK(x)   POOL_BLOCK((x), -((x)->PreviousSize))
 

Typedefs

typedef struct _POOL_DPC_CONTEXT POOL_DPC_CONTEXT
 
typedef struct _POOL_DPC_CONTEXTPPOOL_DPC_CONTEXT
 

Functions

PLIST_ENTRY NTAPI ExpDecodePoolLink (IN PLIST_ENTRY Link)
 
PLIST_ENTRY NTAPI ExpEncodePoolLink (IN PLIST_ENTRY Link)
 
VOID NTAPI ExpCheckPoolLinks (IN PLIST_ENTRY ListHead)
 
VOID NTAPI ExpInitializePoolListHead (IN PLIST_ENTRY ListHead)
 
BOOLEAN NTAPI ExpIsPoolListEmpty (IN PLIST_ENTRY ListHead)
 
VOID NTAPI ExpRemovePoolEntryList (IN PLIST_ENTRY Entry)
 
PLIST_ENTRY NTAPI ExpRemovePoolHeadList (IN PLIST_ENTRY ListHead)
 
PLIST_ENTRY NTAPI ExpRemovePoolTailList (IN PLIST_ENTRY ListHead)
 
VOID NTAPI ExpInsertPoolTailList (IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry)
 
VOID NTAPI ExpInsertPoolHeadList (IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry)
 
VOID NTAPI ExpCheckPoolHeader (IN PPOOL_HEADER Entry)
 
VOID NTAPI ExpCheckPoolAllocation (PVOID P, POOL_TYPE PoolType, ULONG Tag)
 
VOID NTAPI ExpCheckPoolBlocks (IN PVOID Block)
 
FORCEINLINE VOID ExpCheckPoolIrqlLevel (IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN PVOID Entry)
 
FORCEINLINE ULONG ExpComputeHashForTag (IN ULONG Tag, IN SIZE_T BucketMask)
 
FORCEINLINE ULONG ExpComputePartialHashForAddress (IN PVOID BaseAddress)
 
VOID NTAPI INIT_SECTION ExpSeedHotTags (VOID)
 
VOID NTAPI ExpRemovePoolTracker (IN ULONG Key, IN SIZE_T NumberOfBytes, IN POOL_TYPE PoolType)
 
VOID NTAPI ExpInsertPoolTracker (IN ULONG Key, IN SIZE_T NumberOfBytes, IN POOL_TYPE PoolType)
 
VOID NTAPI INIT_SECTION ExInitializePoolDescriptor (IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, IN ULONG Threshold, IN PVOID PoolLock)
 
VOID NTAPI INIT_SECTION InitializePool (IN POOL_TYPE PoolType, IN ULONG Threshold)
 
FORCEINLINE KIRQL ExLockPool (IN PPOOL_DESCRIPTOR Descriptor)
 
FORCEINLINE VOID ExUnlockPool (IN PPOOL_DESCRIPTOR Descriptor, IN KIRQL OldIrql)
 
VOID NTAPI ExpGetPoolTagInfoTarget (IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
 
NTSTATUS NTAPI ExGetPoolTagInfo (IN PSYSTEM_POOLTAG_INFORMATION SystemInformation, IN ULONG SystemInformationLength, IN OUT PULONG ReturnLength OPTIONAL)
 
BOOLEAN NTAPI ExpAddTagForBigPages (IN PVOID Va, IN ULONG Key, IN ULONG NumberOfPages, IN POOL_TYPE PoolType)
 
ULONG NTAPI ExpFindAndRemoveTagBigPages (IN PVOID Va, OUT PULONG_PTR BigPages, IN POOL_TYPE PoolType)
 
VOID NTAPI ExQueryPoolUsage (OUT PULONG PagedPoolPages, OUT PULONG NonPagedPoolPages, OUT PULONG PagedPoolAllocs, OUT PULONG PagedPoolFrees, OUT PULONG PagedPoolLookasideHits, OUT PULONG NonPagedPoolAllocs, OUT PULONG NonPagedPoolFrees, OUT PULONG NonPagedPoolLookasideHits)
 
VOID NTAPI ExReturnPoolQuota (IN PVOID P)
 
PVOID NTAPI ExAllocatePoolWithTag (IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
 
PVOID NTAPI ExAllocatePool (POOL_TYPE PoolType, SIZE_T NumberOfBytes)
 
VOID NTAPI ExFreePoolWithTag (IN PVOID P, IN ULONG TagToFree)
 
VOID NTAPI ExFreePool (PVOID P)
 
SIZE_T NTAPI ExQueryPoolBlockSize (IN PVOID PoolBlock, OUT PBOOLEAN QuotaCharged)
 
PVOID NTAPI ExAllocatePoolWithQuota (IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
 
PVOID NTAPI ExAllocatePoolWithTagPriority (IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag, IN EX_POOL_PRIORITY Priority)
 
PVOID NTAPI ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
 

Variables

ULONG ExpNumberOfPagedPools
 
POOL_DESCRIPTOR NonPagedPoolDescriptor
 
PPOOL_DESCRIPTOR ExpPagedPoolDescriptor [16+1]
 
PPOOL_DESCRIPTOR PoolVector [2]
 
PKGUARDED_MUTEX ExpPagedPoolMutex
 
SIZE_T PoolTrackTableSize
 
SIZE_T PoolTrackTableMask
 
SIZE_T PoolBigPageTableSize
 
SIZE_T PoolBigPageTableHash
 
PPOOL_TRACKER_TABLE PoolTrackTable
 
PPOOL_TRACKER_BIG_PAGES PoolBigPageTable
 
KSPIN_LOCK ExpTaggedPoolLock
 
ULONG PoolHitTag
 
BOOLEAN ExStopBadTags
 
KSPIN_LOCK ExpLargePoolTableLock
 
ULONG ExpPoolBigEntriesInUse
 
ULONG ExpPoolFlags
 
ULONG ExPoolFailures
 

Macro Definition Documentation

#define MODULE_INVOLVED_IN_ARM3

Definition at line 15 of file expool.c.

#define NDEBUG

Definition at line 12 of file expool.c.

#define POOL_BIG_TABLE_ENTRY_FREE   0x1

Definition at line 23 of file expool.c.

Referenced by ExpAddTagForBigPages(), and ExpFindAndRemoveTagBigPages().

#define POOL_BLOCK (   x,
  i 
)    (PPOOL_HEADER)((ULONG_PTR)(x) + ((i) * POOL_BLOCK_SIZE))

Definition at line 53 of file expool.c.

Referenced by ExAllocatePoolWithTag(), and ExFreePoolWithTag().

#define POOL_ENTRY (   x)    (PPOOL_HEADER)((ULONG_PTR)(x) - sizeof(POOL_HEADER))

Definition at line 51 of file expool.c.

Referenced by ExAllocatePoolWithQuotaTag(), and ExAllocatePoolWithTag().

#define POOL_FREE_BLOCK (   x)    (PLIST_ENTRY)((ULONG_PTR)(x) + sizeof(POOL_HEADER))

Definition at line 52 of file expool.c.

Referenced by ExAllocatePoolWithTag(), and ExFreePoolWithTag().

#define POOL_NEXT_BLOCK (   x)    POOL_BLOCK((x), (x)->BlockSize)
#define POOL_PREV_BLOCK (   x)    POOL_BLOCK((x), -((x)->PreviousSize))

Definition at line 55 of file expool.c.

Referenced by ExFreePoolWithTag(), and ExpCheckPoolHeader().

Typedef Documentation

Function Documentation

PVOID NTAPI ExAllocatePool ( POOL_TYPE  PoolType,
SIZE_T  NumberOfBytes 
)

Definition at line 2287 of file expool.c.

2289 {
2290  ULONG Tag = TAG_NONE;
2291 #if 0 && DBG
2292  PLDR_DATA_TABLE_ENTRY LdrEntry;
2293 
2294  /* Use the first four letters of the driver name, or "None" if unavailable */
2295  LdrEntry = KeGetCurrentIrql() <= APC_LEVEL
2297  : NULL;
2298  if (LdrEntry)
2299  {
2300  ULONG i;
2301  Tag = 0;
2302  for (i = 0; i < min(4, LdrEntry->BaseDllName.Length / sizeof(WCHAR)); i++)
2303  Tag = Tag >> 8 | (LdrEntry->BaseDllName.Buffer[i] & 0xff) << 24;
2304  for (; i < 4; i++)
2305  Tag = Tag >> 8 | ' ' << 24;
2306  }
2307 #endif
2309 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
PVOID NTAPI ExAllocatePoolWithTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:1732
__wchar_t WCHAR
Definition: xmlstorage.h:180
PLDR_DATA_TABLE_ENTRY NTAPI MiLookupDataTableEntry(IN PVOID Address)
Definition: sysldr.c:3365
#define TAG_NONE
Definition: tag.h:127
GLenum GLclampf GLint i
Definition: glfuncs.h:14
smooth NULL
Definition: ftsmooth.c:416
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
IN SIZE_T NumberOfBytes
Definition: ndis.h:3915
Definition: btrfs_drv.h:1762
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:143
#define min(a, b)
Definition: monoChain.cc:55
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
void * _ReturnAddress(void)
unsigned int ULONG
Definition: retypes.h:1
#define APC_LEVEL
Definition: env_spec_w32.h:695
PVOID NTAPI ExAllocatePoolWithQuota ( IN POOL_TYPE  PoolType,
IN SIZE_T  NumberOfBytes 
)

Definition at line 2765 of file expool.c.

2767 {
2768  //
2769  // Allocate the pool
2770  //
2772 }
PVOID NTAPI ExAllocatePoolWithQuotaTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:2803
#define TAG_NONE
Definition: tag.h:127
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
IN SIZE_T NumberOfBytes
Definition: ndis.h:3915
PVOID NTAPI ExAllocatePoolWithQuotaTag ( IN POOL_TYPE  PoolType,
IN SIZE_T  NumberOfBytes,
IN ULONG  Tag 
)

Definition at line 2803 of file expool.c.

Referenced by BuildAndSubmitIrp(), ExAllocatePoolWithQuota(), FsRtlAllocatePoolWithQuota(), FsRtlAllocatePoolWithQuotaTag(), IoAllocateIrp(), IopDeviceFsIoControl(), NpAddDataQueueEntry(), NpAddWaiter(), NpGetClientSecurityContext(), NpInitializeSecurity(), NpSetClientProcess(), NpTransceive(), NtGdiAddFontMemResourceEx(), NtQueueApcThread(), and TestPoolQuota().

2806 {
2807  BOOLEAN Raise = TRUE;
2808  PVOID Buffer;
2810  NTSTATUS Status;
2812 
2813  //
2814  // Check if we should fail instead of raising an exception
2815  //
2817  {
2818  Raise = FALSE;
2819  PoolType &= ~POOL_QUOTA_FAIL_INSTEAD_OF_RAISE;
2820  }
2821 
2822  //
2823  // Inject the pool quota mask
2824  //
2826 
2827  //
2828  // Check if we have enough space to add the quota owner process, as long as
2829  // this isn't the system process, which never gets charged quota
2830  //
2831  ASSERT(NumberOfBytes != 0);
2832  if ((NumberOfBytes <= (PAGE_SIZE - POOL_BLOCK_SIZE - sizeof(PVOID))) &&
2833  (Process != PsInitialSystemProcess))
2834  {
2835  //
2836  // Add space for our EPROCESS pointer
2837  //
2838  NumberOfBytes += sizeof(PEPROCESS);
2839  }
2840  else
2841  {
2842  //
2843  // We won't be able to store the pointer, so don't use quota for this
2844  //
2846  }
2847 
2848  //
2849  // Allocate the pool buffer now
2850  //
2852 
2853  //
2854  // If the buffer is page-aligned, this is a large page allocation and we
2855  // won't touch it
2856  //
2857  if (PAGE_ALIGN(Buffer) != Buffer)
2858  {
2859  //
2860  // Also if special pool is enabled, and this was allocated from there,
2861  // we won't touch it either
2862  //
2864  (MmIsSpecialPoolAddress(Buffer)))
2865  {
2866  return Buffer;
2867  }
2868 
2869  //
2870  // If it wasn't actually allocated with quota charges, ignore it too
2871  //
2872  if (!(PoolType & QUOTA_POOL_MASK)) return Buffer;
2873 
2874  //
2875  // If this is the system process, we don't charge quota, so ignore
2876  //
2877  if (Process == PsInitialSystemProcess) return Buffer;
2878 
2879  //
2880  // Actually go and charge quota for the process now
2881  //
2882  Entry = POOL_ENTRY(Buffer);
2883  Status = PsChargeProcessPoolQuota(Process,
2885  Entry->BlockSize * POOL_BLOCK_SIZE);
2886  if (!NT_SUCCESS(Status))
2887  {
2888  //
2889  // Quota failed, back out the allocation, clear the owner, and fail
2890  //
2891  ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1] = NULL;
2892  ExFreePoolWithTag(Buffer, Tag);
2893  if (Raise) RtlRaiseStatus(Status);
2894  return NULL;
2895  }
2896 
2897  //
2898  // Quota worked, write the owner and then reference it before returning
2899  //
2900  ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1] = Process;
2901  ObReferenceObject(Process);
2902  }
2903  else if (!(Buffer) && (Raise))
2904  {
2905  //
2906  // The allocation failed, raise an error if we are in raise mode
2907  //
2909  }
2910 
2911  //
2912  // Return the allocated buffer
2913  //
2914  return Buffer;
2915 }
DWORD *typedef PVOID
Definition: winlogon.h:52
PVOID NTAPI ExAllocatePoolWithTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:1732
DECLSPEC_NORETURN NTSYSAPI VOID NTAPI RtlRaiseStatus(_In_ NTSTATUS Status)
#define TRUE
Definition: types.h:120
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS NTAPI PsChargeProcessPoolQuota(IN PEPROCESS Process, IN POOL_TYPE PoolType, IN SIZE_T Amount)
Definition: quota.c:220
struct _Entry Entry
Definition: kefuncs.h:640
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define POOL_FLAG_SPECIAL_POOL
Definition: miarm.h:262
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
#define FALSE
Definition: types.h:117
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
#define POOL_NEXT_BLOCK(x)
Definition: expool.c:54
#define PsGetCurrentProcess
Definition: psfuncs.h:17
smooth NULL
Definition: ftsmooth.c:416
#define POOL_ENTRY(x)
Definition: expool.c:51
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define PAGE_ALIGN(Va)
UINTN VOID * Buffer
Definition: acefiex.h:370
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
IN SIZE_T NumberOfBytes
Definition: ndis.h:3915
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Status
Definition: gdiplustypes.h:24
#define QUOTA_POOL_MASK
Definition: ExPools.c:16
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define ObReferenceObject
Definition: obfuncs.h:204
ULONG ExpPoolFlags
Definition: expool.c:47
#define POOL_QUOTA_FAIL_INSTEAD_OF_RAISE
#define POOL_BLOCK_SIZE
Definition: miarm.h:248
VOID NTAPI ExFreePoolWithTag(IN PVOID P, IN ULONG TagToFree)
Definition: expool.c:2316
BOOLEAN NTAPI MmIsSpecialPoolAddress(IN PVOID P)
PVOID NTAPI ExAllocatePoolWithTag ( IN POOL_TYPE  PoolType,
IN SIZE_T  NumberOfBytes,
IN ULONG  Tag 
)

Definition at line 1732 of file expool.c.

Referenced by ExAllocatePool(), ExAllocatePoolWithQuotaTag(), ExAllocatePoolWithTagPriority(), ExGetPoolTagInfo(), and InitializePool().

1735 {
1736  PPOOL_DESCRIPTOR PoolDesc;
1737  PLIST_ENTRY ListHead;
1738  PPOOL_HEADER Entry, NextEntry, FragmentEntry;
1739  KIRQL OldIrql;
1740  USHORT BlockSize, i;
1741  ULONG OriginalType;
1742  PKPRCB Prcb = KeGetCurrentPrcb();
1744 
1745  //
1746  // Some sanity checks
1747  //
1748  ASSERT(Tag != 0);
1749  ASSERT(Tag != ' GIB');
1750  ASSERT(NumberOfBytes != 0);
1752 
1753  //
1754  // Not supported in ReactOS
1755  //
1757 
1758  //
1759  // Check if verifier or special pool is enabled
1760  //
1762  {
1763  //
1764  // For verifier, we should call the verification routine
1765  //
1767  {
1768  DPRINT1("Driver Verifier is not yet supported\n");
1769  }
1770 
1771  //
1772  // For special pool, we check if this is a suitable allocation and do
1773  // the special allocation if needed
1774  //
1776  {
1777  //
1778  // Check if this is a special pool allocation
1779  //
1781  {
1782  //
1783  // Try to allocate using special pool
1784  //
1786  if (Entry) return Entry;
1787  }
1788  }
1789  }
1790 
1791  //
1792  // Get the pool type and its corresponding vector for this request
1793  //
1794  OriginalType = PoolType;
1796  PoolDesc = PoolVector[PoolType];
1797  ASSERT(PoolDesc != NULL);
1798 
1799  //
1800  // Check if this is a big page allocation
1801  //
1803  {
1804  //
1805  // Allocate pages for it
1806  //
1807  Entry = MiAllocatePoolPages(OriginalType, NumberOfBytes);
1808  if (!Entry)
1809  {
1810 #if DBG
1811  //
1812  // Out of memory, display current consumption
1813  // Let's consider that if the caller wanted more
1814  // than a hundred pages, that's a bogus caller
1815  // and we are not out of memory
1816  //
1817  if (NumberOfBytes < 100 * PAGE_SIZE)
1818  {
1819  MiDumpPoolConsumers(FALSE, 0, 0, 0);
1820  }
1821 #endif
1822 
1823  //
1824  // Must succeed pool is deprecated, but still supported. These allocation
1825  // failures must cause an immediate bugcheck
1826  //
1827  if (OriginalType & MUST_SUCCEED_POOL_MASK)
1828  {
1829  KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
1830  NumberOfBytes,
1833  0);
1834  }
1835 
1836  //
1837  // Internal debugging
1838  //
1839  ExPoolFailures++;
1840 
1841  //
1842  // This flag requests printing failures, and can also further specify
1843  // breaking on failures
1844  //
1846  {
1847  DPRINT1("EX: ExAllocatePool (%lu, 0x%x) returning NULL\n",
1848  NumberOfBytes,
1849  OriginalType);
1851  }
1852 
1853  //
1854  // Finally, this flag requests an exception, which we are more than
1855  // happy to raise!
1856  //
1857  if (OriginalType & POOL_RAISE_IF_ALLOCATION_FAILURE)
1858  {
1860  }
1861 
1862  return NULL;
1863  }
1864 
1865  //
1866  // Increment required counters
1867  //
1872 
1873  //
1874  // Add a tag for the big page allocation and switch to the generic "BIG"
1875  // tag if we failed to do so, then insert a tracker for this alloation.
1876  //
1877  if (!ExpAddTagForBigPages(Entry,
1878  Tag,
1880  OriginalType))
1881  {
1882  Tag = ' GIB';
1883  }
1885  return Entry;
1886  }
1887 
1888  //
1889  // Should never request 0 bytes from the pool, but since so many drivers do
1890  // it, we'll just assume they want 1 byte, based on NT's similar behavior
1891  //
1892  if (!NumberOfBytes) NumberOfBytes = 1;
1893 
1894  //
1895  // A pool allocation is defined by its data, a linked list to connect it to
1896  // the free list (if necessary), and a pool header to store accounting info.
1897  // Calculate this size, then convert it into a block size (units of pool
1898  // headers)
1899  //
1900  // Note that i cannot overflow (past POOL_LISTS_PER_PAGE) because any such
1901  // request would've been treated as a POOL_MAX_ALLOC earlier and resulted in
1902  // the direct allocation of pages.
1903  //
1904  i = (USHORT)((NumberOfBytes + sizeof(POOL_HEADER) + (POOL_BLOCK_SIZE - 1))
1905  / POOL_BLOCK_SIZE);
1907 
1908  //
1909  // Handle lookaside list optimization for both paged and nonpaged pool
1910  //
1911  if (i <= NUMBER_POOL_LOOKASIDE_LISTS)
1912  {
1913  //
1914  // Try popping it from the per-CPU lookaside list
1915  //
1916  LookasideList = (PoolType == PagedPool) ?
1917  Prcb->PPPagedLookasideList[i - 1].P :
1918  Prcb->PPNPagedLookasideList[i - 1].P;
1919  LookasideList->TotalAllocates++;
1920  Entry = (PPOOL_HEADER)InterlockedPopEntrySList(&LookasideList->ListHead);
1921  if (!Entry)
1922  {
1923  //
1924  // We failed, try popping it from the global list
1925  //
1926  LookasideList = (PoolType == PagedPool) ?
1927  Prcb->PPPagedLookasideList[i - 1].L :
1928  Prcb->PPNPagedLookasideList[i - 1].L;
1929  LookasideList->TotalAllocates++;
1930  Entry = (PPOOL_HEADER)InterlockedPopEntrySList(&LookasideList->ListHead);
1931  }
1932 
1933  //
1934  // If we were able to pop it, update the accounting and return the block
1935  //
1936  if (Entry)
1937  {
1938  LookasideList->AllocateHits++;
1939 
1940  //
1941  // Get the real entry, write down its pool type, and track it
1942  //
1943  Entry--;
1944  Entry->PoolType = OriginalType + 1;
1946  Entry->BlockSize * POOL_BLOCK_SIZE,
1947  OriginalType);
1948 
1949  //
1950  // Return the pool allocation
1951  //
1952  Entry->PoolTag = Tag;
1953  (POOL_FREE_BLOCK(Entry))->Flink = NULL;
1954  (POOL_FREE_BLOCK(Entry))->Blink = NULL;
1955  return POOL_FREE_BLOCK(Entry);
1956  }
1957  }
1958 
1959  //
1960  // Loop in the free lists looking for a block if this size. Start with the
1961  // list optimized for this kind of size lookup
1962  //
1963  ListHead = &PoolDesc->ListHeads[i];
1964  do
1965  {
1966  //
1967  // Are there any free entries available on this list?
1968  //
1969  if (!ExpIsPoolListEmpty(ListHead))
1970  {
1971  //
1972  // Acquire the pool lock now
1973  //
1974  OldIrql = ExLockPool(PoolDesc);
1975 
1976  //
1977  // And make sure the list still has entries
1978  //
1979  if (ExpIsPoolListEmpty(ListHead))
1980  {
1981  //
1982  // Someone raced us (and won) before we had a chance to acquire
1983  // the lock.
1984  //
1985  // Try again!
1986  //
1987  ExUnlockPool(PoolDesc, OldIrql);
1988  continue;
1989  }
1990 
1991  //
1992  // Remove a free entry from the list
1993  // Note that due to the way we insert free blocks into multiple lists
1994  // there is a guarantee that any block on this list will either be
1995  // of the correct size, or perhaps larger.
1996  //
1997  ExpCheckPoolLinks(ListHead);
1998  Entry = POOL_ENTRY(ExpRemovePoolHeadList(ListHead));
1999  ExpCheckPoolLinks(ListHead);
2000  ExpCheckPoolBlocks(Entry);
2001  ASSERT(Entry->BlockSize >= i);
2002  ASSERT(Entry->PoolType == 0);
2003 
2004  //
2005  // Check if this block is larger that what we need. The block could
2006  // not possibly be smaller, due to the reason explained above (and
2007  // we would've asserted on a checked build if this was the case).
2008  //
2009  if (Entry->BlockSize != i)
2010  {
2011  //
2012  // Is there an entry before this one?
2013  //
2014  if (Entry->PreviousSize == 0)
2015  {
2016  //
2017  // There isn't anyone before us, so take the next block and
2018  // turn it into a fragment that contains the leftover data
2019  // that we don't need to satisfy the caller's request
2020  //
2021  FragmentEntry = POOL_BLOCK(Entry, i);
2022  FragmentEntry->BlockSize = Entry->BlockSize - i;
2023 
2024  //
2025  // And make it point back to us
2026  //
2027  FragmentEntry->PreviousSize = i;
2028 
2029  //
2030  // Now get the block that follows the new fragment and check
2031  // if it's still on the same page as us (and not at the end)
2032  //
2033  NextEntry = POOL_NEXT_BLOCK(FragmentEntry);
2034  if (PAGE_ALIGN(NextEntry) != NextEntry)
2035  {
2036  //
2037  // Adjust this next block to point to our newly created
2038  // fragment block
2039  //
2040  NextEntry->PreviousSize = FragmentEntry->BlockSize;
2041  }
2042  }
2043  else
2044  {
2045  //
2046  // There is a free entry before us, which we know is smaller
2047  // so we'll make this entry the fragment instead
2048  //
2049  FragmentEntry = Entry;
2050 
2051  //
2052  // And then we'll remove from it the actual size required.
2053  // Now the entry is a leftover free fragment
2054  //
2055  Entry->BlockSize -= i;
2056 
2057  //
2058  // Now let's go to the next entry after the fragment (which
2059  // used to point to our original free entry) and make it
2060  // reference the new fragment entry instead.
2061  //
2062  // This is the entry that will actually end up holding the
2063  // allocation!
2064  //
2065  Entry = POOL_NEXT_BLOCK(Entry);
2066  Entry->PreviousSize = FragmentEntry->BlockSize;
2067 
2068  //
2069  // And now let's go to the entry after that one and check if
2070  // it's still on the same page, and not at the end
2071  //
2072  NextEntry = POOL_BLOCK(Entry, i);
2073  if (PAGE_ALIGN(NextEntry) != NextEntry)
2074  {
2075  //
2076  // Make it reference the allocation entry
2077  //
2078  NextEntry->PreviousSize = i;
2079  }
2080  }
2081 
2082  //
2083  // Now our (allocation) entry is the right size
2084  //
2085  Entry->BlockSize = i;
2086 
2087  //
2088  // And the next entry is now the free fragment which contains
2089  // the remaining difference between how big the original entry
2090  // was, and the actual size the caller needs/requested.
2091  //
2092  FragmentEntry->PoolType = 0;
2093  BlockSize = FragmentEntry->BlockSize;
2094 
2095  //
2096  // Now check if enough free bytes remained for us to have a
2097  // "full" entry, which contains enough bytes for a linked list
2098  // and thus can be used for allocations (up to 8 bytes...)
2099  //
2100  ExpCheckPoolLinks(&PoolDesc->ListHeads[BlockSize - 1]);
2101  if (BlockSize != 1)
2102  {
2103  //
2104  // Insert the free entry into the free list for this size
2105  //
2106  ExpInsertPoolTailList(&PoolDesc->ListHeads[BlockSize - 1],
2107  POOL_FREE_BLOCK(FragmentEntry));
2108  ExpCheckPoolLinks(POOL_FREE_BLOCK(FragmentEntry));
2109  }
2110  }
2111 
2112  //
2113  // We have found an entry for this allocation, so set the pool type
2114  // and release the lock since we're done
2115  //
2116  Entry->PoolType = OriginalType + 1;
2117  ExpCheckPoolBlocks(Entry);
2118  ExUnlockPool(PoolDesc, OldIrql);
2119 
2120  //
2121  // Increment required counters
2122  //
2125 
2126  //
2127  // Track this allocation
2128  //
2130  Entry->BlockSize * POOL_BLOCK_SIZE,
2131  OriginalType);
2132 
2133  //
2134  // Return the pool allocation
2135  //
2136  Entry->PoolTag = Tag;
2137  (POOL_FREE_BLOCK(Entry))->Flink = NULL;
2138  (POOL_FREE_BLOCK(Entry))->Blink = NULL;
2139  return POOL_FREE_BLOCK(Entry);
2140  }
2141  } while (++ListHead != &PoolDesc->ListHeads[POOL_LISTS_PER_PAGE]);
2142 
2143  //
2144  // There were no free entries left, so we have to allocate a new fresh page
2145  //
2146  Entry = MiAllocatePoolPages(OriginalType, PAGE_SIZE);
2147  if (!Entry)
2148  {
2149 #if DBG
2150  //
2151  // Out of memory, display current consumption
2152  // Let's consider that if the caller wanted more
2153  // than a hundred pages, that's a bogus caller
2154  // and we are not out of memory
2155  //
2156  if (NumberOfBytes < 100 * PAGE_SIZE)
2157  {
2158  MiDumpPoolConsumers(FALSE, 0, 0, 0);
2159  }
2160 #endif
2161 
2162  //
2163  // Must succeed pool is deprecated, but still supported. These allocation
2164  // failures must cause an immediate bugcheck
2165  //
2166  if (OriginalType & MUST_SUCCEED_POOL_MASK)
2167  {
2168  KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
2169  PAGE_SIZE,
2172  0);
2173  }
2174 
2175  //
2176  // Internal debugging
2177  //
2178  ExPoolFailures++;
2179 
2180  //
2181  // This flag requests printing failures, and can also further specify
2182  // breaking on failures
2183  //
2184  if (ExpPoolFlags & POOL_FLAG_DBGPRINT_ON_FAILURE)
2185  {
2186  DPRINT1("EX: ExAllocatePool (%lu, 0x%x) returning NULL\n",
2187  NumberOfBytes,
2188  OriginalType);
2190  }
2191 
2192  //
2193  // Finally, this flag requests an exception, which we are more than
2194  // happy to raise!
2195  //
2196  if (OriginalType & POOL_RAISE_IF_ALLOCATION_FAILURE)
2197  {
2199  }
2200 
2201  //
2202  // Return NULL to the caller in all other cases
2203  //
2204  return NULL;
2205  }
2206 
2207  //
2208  // Setup the entry data
2209  //
2210  Entry->Ulong1 = 0;
2211  Entry->BlockSize = i;
2212  Entry->PoolType = OriginalType + 1;
2213 
2214  //
2215  // This page will have two entries -- one for the allocation (which we just
2216  // created above), and one for the remaining free bytes, which we're about
2217  // to create now. The free bytes are the whole page minus what was allocated
2218  // and then converted into units of block headers.
2219  //
2220  BlockSize = (PAGE_SIZE / POOL_BLOCK_SIZE) - i;
2221  FragmentEntry = POOL_BLOCK(Entry, i);
2222  FragmentEntry->Ulong1 = 0;
2223  FragmentEntry->BlockSize = BlockSize;
2224  FragmentEntry->PreviousSize = i;
2225 
2226  //
2227  // Increment required counters
2228  //
2229  InterlockedIncrement((PLONG)&PoolDesc->TotalPages);
2231 
2232  //
2233  // Now check if enough free bytes remained for us to have a "full" entry,
2234  // which contains enough bytes for a linked list and thus can be used for
2235  // allocations (up to 8 bytes...)
2236  //
2237  if (FragmentEntry->BlockSize != 1)
2238  {
2239  //
2240  // Excellent -- acquire the pool lock
2241  //
2242  OldIrql = ExLockPool(PoolDesc);
2243 
2244  //
2245  // And insert the free entry into the free list for this block size
2246  //
2247  ExpCheckPoolLinks(&PoolDesc->ListHeads[BlockSize - 1]);
2248  ExpInsertPoolTailList(&PoolDesc->ListHeads[BlockSize - 1],
2249  POOL_FREE_BLOCK(FragmentEntry));
2250  ExpCheckPoolLinks(POOL_FREE_BLOCK(FragmentEntry));
2251 
2252  //
2253  // Release the pool lock
2254  //
2255  ExpCheckPoolBlocks(Entry);
2256  ExUnlockPool(PoolDesc, OldIrql);
2257  }
2258  else
2259  {
2260  //
2261  // Simply do a sanity check
2262  //
2263  ExpCheckPoolBlocks(Entry);
2264  }
2265 
2266  //
2267  // Increment performance counters and track this allocation
2268  //
2271  Entry->BlockSize * POOL_BLOCK_SIZE,
2272  OriginalType);
2273 
2274  //
2275  // And return the pool allocation
2276  //
2277  ExpCheckPoolBlocks(Entry);
2278  Entry->PoolTag = Tag;
2279  return POOL_FREE_BLOCK(Entry);
2280 }
GENERAL_LOOKASIDE_POOL PPNPagedLookasideList[NUMBER_POOL_LOOKASIDE_LISTS]
Definition: ketypes.h:625
VOID NTAPI ExpCheckPoolLinks(IN PLIST_ENTRY ListHead)
Definition: expool.c:89
PLIST_ENTRY NTAPI ExpRemovePoolHeadList(IN PLIST_ENTRY ListHead)
Definition: expool.c:129
BOOLEAN NTAPI ExpIsPoolListEmpty(IN PLIST_ENTRY ListHead)
Definition: expool.c:111
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define SESSION_POOL_MASK
Definition: mm.h:102
#define POOL_FLAG_VERIFIER
Definition: miarm.h:260
struct _Entry Entry
Definition: kefuncs.h:640
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define POOL_FLAG_SPECIAL_POOL
Definition: miarm.h:262
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
#define POOL_FLAG_CRASH_ON_FAILURE
Definition: miarm.h:264
#define ExRaiseStatus
Definition: ntoskrnl.h:94
SIZE_T TotalBytes
Definition: miarm.h:300
void DbgBreakPoint()
Definition: mach.c:558
LIST_ENTRY ListHeads[POOL_LISTS_PER_PAGE]
Definition: miarm.h:302
PVOID NTAPI MmAllocateSpecialPool(IN SIZE_T NumberOfBytes, IN ULONG Tag, IN POOL_TYPE PoolType, IN ULONG SpecialType)
PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER ListHead)
Definition: interlocked.c:55
BOOLEAN NTAPI ExpAddTagForBigPages(IN PVOID Va, IN ULONG Key, IN ULONG NumberOfPages, IN POOL_TYPE PoolType)
Definition: expool.c:1453
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define POOL_FREE_BLOCK(x)
Definition: expool.c:52
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define FALSE
Definition: types.h:117
PPOOL_DESCRIPTOR PoolVector[2]
Definition: expool.c:36
long LONG
Definition: pedump.c:60
#define POOL_NEXT_BLOCK(x)
Definition: expool.c:54
struct LOOKASIDE_ALIGN _GENERAL_LOOKASIDE * PGENERAL_LOOKASIDE
#define POOL_BLOCK(x, i)
Definition: expool.c:53
smooth NULL
Definition: ftsmooth.c:416
#define POOL_ENTRY(x)
Definition: expool.c:51
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
#define InterlockedExchangeAdd
Definition: interlocked.h:181
VOID NTAPI ExpCheckPoolBlocks(IN PVOID Block)
Definition: expool.c:366
ULONG RunningAllocs
Definition: miarm.h:292
POOL_DESCRIPTOR NonPagedPoolDescriptor
Definition: expool.c:34
#define PAGE_ALIGN(Va)
#define MUST_SUCCEED_POOL_MASK
Definition: mm.h:99
ULONG TotalPages
Definition: miarm.h:294
PVOID NTAPI MiAllocatePoolPages(IN POOL_TYPE PoolType, IN SIZE_T SizeInBytes)
Definition: pool.c:420
#define BYTES_TO_PAGES(Size)
VOID NTAPI ExpInsertPoolTailList(IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry)
Definition: expool.c:153
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
FORCEINLINE KIRQL ExLockPool(IN PPOOL_DESCRIPTOR Descriptor)
Definition: expool.c:1265
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
IN SIZE_T NumberOfBytes
Definition: ndis.h:3915
FORCEINLINE VOID ExpCheckPoolIrqlLevel(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN PVOID Entry)
Definition: expool.c:406
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:117
ULONG TotalBigPages
Definition: miarm.h:295
#define InterlockedIncrement
Definition: armddk.h:53
USHORT PreviousSize
#define NUMBER_POOL_LOOKASIDE_LISTS
Definition: ketypes.h:286
#define ROUND_TO_PAGES(Size)
unsigned short USHORT
Definition: pedump.c:61
ULONG ExPoolFailures
Definition: expool.c:48
VOID NTAPI ExpInsertPoolTracker(IN ULONG Key, IN SIZE_T NumberOfBytes, IN POOL_TYPE PoolType)
Definition: expool.c:845
#define POOL_FLAG_DBGPRINT_ON_FAILURE
Definition: miarm.h:263
#define DPRINT1
Definition: precomp.h:8
#define POOL_LISTS_PER_PAGE
Definition: miarm.h:250
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
FORCEINLINE VOID ExUnlockPool(IN PPOOL_DESCRIPTOR Descriptor, IN KIRQL OldIrql)
Definition: expool.c:1289
ULONG ExpPoolFlags
Definition: expool.c:47
unsigned int ULONG
Definition: retypes.h:1
BOOLEAN NTAPI MmUseSpecialPool(IN SIZE_T NumberOfBytes, IN ULONG Tag)
#define POOL_MAX_ALLOC
Definition: miarm.h:252
#define POOL_RAISE_IF_ALLOCATION_FAILURE
#define POOL_BLOCK_SIZE
Definition: miarm.h:248
signed int * PLONG
Definition: retypes.h:5
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:94
_Must_inspect_result_ _In_ LPCGUID _In_ ULONG _In_ FSRTL_ALLOCATE_ECP_FLAGS _In_opt_ PFSRTL_EXTRA_CREATE_PARAMETER_CLEANUP_CALLBACK _Inout_ PVOID LookasideList
Definition: fltkernel.h:2551
GENERAL_LOOKASIDE_POOL PPPagedLookasideList[NUMBER_POOL_LOOKASIDE_LISTS]
Definition: ketypes.h:626
PVOID NTAPI ExAllocatePoolWithTagPriority ( IN POOL_TYPE  PoolType,
IN SIZE_T  NumberOfBytes,
IN ULONG  Tag,
IN EX_POOL_PRIORITY  Priority 
)

Definition at line 2779 of file expool.c.

Referenced by _RxAllocatePoolWithTag(), InitializeMemoryManagement(), and MyAllocatePool().

2783 {
2784  PVOID Buffer;
2785 
2786  //
2787  // Allocate the pool
2788  //
2790  if (Buffer == NULL)
2791  {
2792  UNIMPLEMENTED;
2793  }
2794 
2795  return Buffer;
2796 }
DWORD *typedef PVOID
Definition: winlogon.h:52
PVOID NTAPI ExAllocatePoolWithTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:1732
smooth NULL
Definition: ftsmooth.c:416
UINTN VOID * Buffer
Definition: acefiex.h:370
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
IN SIZE_T NumberOfBytes
Definition: ndis.h:3915
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
#define UNIMPLEMENTED
Definition: debug.h:114
VOID NTAPI ExFreePool ( PVOID  P)

Definition at line 2736 of file expool.c.

2737 {
2738  //
2739  // Just free without checking for the tag
2740  //
2741  ExFreePoolWithTag(P, 0);
2742 }
VOID NTAPI ExFreePoolWithTag(IN PVOID P, IN ULONG TagToFree)
Definition: expool.c:2316
#define P(row, col)
Definition: m_matrix.c:147
VOID NTAPI ExFreePoolWithTag ( IN PVOID  P,
IN ULONG  TagToFree 
)

Definition at line 2316 of file expool.c.

Referenced by ExAllocatePoolWithQuotaTag(), ExFreePool(), and ExGetPoolTagInfo().

2318 {
2319  PPOOL_HEADER Entry, NextEntry;
2320  USHORT BlockSize;
2321  KIRQL OldIrql;
2323  PPOOL_DESCRIPTOR PoolDesc;
2324  ULONG Tag;
2325  BOOLEAN Combined = FALSE;
2326  PFN_NUMBER PageCount, RealPageCount;
2327  PKPRCB Prcb = KeGetCurrentPrcb();
2330 
2331  //
2332  // Check if any of the debug flags are enabled
2333  //
2340  {
2341  //
2342  // Check if special pool is enabled
2343  //
2345  {
2346  //
2347  // Check if it was allocated from a special pool
2348  //
2350  {
2351  //
2352  // Was deadlock verification also enabled? We can do some extra
2353  // checks at this point
2354  //
2356  {
2357  DPRINT1("Verifier not yet supported\n");
2358  }
2359 
2360  //
2361  // It is, so handle it via special pool free routine
2362  //
2364  return;
2365  }
2366  }
2367 
2368  //
2369  // For non-big page allocations, we'll do a bunch of checks in here
2370  //
2371  if (PAGE_ALIGN(P) != P)
2372  {
2373  //
2374  // Get the entry for this pool allocation
2375  // The pointer math here may look wrong or confusing, but it is quite right
2376  //
2377  Entry = P;
2378  Entry--;
2379 
2380  //
2381  // Get the pool type
2382  //
2383  PoolType = (Entry->PoolType - 1) & BASE_POOL_TYPE_MASK;
2384 
2385  //
2386  // FIXME: Many other debugging checks go here
2387  //
2388  ExpCheckPoolIrqlLevel(PoolType, 0, P);
2389  }
2390  }
2391 
2392  //
2393  // Check if this is a big page allocation
2394  //
2395  if (PAGE_ALIGN(P) == P)
2396  {
2397  //
2398  // We need to find the tag for it, so first we need to find out what
2399  // kind of allocation this was (paged or nonpaged), then we can go
2400  // ahead and try finding the tag for it. Remember to get rid of the
2401  // PROTECTED_POOL tag if it's found.
2402  //
2403  // Note that if at insertion time, we failed to add the tag for a big
2404  // pool allocation, we used a special tag called 'BIG' to identify the
2405  // allocation, and we may get this tag back. In this scenario, we must
2406  // manually get the size of the allocation by actually counting through
2407  // the PFN database.
2408  //
2409  PoolType = MmDeterminePoolType(P);
2410  ExpCheckPoolIrqlLevel(PoolType, 0, P);
2411  Tag = ExpFindAndRemoveTagBigPages(P, &PageCount, PoolType);
2412  if (!Tag)
2413  {
2414  DPRINT1("We do not know the size of this allocation. This is not yet supported\n");
2415  ASSERT(Tag == ' GIB');
2416  PageCount = 1; // We are going to lie! This might screw up accounting?
2417  }
2418  else if (Tag & PROTECTED_POOL)
2419  {
2420  Tag &= ~PROTECTED_POOL;
2421  }
2422 
2423  //
2424  // Check block tag
2425  //
2426  if (TagToFree && TagToFree != Tag)
2427  {
2428  DPRINT1("Freeing pool - invalid tag specified: %.4s != %.4s\n", (char*)&TagToFree, (char*)&Tag);
2429  KeBugCheckEx(BAD_POOL_CALLER, 0x0A, (ULONG_PTR)P, Tag, TagToFree);
2430  }
2431 
2432  //
2433  // We have our tag and our page count, so we can go ahead and remove this
2434  // tracker now
2435  //
2436  ExpRemovePoolTracker(Tag, PageCount << PAGE_SHIFT, PoolType);
2437 
2438  //
2439  // Check if any of the debug flags are enabled
2440  //
2445  {
2446  //
2447  // Was deadlock verification also enabled? We can do some extra
2448  // checks at this point
2449  //
2451  {
2452  DPRINT1("Verifier not yet supported\n");
2453  }
2454 
2455  //
2456  // FIXME: Many debugging checks go here
2457  //
2458  }
2459 
2460  //
2461  // Update counters
2462  //
2463  PoolDesc = PoolVector[PoolType];
2466  -(LONG_PTR)(PageCount << PAGE_SHIFT));
2467 
2468  //
2469  // Do the real free now and update the last counter with the big page count
2470  //
2471  RealPageCount = MiFreePoolPages(P);
2472  ASSERT(RealPageCount == PageCount);
2474  -(LONG)RealPageCount);
2475  return;
2476  }
2477 
2478  //
2479  // Get the entry for this pool allocation
2480  // The pointer math here may look wrong or confusing, but it is quite right
2481  //
2482  Entry = P;
2483  Entry--;
2484  ASSERT((ULONG_PTR)Entry % POOL_BLOCK_SIZE == 0);
2485 
2486  //
2487  // Get the size of the entry, and it's pool type, then load the descriptor
2488  // for this pool type
2489  //
2490  BlockSize = Entry->BlockSize;
2491  PoolType = (Entry->PoolType - 1) & BASE_POOL_TYPE_MASK;
2492  PoolDesc = PoolVector[PoolType];
2493 
2494  //
2495  // Make sure that the IRQL makes sense
2496  //
2497  ExpCheckPoolIrqlLevel(PoolType, 0, P);
2498 
2499  //
2500  // Get the pool tag and get rid of the PROTECTED_POOL flag
2501  //
2502  Tag = Entry->PoolTag;
2503  if (Tag & PROTECTED_POOL) Tag &= ~PROTECTED_POOL;
2504 
2505  //
2506  // Check block tag
2507  //
2508  if (TagToFree && TagToFree != Tag)
2509  {
2510  DPRINT1("Freeing pool - invalid tag specified: %.4s != %.4s\n", (char*)&TagToFree, (char*)&Tag);
2511  KeBugCheckEx(BAD_POOL_CALLER, 0x0A, (ULONG_PTR)P, Tag, TagToFree);
2512  }
2513 
2514  //
2515  // Track the removal of this allocation
2516  //
2518  BlockSize * POOL_BLOCK_SIZE,
2519  Entry->PoolType - 1);
2520 
2521  //
2522  // Release pool quota, if any
2523  //
2524  if ((Entry->PoolType - 1) & QUOTA_POOL_MASK)
2525  {
2526  Process = ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1];
2527  if (Process)
2528  {
2529  if (Process->Pcb.Header.Type != ProcessObject)
2530  {
2531  DPRINT1("Object %p is not a process. Type %u, pool type 0x%x, block size %u\n",
2532  Process, Process->Pcb.Header.Type, Entry->PoolType, BlockSize);
2533  KeBugCheckEx(BAD_POOL_CALLER,
2534  0x0D,
2535  (ULONG_PTR)P,
2536  Tag,
2537  (ULONG_PTR)Process);
2538  }
2539  PsReturnPoolQuota(Process, PoolType, BlockSize * POOL_BLOCK_SIZE);
2540  ObDereferenceObject(Process);
2541  }
2542  }
2543 
2544  //
2545  // Is this allocation small enough to have come from a lookaside list?
2546  //
2547  if (BlockSize <= NUMBER_POOL_LOOKASIDE_LISTS)
2548  {
2549  //
2550  // Try pushing it into the per-CPU lookaside list
2551  //
2552  LookasideList = (PoolType == PagedPool) ?
2553  Prcb->PPPagedLookasideList[BlockSize - 1].P :
2554  Prcb->PPNPagedLookasideList[BlockSize - 1].P;
2555  LookasideList->TotalFrees++;
2556  if (ExQueryDepthSList(&LookasideList->ListHead) < LookasideList->Depth)
2557  {
2558  LookasideList->FreeHits++;
2559  InterlockedPushEntrySList(&LookasideList->ListHead, P);
2560  return;
2561  }
2562 
2563  //
2564  // We failed, try to push it into the global lookaside list
2565  //
2566  LookasideList = (PoolType == PagedPool) ?
2567  Prcb->PPPagedLookasideList[BlockSize - 1].L :
2568  Prcb->PPNPagedLookasideList[BlockSize - 1].L;
2569  LookasideList->TotalFrees++;
2570  if (ExQueryDepthSList(&LookasideList->ListHead) < LookasideList->Depth)
2571  {
2572  LookasideList->FreeHits++;
2573  InterlockedPushEntrySList(&LookasideList->ListHead, P);
2574  return;
2575  }
2576  }
2577 
2578  //
2579  // Get the pointer to the next entry
2580  //
2581  NextEntry = POOL_BLOCK(Entry, BlockSize);
2582 
2583  //
2584  // Update performance counters
2585  //
2587  InterlockedExchangeAddSizeT(&PoolDesc->TotalBytes, -BlockSize * POOL_BLOCK_SIZE);
2588 
2589  //
2590  // Acquire the pool lock
2591  //
2592  OldIrql = ExLockPool(PoolDesc);
2593 
2594  //
2595  // Check if the next allocation is at the end of the page
2596  //
2597  ExpCheckPoolBlocks(Entry);
2598  if (PAGE_ALIGN(NextEntry) != NextEntry)
2599  {
2600  //
2601  // We may be able to combine the block if it's free
2602  //
2603  if (NextEntry->PoolType == 0)
2604  {
2605  //
2606  // The next block is free, so we'll do a combine
2607  //
2608  Combined = TRUE;
2609 
2610  //
2611  // Make sure there's actual data in the block -- anything smaller
2612  // than this means we only have the header, so there's no linked list
2613  // for us to remove
2614  //
2615  if ((NextEntry->BlockSize != 1))
2616  {
2617  //
2618  // The block is at least big enough to have a linked list, so go
2619  // ahead and remove it
2620  //
2621  ExpCheckPoolLinks(POOL_FREE_BLOCK(NextEntry));
2623  ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Flink));
2624  ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Blink));
2625  }
2626 
2627  //
2628  // Our entry is now combined with the next entry
2629  //
2630  Entry->BlockSize = Entry->BlockSize + NextEntry->BlockSize;
2631  }
2632  }
2633 
2634  //
2635  // Now check if there was a previous entry on the same page as us
2636  //
2637  if (Entry->PreviousSize)
2638  {
2639  //
2640  // Great, grab that entry and check if it's free
2641  //
2642  NextEntry = POOL_PREV_BLOCK(Entry);
2643  if (NextEntry->PoolType == 0)
2644  {
2645  //
2646  // It is, so we can do a combine
2647  //
2648  Combined = TRUE;
2649 
2650  //
2651  // Make sure there's actual data in the block -- anything smaller
2652  // than this means we only have the header so there's no linked list
2653  // for us to remove
2654  //
2655  if ((NextEntry->BlockSize != 1))
2656  {
2657  //
2658  // The block is at least big enough to have a linked list, so go
2659  // ahead and remove it
2660  //
2661  ExpCheckPoolLinks(POOL_FREE_BLOCK(NextEntry));
2663  ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Flink));
2664  ExpCheckPoolLinks(ExpDecodePoolLink((POOL_FREE_BLOCK(NextEntry))->Blink));
2665  }
2666 
2667  //
2668  // Combine our original block (which might've already been combined
2669  // with the next block), into the previous block
2670  //
2671  NextEntry->BlockSize = NextEntry->BlockSize + Entry->BlockSize;
2672 
2673  //
2674  // And now we'll work with the previous block instead
2675  //
2676  Entry = NextEntry;
2677  }
2678  }
2679 
2680  //
2681  // By now, it may have been possible for our combined blocks to actually
2682  // have made up a full page (if there were only 2-3 allocations on the
2683  // page, they could've all been combined).
2684  //
2685  if ((PAGE_ALIGN(Entry) == Entry) &&
2686  (PAGE_ALIGN(POOL_NEXT_BLOCK(Entry)) == POOL_NEXT_BLOCK(Entry)))
2687  {
2688  //
2689  // In this case, release the pool lock, update the performance counter,
2690  // and free the page
2691  //
2692  ExUnlockPool(PoolDesc, OldIrql);
2693  InterlockedExchangeAdd((PLONG)&PoolDesc->TotalPages, -1);
2694  MiFreePoolPages(Entry);
2695  return;
2696  }
2697 
2698  //
2699  // Otherwise, we now have a free block (or a combination of 2 or 3)
2700  //
2701  Entry->PoolType = 0;
2702  BlockSize = Entry->BlockSize;
2703  ASSERT(BlockSize != 1);
2704 
2705  //
2706  // Check if we actually did combine it with anyone
2707  //
2708  if (Combined)
2709  {
2710  //
2711  // Get the first combined block (either our original to begin with, or
2712  // the one after the original, depending if we combined with the previous)
2713  //
2714  NextEntry = POOL_NEXT_BLOCK(Entry);
2715 
2716  //
2717  // As long as the next block isn't on a page boundary, have it point
2718  // back to us
2719  //
2720  if (PAGE_ALIGN(NextEntry) != NextEntry) NextEntry->PreviousSize = BlockSize;
2721  }
2722 
2723  //
2724  // Insert this new free block, and release the pool lock
2725  //
2726  ExpInsertPoolHeadList(&PoolDesc->ListHeads[BlockSize - 1], POOL_FREE_BLOCK(Entry));
2728  ExUnlockPool(PoolDesc, OldIrql);
2729 }
DWORD *typedef PVOID
Definition: winlogon.h:52
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
GENERAL_LOOKASIDE_POOL PPNPagedLookasideList[NUMBER_POOL_LOOKASIDE_LISTS]
Definition: ketypes.h:625
#define TRUE
Definition: types.h:120
VOID NTAPI ExpCheckPoolLinks(IN PLIST_ENTRY ListHead)
Definition: expool.c:89
#define POOL_FLAG_VERIFIER
Definition: miarm.h:260
struct _Entry Entry
Definition: kefuncs.h:640
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define POOL_FLAG_SPECIAL_POOL
Definition: miarm.h:262
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
#define POOL_PREV_BLOCK(x)
Definition: expool.c:55
VOID NTAPI ExpRemovePoolEntryList(IN PLIST_ENTRY Entry)
Definition: expool.c:118
SIZE_T TotalBytes
Definition: miarm.h:300
VOID NTAPI ExpInsertPoolHeadList(IN PLIST_ENTRY ListHead, IN PLIST_ENTRY Entry)
Definition: expool.c:168
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
ULONG RunningDeAllocs
Definition: miarm.h:293
LIST_ENTRY ListHeads[POOL_LISTS_PER_PAGE]
Definition: miarm.h:302
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define POOL_FLAG_CHECK_TIMERS
Definition: miarm.h:257
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define POOL_FREE_BLOCK(x)
Definition: expool.c:52
ULONG PFN_NUMBER
Definition: ke.h:8
#define FALSE
Definition: types.h:117
PPOOL_DESCRIPTOR PoolVector[2]
Definition: expool.c:36
long LONG
Definition: pedump.c:60
#define POOL_NEXT_BLOCK(x)
Definition: expool.c:54
struct LOOKASIDE_ALIGN _GENERAL_LOOKASIDE * PGENERAL_LOOKASIDE
VOID NTAPI PsReturnPoolQuota(IN PEPROCESS Process, IN POOL_TYPE PoolType, IN SIZE_T Amount)
Definition: quota.c:237
#define POOL_BLOCK(x, i)
Definition: expool.c:53
ULONG NTAPI ExpFindAndRemoveTagBigPages(IN PVOID Va, OUT PULONG_PTR BigPages, IN POOL_TYPE PoolType)
Definition: expool.c:1542
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
#define InterlockedExchangeAdd
Definition: interlocked.h:181
VOID NTAPI ExpCheckPoolBlocks(IN PVOID Block)
Definition: expool.c:366
PLIST_ENTRY NTAPI ExpDecodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:75
unsigned char BOOLEAN
POOL_TYPE NTAPI MmDeterminePoolType(IN PVOID VirtualAddress)
Definition: pool.c:406
VOID NTAPI ExpRemovePoolTracker(IN ULONG Key, IN SIZE_T NumberOfBytes, IN POOL_TYPE PoolType)
Definition: expool.c:754
if(!(yy_init))
Definition: macro.lex.yy.c:717
INT POOL_TYPE
Definition: typedefs.h:76
#define PROTECTED_POOL
Definition: extypes.h:294
#define PAGE_ALIGN(Va)
FORCEINLINE USHORT ExQueryDepthSList(_In_ PSLIST_HEADER SListHead)
Definition: exfuncs.h:153
ULONG TotalPages
Definition: miarm.h:294
ULONG NTAPI MiFreePoolPages(IN PVOID StartingAddress)
Definition: pool.c:901
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
FORCEINLINE KIRQL ExLockPool(IN PPOOL_DESCRIPTOR Descriptor)
Definition: expool.c:1265
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
FORCEINLINE VOID ExpCheckPoolIrqlLevel(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN PVOID Entry)
Definition: expool.c:406
KPROCESS Pcb
Definition: pstypes.h:1194
NTKERNELAPI PSLIST_ENTRY FASTCALL InterlockedPushEntrySList(IN PSLIST_HEADER ListHead, IN PSLIST_ENTRY ListEntry)
Definition: interlocked.c:82
ULONG TotalBigPages
Definition: miarm.h:295
#define POOL_FLAG_CHECK_DEADLOCK
Definition: miarm.h:261
#define QUOTA_POOL_MASK
Definition: ExPools.c:16
#define InterlockedIncrement
Definition: armddk.h:53
USHORT PreviousSize
#define NUMBER_POOL_LOOKASIDE_LISTS
Definition: ketypes.h:286
unsigned short USHORT
Definition: pedump.c:61
#define POOL_FLAG_CHECK_WORKERS
Definition: miarm.h:258
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
#define DPRINT1
Definition: precomp.h:8
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
FORCEINLINE VOID ExUnlockPool(IN PPOOL_DESCRIPTOR Descriptor, IN KIRQL OldIrql)
Definition: expool.c:1289
ULONG ExpPoolFlags
Definition: expool.c:47
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI MmFreeSpecialPool(IN PVOID P)
#define POOL_BLOCK_SIZE
Definition: miarm.h:248
signed int * PLONG
Definition: retypes.h:5
BOOLEAN NTAPI MmIsSpecialPoolAddress(IN PVOID P)
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:94
DISPATCHER_HEADER Header
Definition: ketypes.h:1974
#define P(row, col)
Definition: m_matrix.c:147
_Must_inspect_result_ _In_ LPCGUID _In_ ULONG _In_ FSRTL_ALLOCATE_ECP_FLAGS _In_opt_ PFSRTL_EXTRA_CREATE_PARAMETER_CLEANUP_CALLBACK _Inout_ PVOID LookasideList
Definition: fltkernel.h:2551
#define POOL_FLAG_CHECK_RESOURCES
Definition: miarm.h:259
GENERAL_LOOKASIDE_POOL PPPagedLookasideList[NUMBER_POOL_LOOKASIDE_LISTS]
Definition: ketypes.h:626
NTSTATUS NTAPI ExGetPoolTagInfo ( IN PSYSTEM_POOLTAG_INFORMATION  SystemInformation,
IN ULONG  SystemInformationLength,
IN OUT PULONG ReturnLength  OPTIONAL 
)

Definition at line 1348 of file expool.c.

Referenced by QSI_DEF().

1351 {
1352  ULONG TableSize, CurrentLength;
1353  ULONG EntryCount;
1355  PSYSTEM_POOLTAG TagEntry;
1356  PPOOL_TRACKER_TABLE Buffer, TrackerEntry;
1359 
1360  //
1361  // Keep track of how much data the caller's buffer must hold
1362  //
1363  CurrentLength = FIELD_OFFSET(SYSTEM_POOLTAG_INFORMATION, TagInfo);
1364 
1365  //
1366  // Initialize the caller's buffer
1367  //
1368  TagEntry = &SystemInformation->TagInfo[0];
1369  SystemInformation->Count = 0;
1370 
1371  //
1372  // Capture the number of entries, and the total size needed to make a copy
1373  // of the table
1374  //
1375  EntryCount = (ULONG)PoolTrackTableSize;
1376  TableSize = EntryCount * sizeof(POOL_TRACKER_TABLE);
1377 
1378  //
1379  // Allocate the "Generic DPC" temporary buffer
1380  //
1381  Buffer = ExAllocatePoolWithTag(NonPagedPool, TableSize, 'ofnI');
1382  if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
1383 
1384  //
1385  // Do a "Generic DPC" to atomically retrieve the tag and allocation data
1386  //
1387  Context.PoolTrackTable = Buffer;
1389  Context.PoolTrackTableExpansion = NULL;
1390  Context.PoolTrackTableSizeExpansion = 0;
1392 
1393  //
1394  // Now parse the results
1395  //
1396  for (TrackerEntry = Buffer; TrackerEntry < (Buffer + EntryCount); TrackerEntry++)
1397  {
1398  //
1399  // If the entry is empty, skip it
1400  //
1401  if (!TrackerEntry->Key) continue;
1402 
1403  //
1404  // Otherwise, add one more entry to the caller's buffer, and ensure that
1405  // enough space has been allocated in it
1406  //
1407  SystemInformation->Count++;
1408  CurrentLength += sizeof(*TagEntry);
1409  if (SystemInformationLength < CurrentLength)
1410  {
1411  //
1412  // The caller's buffer is too small, so set a failure code. The
1413  // caller will know the count, as well as how much space is needed.
1414  //
1415  // We do NOT break out of the loop, because we want to keep incrementing
1416  // the Count as well as CurrentLength so that the caller can know the
1417  // final numbers
1418  //
1419  Status = STATUS_INFO_LENGTH_MISMATCH;
1420  }
1421  else
1422  {
1423  //
1424  // Small sanity check that our accounting is working correctly
1425  //
1426  ASSERT(TrackerEntry->PagedAllocs >= TrackerEntry->PagedFrees);
1427  ASSERT(TrackerEntry->NonPagedAllocs >= TrackerEntry->NonPagedFrees);
1428 
1429  //
1430  // Return the data into the caller's buffer
1431  //
1432  TagEntry->TagUlong = TrackerEntry->Key;
1433  TagEntry->PagedAllocs = TrackerEntry->PagedAllocs;
1434  TagEntry->PagedFrees = TrackerEntry->PagedFrees;
1435  TagEntry->PagedUsed = TrackerEntry->PagedBytes;
1436  TagEntry->NonPagedAllocs = TrackerEntry->NonPagedAllocs;
1437  TagEntry->NonPagedFrees = TrackerEntry->NonPagedFrees;
1438  TagEntry->NonPagedUsed = TrackerEntry->NonPagedBytes;
1439  TagEntry++;
1440  }
1441  }
1442 
1443  //
1444  // Free the "Generic DPC" temporary buffer, return the buffer length and status
1445  //
1446  ExFreePoolWithTag(Buffer, 'ofnI');
1447  if (ReturnLength) *ReturnLength = CurrentLength;
1448  return Status;
1449 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
PVOID NTAPI ExAllocatePoolWithTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:1732
IN CINT OUT PVOID IN ULONG OUT PULONG ReturnLength
Definition: dumpinfo.c:39
ULONG PagedAllocs
Definition: extypes.h:1129
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
SIZE_T PoolTrackTableSize
Definition: expool.c:28
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
return STATUS_SUCCESS
Definition: btrfs.c:2690
SIZE_T PoolTrackTableSize
Definition: expool.c:38
ULONG NonPagedFrees
Definition: extypes.h:1133
SIZE_T PoolTrackTableSizeExpansion
Definition: expool.c:30
PPOOL_TRACKER_TABLE PoolTrackTableExpansion
Definition: expool.c:29
smooth NULL
Definition: ftsmooth.c:416
SIZE_T NonPagedBytes
Definition: miarm.h:351
ULONG NonPagedAllocs
Definition: extypes.h:1132
struct _POOL_TRACKER_TABLE POOL_TRACKER_TABLE
SIZE_T NonPagedUsed
Definition: extypes.h:1134
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI ExpGetPoolTagInfoTarget(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
Definition: expool.c:1313
SIZE_T PagedUsed
Definition: extypes.h:1131
LONG NonPagedFrees
Definition: miarm.h:350
PPOOL_TRACKER_TABLE PoolTrackTable
Definition: expool.c:27
UINTN VOID * Buffer
Definition: acefiex.h:370
SIZE_T PagedBytes
Definition: miarm.h:354
ULONG PagedFrees
Definition: extypes.h:1130
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
Status
Definition: gdiplustypes.h:24
VOID NTAPI KeGenericCallDpc(IN PKDEFERRED_ROUTINE Routine, IN PVOID Context)
Definition: dpc.c:983
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
LONG NonPagedAllocs
Definition: miarm.h:349
_Must_inspect_result_ typedef _Out_ PULONG TableSize
Definition: iotypes.h:3938
struct tagContext Context
Definition: acpixf.h:1014
unsigned int ULONG
Definition: retypes.h:1
ULONG TagUlong
Definition: extypes.h:1127
VOID NTAPI ExFreePoolWithTag(IN PVOID P, IN ULONG TagToFree)
Definition: expool.c:2316
ACPI_EFI_GUID ACPI_EFI_OPEN_PROTOCOL_INFORMATION_ENTRY UINTN * EntryCount
Definition: acefiex.h:694
VOID NTAPI INIT_SECTION ExInitializePoolDescriptor ( IN PPOOL_DESCRIPTOR  PoolDescriptor,
IN POOL_TYPE  PoolType,
IN ULONG  PoolIndex,
IN ULONG  Threshold,
IN PVOID  PoolLock 
)

Definition at line 964 of file expool.c.

Referenced by InitializePool(), and MiInitializeSessionPool().

969 {
970  PLIST_ENTRY NextEntry, LastEntry;
971 
972  //
973  // Setup the descriptor based on the caller's request
974  //
975  PoolDescriptor->PoolType = PoolType;
976  PoolDescriptor->PoolIndex = PoolIndex;
977  PoolDescriptor->Threshold = Threshold;
978  PoolDescriptor->LockAddress = PoolLock;
979 
980  //
981  // Initialize accounting data
982  //
983  PoolDescriptor->RunningAllocs = 0;
984  PoolDescriptor->RunningDeAllocs = 0;
985  PoolDescriptor->TotalPages = 0;
986  PoolDescriptor->TotalBytes = 0;
987  PoolDescriptor->TotalBigPages = 0;
988 
989  //
990  // Nothing pending for now
991  //
992  PoolDescriptor->PendingFrees = NULL;
993  PoolDescriptor->PendingFreeDepth = 0;
994 
995  //
996  // Loop all the descriptor's allocation lists and initialize them
997  //
998  NextEntry = PoolDescriptor->ListHeads;
999  LastEntry = NextEntry + POOL_LISTS_PER_PAGE;
1000  while (NextEntry < LastEntry)
1001  {
1002  ExpInitializePoolListHead(NextEntry);
1003  NextEntry++;
1004  }
1005 
1006  //
1007  // Note that ReactOS does not support Session Pool Yet
1008  //
1010 }
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
VOID NTAPI ExpInitializePoolListHead(IN PLIST_ENTRY ListHead)
Definition: expool.c:104
smooth NULL
Definition: ftsmooth.c:416
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
Definition: typedefs.h:117
#define POOL_LISTS_PER_PAGE
Definition: miarm.h:250
FORCEINLINE KIRQL ExLockPool ( IN PPOOL_DESCRIPTOR  Descriptor)

Definition at line 1265 of file expool.c.

Referenced by ExAllocatePoolWithTag(), and ExFreePoolWithTag().

1266 {
1267  //
1268  // Check if this is nonpaged pool
1269  //
1270  if ((Descriptor->PoolType & BASE_POOL_TYPE_MASK) == NonPagedPool)
1271  {
1272  //
1273  // Use the queued spin lock
1274  //
1276  }
1277  else
1278  {
1279  //
1280  // Use the guarded mutex
1281  //
1282  KeAcquireGuardedMutex(Descriptor->LockAddress);
1283  return APC_LEVEL;
1284  }
1285 }
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define APC_LEVEL
Definition: env_spec_w32.h:695
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966
BOOLEAN NTAPI ExpAddTagForBigPages ( IN PVOID  Va,
IN ULONG  Key,
IN ULONG  NumberOfPages,
IN POOL_TYPE  PoolType 
)

Definition at line 1453 of file expool.c.

Referenced by ExAllocatePoolWithTag().

1457 {
1458  ULONG Hash, i = 0;
1459  PVOID OldVa;
1460  KIRQL OldIrql;
1461  SIZE_T TableSize;
1462  PPOOL_TRACKER_BIG_PAGES Entry, EntryEnd, EntryStart;
1465 
1466  //
1467  // As the table is expandable, these values must only be read after acquiring
1468  // the lock to avoid a teared access during an expansion
1469  //
1472  Hash &= PoolBigPageTableHash;
1473  TableSize = PoolBigPageTableSize;
1474 
1475  //
1476  // We loop from the current hash bucket to the end of the table, and then
1477  // rollover to hash bucket 0 and keep going from there. If we return back
1478  // to the beginning, then we attempt expansion at the bottom of the loop
1479  //
1480  EntryStart = Entry = &PoolBigPageTable[Hash];
1481  EntryEnd = &PoolBigPageTable[TableSize];
1482  do
1483  {
1484  //
1485  // Make sure that this is a free entry and attempt to atomically make the
1486  // entry busy now
1487  //
1488  OldVa = Entry->Va;
1489  if (((ULONG_PTR)OldVa & POOL_BIG_TABLE_ENTRY_FREE) &&
1490  (InterlockedCompareExchangePointer(&Entry->Va, Va, OldVa) == OldVa))
1491  {
1492  //
1493  // We now own this entry, write down the size and the pool tag
1494  //
1495  Entry->Key = Key;
1496  Entry->NumberOfPages = NumberOfPages;
1497 
1498  //
1499  // Add one more entry to the count, and see if we're getting within
1500  // 25% of the table size, at which point we'll do an expansion now
1501  // to avoid blocking too hard later on.
1502  //
1503  // Note that we only do this if it's also been the 16th time that we
1504  // keep losing the race or that we are not finding a free entry anymore,
1505  // which implies a massive number of concurrent big pool allocations.
1506  //
1508  if ((i >= 16) && (ExpPoolBigEntriesInUse > (TableSize / 4)))
1509  {
1510  DPRINT("Should attempt expansion since we now have %lu entries\n",
1512  }
1513 
1514  //
1515  // We have our entry, return
1516  //
1518  return TRUE;
1519  }
1520 
1521  //
1522  // We don't have our entry yet, so keep trying, making the entry list
1523  // circular if we reach the last entry. We'll eventually break out of
1524  // the loop once we've rolled over and returned back to our original
1525  // hash bucket
1526  //
1527  i++;
1528  if (++Entry >= EntryEnd) Entry = &PoolBigPageTable[0];
1529  } while (Entry != EntryStart);
1530 
1531  //
1532  // This means there's no free hash buckets whatsoever, so we would now have
1533  // to attempt expanding the table
1534  //
1535  DPRINT1("Big pool expansion needed, not implemented!\n");
1537  return FALSE;
1538 }
DWORD *typedef PVOID
Definition: winlogon.h:52
static int Hash(const char *)
Definition: reader.c:2258
#define TRUE
Definition: types.h:120
#define SESSION_POOL_MASK
Definition: mm.h:102
struct _Entry Entry
Definition: kefuncs.h:640
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
uint32_t ULONG_PTR
Definition: typedefs.h:63
KSPIN_LOCK ExpLargePoolTableLock
Definition: expool.c:45
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define FALSE
Definition: types.h:117
SIZE_T PoolBigPageTableSize
Definition: expool.c:39
#define InterlockedCompareExchangePointer
Definition: interlocked.h:129
void DPRINT(...)
Definition: polytest.cpp:61
ULONG ExpPoolBigEntriesInUse
Definition: expool.c:46
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define InterlockedIncrementUL(Addend)
Definition: ex.h:1469
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
FORCEINLINE ULONG ExpComputePartialHashForAddress(IN PVOID BaseAddress)
Definition: expool.c:447
#define DPRINT1
Definition: precomp.h:8
PPOOL_TRACKER_BIG_PAGES PoolBigPageTable
Definition: expool.c:41
SIZE_T PoolBigPageTableHash
Definition: expool.c:39
#define POOL_BIG_TABLE_ENTRY_FREE
Definition: expool.c:23
_Must_inspect_result_ typedef _Out_ PULONG TableSize
Definition: iotypes.h:3938
unsigned int ULONG
Definition: retypes.h:1
ACPI_EFI_INPUT_KEY * Key
Definition: acefiex.h:303
VOID NTAPI ExpCheckPoolAllocation ( PVOID  P,
POOL_TYPE  PoolType,
ULONG  Tag 
)

Definition at line 286 of file expool.c.

290 {
292  ULONG i;
293  KIRQL OldIrql;
294  POOL_TYPE RealPoolType;
295 
296  /* Get the pool header */
297  Entry = ((PPOOL_HEADER)P) - 1;
298 
299  /* Check if this is a large allocation */
300  if (PAGE_ALIGN(P) == P)
301  {
302  /* Lock the pool table */
304 
305  /* Find the pool tag */
306  for (i = 0; i < PoolBigPageTableSize; i++)
307  {
308  /* Check if this is our allocation */
309  if (PoolBigPageTable[i].Va == P)
310  {
311  /* Make sure the tag is ok */
312  if (PoolBigPageTable[i].Key != Tag)
313  {
314  KeBugCheckEx(BAD_POOL_CALLER, 0x0A, (ULONG_PTR)P, PoolBigPageTable[i].Key, Tag);
315  }
316 
317  break;
318  }
319  }
320 
321  /* Release the lock */
323 
324  if (i == PoolBigPageTableSize)
325  {
326  /* Did not find the allocation */
327  //ASSERT(FALSE);
328  }
329 
330  /* Get Pool type by address */
331  RealPoolType = MmDeterminePoolType(P);
332  }
333  else
334  {
335  /* Verify the tag */
336  if (Entry->PoolTag != Tag)
337  {
338  DPRINT1("Allocation has wrong pool tag! Expected '%.4s', got '%.4s' (0x%08lx)\n",
339  &Tag, &Entry->PoolTag, Entry->PoolTag);
340  KeBugCheckEx(BAD_POOL_CALLER, 0x0A, (ULONG_PTR)P, Entry->PoolTag, Tag);
341  }
342 
343  /* Check the rest of the header */
344  ExpCheckPoolHeader(Entry);
345 
346  /* Get Pool type from entry */
347  RealPoolType = (Entry->PoolType - 1);
348  }
349 
350  /* Should we check the pool type? */
351  if (PoolType != -1)
352  {
353  /* Verify the pool type */
354  if (RealPoolType != PoolType)
355  {
356  DPRINT1("Wrong pool type! Expected %s, got %s\n",
357  PoolType & BASE_POOL_TYPE_MASK ? "PagedPool" : "NonPagedPool",
358  (Entry->PoolType - 1) & BASE_POOL_TYPE_MASK ? "PagedPool" : "NonPagedPool");
359  KeBugCheckEx(BAD_POOL_CALLER, 0xCC, (ULONG_PTR)P, Entry->PoolTag, Tag);
360  }
361  }
362 }
struct _Entry Entry
Definition: kefuncs.h:640
uint32_t ULONG_PTR
Definition: typedefs.h:63
KSPIN_LOCK ExpLargePoolTableLock
Definition: expool.c:45
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLenum GLclampf GLint i
Definition: glfuncs.h:14
SIZE_T PoolBigPageTableSize
Definition: expool.c:39
VOID NTAPI ExpCheckPoolHeader(IN PPOOL_HEADER Entry)
Definition: expool.c:183
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
struct _POOL_HEADER * PPOOL_HEADER
POOL_TYPE NTAPI MmDeterminePoolType(IN PVOID VirtualAddress)
Definition: pool.c:406
INT POOL_TYPE
Definition: typedefs.h:76
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define PAGE_ALIGN(Va)
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define DPRINT1
Definition: precomp.h:8
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
PPOOL_TRACKER_BIG_PAGES PoolBigPageTable
Definition: expool.c:41
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:94
#define P(row, col)
Definition: m_matrix.c:147
VOID NTAPI ExpCheckPoolBlocks ( IN PVOID  Block)

Definition at line 366 of file expool.c.

Referenced by ExAllocatePoolWithTag(), and ExFreePoolWithTag().

367 {
368  BOOLEAN FoundBlock = FALSE;
369  SIZE_T Size = 0;
371 
372  /* Get the first entry for this page, make sure it really is the first */
373  Entry = PAGE_ALIGN(Block);
374  ASSERT(Entry->PreviousSize == 0);
375 
376  /* Now scan each entry */
377  while (TRUE)
378  {
379  /* When we actually found our block, remember this */
380  if (Entry == Block) FoundBlock = TRUE;
381 
382  /* Now validate this block header */
383  ExpCheckPoolHeader(Entry);
384 
385  /* And go to the next one, keeping track of our size */
386  Size += Entry->BlockSize;
387  Entry = POOL_NEXT_BLOCK(Entry);
388 
389  /* If we hit the last block, stop */
390  if (Size >= (PAGE_SIZE / POOL_BLOCK_SIZE)) break;
391 
392  /* If we hit the end of the page, stop */
393  if (PAGE_ALIGN(Entry) == Entry) break;
394  }
395 
396  /* We must've found our block, and we must have hit the end of the page */
397  if ((PAGE_ALIGN(Entry) != Entry) || !(FoundBlock))
398  {
399  /* Otherwise, the blocks are messed up */
400  KeBugCheckEx(BAD_POOL_HEADER, 10, (ULONG_PTR)Block, __LINE__, (ULONG_PTR)Entry);
401  }
402 }
#define TRUE
Definition: types.h:120
struct _Entry Entry
Definition: kefuncs.h:640
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define FALSE
Definition: types.h:117
#define POOL_NEXT_BLOCK(x)
Definition: expool.c:54
VOID NTAPI ExpCheckPoolHeader(IN PPOOL_HEADER Entry)
Definition: expool.c:183
UINTN Size
Definition: acefiex.h:555
unsigned char BOOLEAN
#define PAGE_ALIGN(Va)
#define PAGE_SIZE
Definition: env_spec_w32.h:49
ULONG_PTR SIZE_T
Definition: typedefs.h:78
USHORT PreviousSize
#define POOL_BLOCK_SIZE
Definition: miarm.h:248
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:94
VOID NTAPI ExpCheckPoolHeader ( IN PPOOL_HEADER  Entry)

Definition at line 183 of file expool.c.

Referenced by ExpCheckPoolAllocation(), and ExpCheckPoolBlocks().

184 {
185  PPOOL_HEADER PreviousEntry, NextEntry;
186 
187  /* Is there a block before this one? */
188  if (Entry->PreviousSize)
189  {
190  /* Get it */
191  PreviousEntry = POOL_PREV_BLOCK(Entry);
192 
193  /* The two blocks must be on the same page! */
194  if (PAGE_ALIGN(Entry) != PAGE_ALIGN(PreviousEntry))
195  {
196  /* Something is awry */
197  KeBugCheckEx(BAD_POOL_HEADER,
198  6,
199  (ULONG_PTR)PreviousEntry,
200  __LINE__,
201  (ULONG_PTR)Entry);
202  }
203 
204  /* This block should also indicate that it's as large as we think it is */
205  if (PreviousEntry->BlockSize != Entry->PreviousSize)
206  {
207  /* Otherwise, someone corrupted one of the sizes */
208  DPRINT1("PreviousEntry BlockSize %lu, tag %.4s. Entry PreviousSize %lu, tag %.4s\n",
209  PreviousEntry->BlockSize, (char *)&PreviousEntry->PoolTag,
210  Entry->PreviousSize, (char *)&Entry->PoolTag);
211  KeBugCheckEx(BAD_POOL_HEADER,
212  5,
213  (ULONG_PTR)PreviousEntry,
214  __LINE__,
215  (ULONG_PTR)Entry);
216  }
217  }
218  else if (PAGE_ALIGN(Entry) != Entry)
219  {
220  /* If there's no block before us, we are the first block, so we should be on a page boundary */
221  KeBugCheckEx(BAD_POOL_HEADER,
222  7,
223  0,
224  __LINE__,
225  (ULONG_PTR)Entry);
226  }
227 
228  /* This block must have a size */
229  if (!Entry->BlockSize)
230  {
231  /* Someone must've corrupted this field */
232  if (Entry->PreviousSize)
233  {
234  PreviousEntry = POOL_PREV_BLOCK(Entry);
235  DPRINT1("PreviousEntry tag %.4s. Entry tag %.4s\n",
236  (char *)&PreviousEntry->PoolTag,
237  (char *)&Entry->PoolTag);
238  }
239  else
240  {
241  DPRINT1("Entry tag %.4s\n",
242  (char *)&Entry->PoolTag);
243  }
244  KeBugCheckEx(BAD_POOL_HEADER,
245  8,
246  0,
247  __LINE__,
248  (ULONG_PTR)Entry);
249  }
250 
251  /* Okay, now get the next block */
252  NextEntry = POOL_NEXT_BLOCK(Entry);
253 
254  /* If this is the last block, then we'll be page-aligned, otherwise, check this block */
255  if (PAGE_ALIGN(NextEntry) != NextEntry)
256  {
257  /* The two blocks must be on the same page! */
258  if (PAGE_ALIGN(Entry) != PAGE_ALIGN(NextEntry))
259  {
260  /* Something is messed up */
261  KeBugCheckEx(BAD_POOL_HEADER,
262  9,
263  (ULONG_PTR)NextEntry,
264  __LINE__,
265  (ULONG_PTR)Entry);
266  }
267 
268  /* And this block should think we are as large as we truly are */
269  if (NextEntry->PreviousSize != Entry->BlockSize)
270  {
271  /* Otherwise, someone corrupted the field */
272  DPRINT1("Entry BlockSize %lu, tag %.4s. NextEntry PreviousSize %lu, tag %.4s\n",
273  Entry->BlockSize, (char *)&Entry->PoolTag,
274  NextEntry->PreviousSize, (char *)&NextEntry->PoolTag);
275  KeBugCheckEx(BAD_POOL_HEADER,
276  5,
277  (ULONG_PTR)NextEntry,
278  __LINE__,
279  (ULONG_PTR)Entry);
280  }
281  }
282 }
#define POOL_PREV_BLOCK(x)
Definition: expool.c:55
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define POOL_NEXT_BLOCK(x)
Definition: expool.c:54
#define PAGE_ALIGN(Va)
USHORT PreviousSize
#define DPRINT1
Definition: precomp.h:8
base of all file and directory entries
Definition: entries.h:82
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:94
FORCEINLINE VOID ExpCheckPoolIrqlLevel ( IN POOL_TYPE  PoolType,
IN SIZE_T  NumberOfBytes,
IN PVOID  Entry 
)

Definition at line 406 of file expool.c.

Referenced by ExAllocatePoolWithTag(), and ExFreePoolWithTag().

409 {
410  //
411  // Validate IRQL: It must be APC_LEVEL or lower for Paged Pool, and it must
412  // be DISPATCH_LEVEL or lower for Non Paged Pool
413  //
414  if (((PoolType & BASE_POOL_TYPE_MASK) == PagedPool) ?
417  {
418  //
419  // Take the system down
420  //
421  KeBugCheckEx(BAD_POOL_CALLER,
424  PoolType,
426  }
427 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define POOL_FREE_IRQL_INVALID
Definition: miarm.h:284
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
#define POOL_ALLOC_IRQL_INVALID
Definition: miarm.h:283
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
IN SIZE_T NumberOfBytes
Definition: ndis.h:3915
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
#define APC_LEVEL
Definition: env_spec_w32.h:695
base of all file and directory entries
Definition: entries.h:82
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:94
VOID NTAPI ExpCheckPoolLinks ( IN PLIST_ENTRY  ListHead)

Definition at line 89 of file expool.c.

Referenced by ExAllocatePoolWithTag(), ExFreePoolWithTag(), ExpInsertPoolHeadList(), and ExpInsertPoolTailList().

90 {
91  if ((ExpDecodePoolLink(ExpDecodePoolLink(ListHead->Flink)->Blink) != ListHead) ||
92  (ExpDecodePoolLink(ExpDecodePoolLink(ListHead->Blink)->Flink) != ListHead))
93  {
94  KeBugCheckEx(BAD_POOL_HEADER,
95  3,
96  (ULONG_PTR)ListHead,
99  }
100 }
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
uint32_t ULONG_PTR
Definition: typedefs.h:63
PLIST_ENTRY NTAPI ExpDecodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:75
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:94
FORCEINLINE ULONG ExpComputeHashForTag ( IN ULONG  Tag,
IN SIZE_T  BucketMask 
)

Definition at line 431 of file expool.c.

Referenced by ExpInsertPoolTracker(), ExpRemovePoolTracker(), and ExpSeedHotTags().

433 {
434  //
435  // Compute the hash by multiplying with a large prime number and then XORing
436  // with the HIDWORD of the result.
437  //
438  // Finally, AND with the bucket mask to generate a valid index/bucket into
439  // the table
440  //
441  ULONGLONG Result = (ULONGLONG)40543 * Tag;
442  return (ULONG)BucketMask & ((ULONG)Result ^ (Result >> 32));
443 }
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
uint64_t ULONGLONG
Definition: typedefs.h:65
IN ULONG IN ULONG Tag
Definition: evtlib.h:159
unsigned int ULONG
Definition: retypes.h:1
FORCEINLINE ULONG ExpComputePartialHashForAddress ( IN PVOID  BaseAddress)

Definition at line 447 of file expool.c.

Referenced by ExpAddTagForBigPages(), and ExpFindAndRemoveTagBigPages().

448 {
449  ULONG Result;
450  //
451  // Compute the hash by converting the address into a page number, and then
452  // XORing each nibble with the next one.
453  //
454  // We do *NOT* AND with the bucket mask at this point because big table expansion
455  // might happen. Therefore, the final step of the hash must be performed
456  // while holding the expansion pushlock, and this is why we call this a
457  // "partial" hash only.
458  //
459  Result = (ULONG)((ULONG_PTR)BaseAddress >> PAGE_SHIFT);
460  return (Result >> 24) ^ (Result >> 16) ^ (Result >> 8) ^ Result;
461 }
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
uint32_t ULONG_PTR
Definition: typedefs.h:63
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
unsigned int ULONG
Definition: retypes.h:1
PLIST_ENTRY NTAPI ExpDecodePoolLink ( IN PLIST_ENTRY  Link)

Definition at line 75 of file expool.c.

Referenced by ExFreePoolWithTag(), ExpCheckPoolLinks(), ExpInsertPoolHeadList(), ExpInsertPoolTailList(), ExpIsPoolListEmpty(), ExpRemovePoolEntryList(), ExpRemovePoolHeadList(), and ExpRemovePoolTailList().

76 {
77  return (PLIST_ENTRY)((ULONG_PTR)Link & ~1);
78 }
static int Link(const char **args)
Definition: vfdcmd.c:2414
Definition: typedefs.h:117
#define ULONG_PTR
Definition: config.h:101
PLIST_ENTRY NTAPI ExpEncodePoolLink ( IN PLIST_ENTRY  Link)

Definition at line 82 of file expool.c.

Referenced by ExpInitializePoolListHead(), ExpInsertPoolHeadList(), ExpInsertPoolTailList(), ExpRemovePoolEntryList(), ExpRemovePoolHeadList(), and ExpRemovePoolTailList().

83 {
84  return (PLIST_ENTRY)((ULONG_PTR)Link | 1);
85 }
static int Link(const char **args)
Definition: vfdcmd.c:2414
Definition: typedefs.h:117
#define ULONG_PTR
Definition: config.h:101
ULONG NTAPI ExpFindAndRemoveTagBigPages ( IN PVOID  Va,
OUT PULONG_PTR  BigPages,
IN POOL_TYPE  PoolType 
)

Definition at line 1542 of file expool.c.

Referenced by ExFreePoolWithTag().

1545 {
1546  BOOLEAN FirstTry = TRUE;
1547  SIZE_T TableSize;
1548  KIRQL OldIrql;
1549  ULONG PoolTag, Hash;
1553 
1554  //
1555  // As the table is expandable, these values must only be read after acquiring
1556  // the lock to avoid a teared access during an expansion
1557  //
1560  Hash &= PoolBigPageTableHash;
1561  TableSize = PoolBigPageTableSize;
1562 
1563  //
1564  // Loop while trying to find this big page allocation
1565  //
1566  while (PoolBigPageTable[Hash].Va != Va)
1567  {
1568  //
1569  // Increment the size until we go past the end of the table
1570  //
1571  if (++Hash >= TableSize)
1572  {
1573  //
1574  // Is this the second time we've tried?
1575  //
1576  if (!FirstTry)
1577  {
1578  //
1579  // This means it was never inserted into the pool table and it
1580  // received the special "BIG" tag -- return that and return 0
1581  // so that the code can ask Mm for the page count instead
1582  //
1584  *BigPages = 0;
1585  return ' GIB';
1586  }
1587 
1588  //
1589  // The first time this happens, reset the hash index and try again
1590  //
1591  Hash = 0;
1592  FirstTry = FALSE;
1593  }
1594  }
1595 
1596  //
1597  // Now capture all the information we need from the entry, since after we
1598  // release the lock, the data can change
1599  //
1600  Entry = &PoolBigPageTable[Hash];
1601  *BigPages = Entry->NumberOfPages;
1602  PoolTag = Entry->Key;
1603 
1604  //
1605  // Set the free bit, and decrement the number of allocations. Finally, release
1606  // the lock and return the tag that was located
1607  //
1608  InterlockedIncrement((PLONG)&Entry->Va);
1611  return PoolTag;
1612 }
static int Hash(const char *)
Definition: reader.c:2258
#define TRUE
Definition: types.h:120
#define SESSION_POOL_MASK
Definition: mm.h:102
struct _Entry Entry
Definition: kefuncs.h:640
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
uint32_t ULONG_PTR
Definition: typedefs.h:63
KSPIN_LOCK ExpLargePoolTableLock
Definition: expool.c:45
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
SIZE_T PoolBigPageTableSize
Definition: expool.c:39
_Must_inspect_result_ _In_ LPCGUID ULONG _In_ FSRTL_ALLOCATE_ECP_FLAGS _In_opt_ PFSRTL_EXTRA_CREATE_PARAMETER_CLEANUP_CALLBACK _In_ ULONG PoolTag
Definition: fltkernel.h:2520
ULONG ExpPoolBigEntriesInUse
Definition: expool.c:46
unsigned char BOOLEAN
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
#define InterlockedDecrementUL(Addend)
Definition: ex.h:1466
Definition: copy.c:32
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define InterlockedIncrement
Definition: armddk.h:53
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
FORCEINLINE ULONG ExpComputePartialHashForAddress(IN PVOID BaseAddress)
Definition: expool.c:447
PPOOL_TRACKER_BIG_PAGES PoolBigPageTable
Definition: expool.c:41
SIZE_T PoolBigPageTableHash
Definition: expool.c:39
#define POOL_BIG_TABLE_ENTRY_FREE
Definition: expool.c:23
_Must_inspect_result_ typedef _Out_ PULONG TableSize
Definition: iotypes.h:3938
unsigned int ULONG
Definition: retypes.h:1
signed int * PLONG
Definition: retypes.h:5
VOID NTAPI ExpGetPoolTagInfoTarget ( IN PKDPC  Dpc,
IN PVOID  DeferredContext,
IN PVOID  SystemArgument1,
IN PVOID  SystemArgument2 
)

Definition at line 1313 of file expool.c.

Referenced by ExGetPoolTagInfo().

1317 {
1321 
1322  //
1323  // Make sure we win the race, and if we did, copy the data atomically
1324  //
1326  {
1327  RtlCopyMemory(Context->PoolTrackTable,
1329  Context->PoolTrackTableSize * sizeof(POOL_TRACKER_TABLE));
1330 
1331  //
1332  // This is here because ReactOS does not yet support expansion
1333  //
1334  ASSERT(Context->PoolTrackTableSizeExpansion == 0);
1335  }
1336 
1337  //
1338  // Regardless of whether we won or not, we must now synchronize and then
1339  // decrement the barrier since this is one more processor that has completed
1340  // the callback.
1341  //
1344 }
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
SIZE_T PoolTrackTableSize
Definition: expool.c:28
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
SIZE_T PoolTrackTableSizeExpansion
Definition: expool.c:30
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:675
_In_ LARGE_INTEGER _In_opt_ PKDPC Dpc
Definition: kefuncs.h:524
PPOOL_TRACKER_TABLE PoolTrackTable
Definition: expool.c:40
PPOOL_TRACKER_TABLE PoolTrackTable
Definition: expool.c:27
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:675
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
VOID NTAPI KeSignalCallDpcDone(IN PVOID SystemArgument1)
Definition: dpc.c:1012
BOOLEAN NTAPI KeSignalCallDpcSynchronize(IN PVOID SystemArgument2)
Definition: dpc.c:1025
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:675
VOID NTAPI ExpInitializePoolListHead ( IN PLIST_ENTRY  ListHead)

Definition at line 104 of file expool.c.

Referenced by ExInitializePoolDescriptor().

105 {
106  ListHead->Flink = ListHead->Blink = ExpEncodePoolLink(ListHead);
107 }
PLIST_ENTRY NTAPI ExpEncodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:82
VOID NTAPI ExpInsertPoolHeadList ( IN PLIST_ENTRY  ListHead,
IN PLIST_ENTRY  Entry 
)

Definition at line 168 of file expool.c.

Referenced by ExFreePoolWithTag().

170 {
171  PLIST_ENTRY Flink;
172  ExpCheckPoolLinks(ListHead);
173  Flink = ExpDecodePoolLink(ListHead->Flink);
174  Entry->Flink = ExpEncodePoolLink(Flink);
175  Entry->Blink = ExpEncodePoolLink(ListHead);
176  Flink->Blink = ExpEncodePoolLink(Entry);
177  ListHead->Flink = ExpEncodePoolLink(Entry);
178  ExpCheckPoolLinks(ListHead);
179 }
VOID NTAPI ExpCheckPoolLinks(IN PLIST_ENTRY ListHead)
Definition: expool.c:89
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
PLIST_ENTRY NTAPI ExpEncodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:82
PLIST_ENTRY NTAPI ExpDecodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:75
Definition: typedefs.h:117
base of all file and directory entries
Definition: entries.h:82
VOID NTAPI ExpInsertPoolTailList ( IN PLIST_ENTRY  ListHead,
IN PLIST_ENTRY  Entry 
)

Definition at line 153 of file expool.c.

Referenced by ExAllocatePoolWithTag().

155 {
156  PLIST_ENTRY Blink;
157  ExpCheckPoolLinks(ListHead);
158  Blink = ExpDecodePoolLink(ListHead->Blink);
159  Entry->Flink = ExpEncodePoolLink(ListHead);
160  Entry->Blink = ExpEncodePoolLink(Blink);
161  Blink->Flink = ExpEncodePoolLink(Entry);
162  ListHead->Blink = ExpEncodePoolLink(Entry);
163  ExpCheckPoolLinks(ListHead);
164 }
VOID NTAPI ExpCheckPoolLinks(IN PLIST_ENTRY ListHead)
Definition: expool.c:89
PLIST_ENTRY NTAPI ExpEncodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:82
PLIST_ENTRY NTAPI ExpDecodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:75
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
Definition: typedefs.h:117
base of all file and directory entries
Definition: entries.h:82
VOID NTAPI ExpInsertPoolTracker ( IN ULONG  Key,
IN SIZE_T  NumberOfBytes,
IN POOL_TYPE  PoolType 
)

Definition at line 845 of file expool.c.

Referenced by ExAllocatePoolWithTag(), and InitializePool().

848 {
849  ULONG Hash, Index;
850  KIRQL OldIrql;
852  SIZE_T TableMask, TableSize;
853 
854  //
855  // Remove the PROTECTED_POOL flag which is not part of the tag
856  //
857  Key &= ~PROTECTED_POOL;
858 
859  //
860  // With WinDBG you can set a tag you want to break on when an allocation is
861  // attempted
862  //
863  if (Key == PoolHitTag) DbgBreakPoint();
864 
865  //
866  // There is also an internal flag you can set to break on malformed tags
867  //
868  if (ExStopBadTags) ASSERT(Key & 0xFFFFFF00);
869 
870  //
871  // ASSERT on ReactOS features not yet supported
872  //
875 
876  //
877  // Why the double indirection? Because normally this function is also used
878  // when doing session pool allocations, which has another set of tables,
879  // sizes, and masks that live in session pool. Now we don't support session
880  // pool so we only ever use the regular tables, but I'm keeping the code this
881  // way so that the day we DO support session pool, it won't require that
882  // many changes
883  //
884  Table = PoolTrackTable;
885  TableMask = PoolTrackTableMask;
886  TableSize = PoolTrackTableSize;
888 
889  //
890  // Compute the hash for this key, and loop all the possible buckets
891  //
892  Hash = ExpComputeHashForTag(Key, TableMask);
893  Index = Hash;
894  while (TRUE)
895  {
896  //
897  // Do we already have an entry for this tag? */
898  //
899  TableEntry = &Table[Hash];
900  if (TableEntry->Key == Key)
901  {
902  //
903  // Increment the counters depending on if this was paged or nonpaged
904  // pool
905  //
907  {
908  InterlockedIncrement(&TableEntry->NonPagedAllocs);
910  return;
911  }
912  InterlockedIncrement(&TableEntry->PagedAllocs);
914  return;
915  }
916 
917  //
918  // We don't have an entry yet, but we've found a free bucket for it
919  //
920  if (!(TableEntry->Key) && (Hash != PoolTrackTableSize - 1))
921  {
922  //
923  // We need to hold the lock while creating a new entry, since other
924  // processors might be in this code path as well
925  //
927  if (!PoolTrackTable[Hash].Key)
928  {
929  //
930  // We've won the race, so now create this entry in the bucket
931  //
932  ASSERT(Table[Hash].Key == 0);
934  TableEntry->Key = Key;
935  }
937 
938  //
939  // Now we force the loop to run again, and we should now end up in
940  // the code path above which does the interlocked increments...
941  //
942  continue;
943  }
944 
945  //
946  // This path is hit when we don't have an entry, and the current bucket
947  // is full, so we simply try the next one
948  //
949  Hash = (Hash + 1) & TableMask;
950  if (Hash == Index) break;
951  }
952 
953  //
954  // And finally this path is hit when all the buckets are full, and we need
955  // some expansion. This path is not yet supported in ReactOS and so we'll
956  // ignore the tag
957  //
958  DPRINT1("Out of pool tag space, ignoring...\n");
959 }
static int Hash(const char *)
Definition: reader.c:2258
#define TRUE
Definition: types.h:120
SIZE_T PoolTrackTableMask
Definition: expool.c:38
#define SESSION_POOL_MASK
Definition: mm.h:102
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define ExReleaseSpinLock(Lock, OldIrql)
SIZE_T PoolTrackTableSize
Definition: expool.c:38
void DbgBreakPoint()
Definition: mach.c:558
#define ExAcquireSpinLock(Lock, OldIrql)
ULONG PoolHitTag
Definition: expool.c:43
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:325
UCHAR KIRQL
Definition: env_spec_w32.h:591
VOID * Table
Definition: acefiex.h:656
SIZE_T NonPagedBytes
Definition: miarm.h:351
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:326
BOOLEAN ExStopBadTags
Definition: expool.c:44
PPOOL_TRACKER_TABLE PoolTrackTable
Definition: expool.c:40
static const UCHAR Index[8]
Definition: usbohci.c:11
#define PROTECTED_POOL
Definition: extypes.h:294
SIZE_T PagedBytes
Definition: miarm.h:354
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
IN SIZE_T NumberOfBytes
Definition: ndis.h:3915
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define InterlockedIncrement
Definition: armddk.h:53
FORCEINLINE ULONG ExpComputeHashForTag(IN ULONG Tag, IN SIZE_T BucketMask)
Definition: expool.c:431
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:3914
LONG NonPagedAllocs
Definition: miarm.h:349
_Must_inspect_result_ typedef _Out_ PULONG TableSize
Definition: iotypes.h:3938
unsigned int ULONG
Definition: retypes.h:1
ACPI_EFI_INPUT_KEY * Key
Definition: acefiex.h:303
KSPIN_LOCK ExpTaggedPoolLock
Definition: expool.c:42
BOOLEAN NTAPI ExpIsPoolListEmpty ( IN PLIST_ENTRY  ListHead)

Definition at line 111 of file expool.c.

Referenced by ExAllocatePoolWithTag().

112 {
113  return (ExpDecodePoolLink(ListHead->Flink) == ListHead);
114 }
PLIST_ENTRY NTAPI ExpDecodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:75
VOID NTAPI ExpRemovePoolEntryList ( IN PLIST_ENTRY  Entry)

Definition at line 118 of file expool.c.

Referenced by ExFreePoolWithTag().

119 {
120  PLIST_ENTRY Blink, Flink;
121  Flink = ExpDecodePoolLink(Entry->Flink);
122  Blink = ExpDecodePoolLink(Entry->Blink);
123  Flink->Blink = ExpEncodePoolLink(Blink);
124  Blink->Flink = ExpEncodePoolLink(Flink);
125 }
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
PLIST_ENTRY NTAPI ExpEncodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:82
PLIST_ENTRY NTAPI ExpDecodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:75
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
Definition: typedefs.h:117
base of all file and directory entries
Definition: entries.h:82
PLIST_ENTRY NTAPI ExpRemovePoolHeadList ( IN PLIST_ENTRY  ListHead)

Definition at line 129 of file expool.c.

Referenced by ExAllocatePoolWithTag().

130 {
131  PLIST_ENTRY Entry, Flink;
132  Entry = ExpDecodePoolLink(ListHead->Flink);
133  Flink = ExpDecodePoolLink(Entry->Flink);
134  ListHead->Flink = ExpEncodePoolLink(Flink);
135  Flink->Blink = ExpEncodePoolLink(ListHead);
136  return Entry;
137 }
struct _Entry Entry
Definition: kefuncs.h:640
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
PLIST_ENTRY NTAPI ExpEncodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:82
PLIST_ENTRY NTAPI ExpDecodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:75
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
Definition: typedefs.h:117
PLIST_ENTRY NTAPI ExpRemovePoolTailList ( IN PLIST_ENTRY  ListHead)

Definition at line 141 of file expool.c.

142 {
143  PLIST_ENTRY Entry, Blink;
144  Entry = ExpDecodePoolLink(ListHead->Blink);
145  Blink = ExpDecodePoolLink(Entry->Blink);
146  ListHead->Blink = ExpEncodePoolLink(Blink);
147  Blink->Flink = ExpEncodePoolLink(ListHead);
148  return Entry;
149 }
struct _Entry Entry
Definition: kefuncs.h:640
struct _LIST_ENTRY * Blink
Definition: typedefs.h:120
PLIST_ENTRY NTAPI ExpEncodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:82
PLIST_ENTRY NTAPI ExpDecodePoolLink(IN PLIST_ENTRY Link)
Definition: expool.c:75
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
Definition: typedefs.h:117
VOID NTAPI ExpRemovePoolTracker ( IN ULONG  Key,
IN SIZE_T  NumberOfBytes,
IN POOL_TYPE  PoolType 
)

Definition at line 754 of file expool.c.

Referenced by ExFreePoolWithTag().

757 {
758  ULONG Hash, Index;
760  SIZE_T TableMask, TableSize;
761 
762  //
763  // Remove the PROTECTED_POOL flag which is not part of the tag
764  //
765  Key &= ~PROTECTED_POOL;
766 
767  //
768  // With WinDBG you can set a tag you want to break on when an allocation is
769  // attempted
770  //
771  if (Key == PoolHitTag) DbgBreakPoint();
772 
773  //
774  // Why the double indirection? Because normally this function is also used
775  // when doing session pool allocations, which has another set of tables,
776  // sizes, and masks that live in session pool. Now we don't support session
777  // pool so we only ever use the regular tables, but I'm keeping the code this
778  // way so that the day we DO support session pool, it won't require that
779  // many changes
780  //
781  Table = PoolTrackTable;
782  TableMask = PoolTrackTableMask;
783  TableSize = PoolTrackTableSize;
785 
786  //
787  // Compute the hash for this key, and loop all the possible buckets
788  //
789  Hash = ExpComputeHashForTag(Key, TableMask);
790  Index = Hash;
791  while (TRUE)
792  {
793  //
794  // Have we found the entry for this tag? */
795  //
796  TableEntry = &Table[Hash];
797  if (TableEntry->Key == Key)
798  {
799  //
800  // Decrement the counters depending on if this was paged or nonpaged
801  // pool
802  //
804  {
805  InterlockedIncrement(&TableEntry->NonPagedFrees);
808  return;
809  }
810  InterlockedIncrement(&TableEntry->PagedFrees);
813  return;
814  }
815 
816  //
817  // We should have only ended up with an empty entry if we've reached
818  // the last bucket
819  //
820  if (!TableEntry->Key)
821  {
822  DPRINT1("Empty item reached in tracker table. Hash=0x%lx, TableMask=0x%lx, Tag=0x%08lx, NumberOfBytes=%lu, PoolType=%d\n",
823  Hash, TableMask, Key, (ULONG)NumberOfBytes, PoolType);
824  ASSERT(Hash == TableMask);
825  }
826 
827  //
828  // This path is hit when we don't have an entry, and the current bucket
829  // is full, so we simply try the next one
830  //
831  Hash = (Hash + 1) & TableMask;
832  if (Hash == Index) break;
833  }
834 
835  //
836  // And finally this path is hit when all the buckets are full, and we need
837  // some expansion. This path is not yet supported in ReactOS and so we'll
838  // ignore the tag
839  //
840  DPRINT1("Out of pool tag space, ignoring...\n");
841 }
static int Hash(const char *)
Definition: reader.c:2258
#define TRUE
Definition: types.h:120
SIZE_T PoolTrackTableMask
Definition: expool.c:38
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
SIZE_T PoolTrackTableSize
Definition: expool.c:38
LONG_PTR SSIZE_T
Definition: basetsd.h:183
void DbgBreakPoint()
Definition: mach.c:558
ULONG PoolHitTag
Definition: expool.c:43
VOID * Table
Definition: acefiex.h:656
SIZE_T NonPagedBytes
Definition: miarm.h:351
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
#define DBG_UNREFERENCED_LOCAL_VARIABLE(L)
Definition: ntbasedef.h:326
PPOOL_TRACKER_TABLE PoolTrackTable
Definition: expool.c:40
static const UCHAR Index[8]
Definition: usbohci.c:11
#define PROTECTED_POOL
Definition: extypes.h:294
LONG NonPagedFrees
Definition: miarm.h:350
SIZE_T PagedBytes
Definition: miarm.h:354
#define InterlockedExchangeAddSizeT(a, b)
Definition: interlocked.h:196
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
IN SIZE_T NumberOfBytes
Definition: ndis.h:3915
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define InterlockedIncrement
Definition: armddk.h:53
FORCEINLINE ULONG ExpComputeHashForTag(IN ULONG Tag, IN SIZE_T BucketMask)
Definition: expool.c:431
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ typedef _In_ ULONG TableEntry
Definition: iotypes.h:3914
_Must_inspect_result_ typedef _Out_ PULONG TableSize
Definition: iotypes.h:3938
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI INIT_SECTION ExpSeedHotTags ( VOID  )

Definition at line 634 of file expool.c.

Referenced by InitializePool().

635 {
636  ULONG i, Key, Hash, Index;
637  PPOOL_TRACKER_TABLE TrackTable = PoolTrackTable;
638  ULONG TagList[] =
639  {
640  ' oI',
641  ' laH',
642  'PldM',
643  'LooP',
644  'tSbO',
645  ' prI',
646  'bdDN',
647  'LprI',
648  'pOoI',
649  ' ldM',
650  'eliF',
651  'aVMC',
652  'dSeS',
653  'CFtN',
654  'looP',
655  'rPCT',
656  'bNMC',
657  'dTeS',
658  'sFtN',
659  'TPCT',
660  'CPCT',
661  ' yeK',
662  'qSbO',
663  'mNoI',
664  'aEoI',
665  'cPCT',
666  'aFtN',
667  '0ftN',
668  'tceS',
669  'SprI',
670  'ekoT',
671  ' eS',
672  'lCbO',
673  'cScC',
674  'lFtN',
675  'cAeS',
676  'mfSF',
677  'kWcC',
678  'miSF',
679  'CdfA',
680  'EdfA',
681  'orSF',
682  'nftN',
683  'PRIU',
684  'rFpN',
685  'RFpN',
686  'aPeS',
687  'sUeS',
688  'FpcA',
689  'MpcA',
690  'cSeS',
691  'mNbO',
692  'sFpN',
693  'uLeS',
694  'DPcS',
695  'nevE',
696  'vrqR',
697  'ldaV',
698  ' pP',
699  'SdaV',
700  ' daV',
701  'LdaV',
702  'FdaV',
703  ' GIB',
704  };
705 
706  //
707  // Loop all 64 hot tags
708  //
709  ASSERT((sizeof(TagList) / sizeof(ULONG)) == 64);
710  for (i = 0; i < sizeof(TagList) / sizeof(ULONG); i++)
711  {
712  //
713  // Get the current tag, and compute its hash in the tracker table
714  //
715  Key = TagList[i];
717 
718  //
719  // Loop all the hashes in this index/bucket
720  //
721  Index = Hash;
722  while (TRUE)
723  {
724  //
725  // Find an empty entry, and make sure this isn't the last hash that
726  // can fit.
727  //
728  // On checked builds, also make sure this is the first time we are
729  // seeding this tag.
730  //
731  ASSERT(TrackTable[Hash].Key != Key);
732  if (!(TrackTable[Hash].Key) && (Hash != PoolTrackTableSize - 1))
733  {
734  //
735  // It has been seeded, move on to the next tag
736  //
737  TrackTable[Hash].Key = Key;
738  break;
739  }
740 
741  //
742  // This entry was already taken, compute the next possible hash while
743  // making sure we're not back at our initial index.
744  //
745  ASSERT(TrackTable[Hash].Key != Key);
746  Hash = (Hash + 1) & PoolTrackTableMask;
747  if (Hash == Index) break;
748  }
749  }
750 }
static int Hash(const char *)
Definition: reader.c:2258
#define TRUE
Definition: types.h:120
SIZE_T PoolTrackTableMask
Definition: expool.c:38
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
SIZE_T PoolTrackTableSize
Definition: expool.c:38
GLenum GLclampf GLint i
Definition: glfuncs.h:14
PPOOL_TRACKER_TABLE PoolTrackTable
Definition: expool.c:40
static const UCHAR Index[8]
Definition: usbohci.c:11
FORCEINLINE ULONG ExpComputeHashForTag(IN ULONG Tag, IN SIZE_T BucketMask)
Definition: expool.c:431
unsigned int ULONG
Definition: retypes.h:1
ACPI_EFI_INPUT_KEY * Key
Definition: acefiex.h:303
SIZE_T NTAPI ExQueryPoolBlockSize ( IN PVOID  PoolBlock,
OUT PBOOLEAN  QuotaCharged 
)

Definition at line 2749 of file expool.c.

2751 {
2752  //
2753  // Not implemented
2754  //
2755  UNIMPLEMENTED;
2756  return FALSE;
2757 }
#define FALSE
Definition: types.h:117
#define UNIMPLEMENTED
Definition: debug.h:114
VOID NTAPI ExQueryPoolUsage ( OUT PULONG  PagedPoolPages,
OUT PULONG  NonPagedPoolPages,
OUT PULONG  PagedPoolAllocs,
OUT PULONG  PagedPoolFrees,
OUT PULONG  PagedPoolLookasideHits,
OUT PULONG  NonPagedPoolAllocs,
OUT PULONG  NonPagedPoolFrees,
OUT PULONG  NonPagedPoolLookasideHits 
)

Definition at line 1616 of file expool.c.

Referenced by QSI_DEF().

1624 {
1625  ULONG i;
1626  PPOOL_DESCRIPTOR PoolDesc;
1627 
1628  //
1629  // Assume all failures
1630  //
1631  *PagedPoolPages = 0;
1632  *PagedPoolAllocs = 0;
1633  *PagedPoolFrees = 0;
1634 
1635  //
1636  // Tally up the totals for all the apged pool
1637  //
1638  for (i = 0; i < ExpNumberOfPagedPools + 1; i++)
1639  {
1640  PoolDesc = ExpPagedPoolDescriptor[i];
1641  *PagedPoolPages += PoolDesc->TotalPages + PoolDesc->TotalBigPages;
1642  *PagedPoolAllocs += PoolDesc->RunningAllocs;
1643  *PagedPoolFrees += PoolDesc->RunningDeAllocs;
1644  }
1645 
1646  //
1647  // The first non-paged pool has a hardcoded well-known descriptor name
1648  //
1649  PoolDesc = &NonPagedPoolDescriptor;
1650  *NonPagedPoolPages = PoolDesc->TotalPages + PoolDesc->TotalBigPages;
1651  *NonPagedPoolAllocs = PoolDesc->RunningAllocs;
1652  *NonPagedPoolFrees = PoolDesc->RunningDeAllocs;
1653 
1654  //
1655  // If the system has more than one non-paged pool, copy the other descriptor
1656  // totals as well
1657  //
1658 #if 0
1659  if (ExpNumberOfNonPagedPools > 1)
1660  {
1661  for (i = 0; i < ExpNumberOfNonPagedPools; i++)
1662  {
1663  PoolDesc = ExpNonPagedPoolDescriptor[i];
1664  *NonPagedPoolPages += PoolDesc->TotalPages + PoolDesc->TotalBigPages;
1665  *NonPagedPoolAllocs += PoolDesc->RunningAllocs;
1666  *NonPagedPoolFrees += PoolDesc->RunningDeAllocs;
1667  }
1668  }
1669 #endif
1670 
1671  //
1672  // FIXME: Not yet supported
1673  //
1674  *NonPagedPoolLookasideHits += 0;
1675  *PagedPoolLookasideHits += 0;
1676 }
ULONG RunningDeAllocs
Definition: miarm.h:293
GLenum GLclampf GLint i
Definition: glfuncs.h:14
ULONG ExpNumberOfPagedPools
Definition: expool.c:33
ULONG RunningAllocs
Definition: miarm.h:292
PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16+1]
Definition: expool.c:35
POOL_DESCRIPTOR NonPagedPoolDescriptor
Definition: expool.c:34
ULONG TotalPages
Definition: miarm.h:294
ULONG TotalBigPages
Definition: miarm.h:295
unsigned int ULONG
Definition: retypes.h:1
VOID NTAPI ExReturnPoolQuota ( IN PVOID  P)

Definition at line 1680 of file expool.c.

Referenced by IoFreeIrp().

1681 {
1684  USHORT BlockSize;
1686 
1689  {
1690  return;
1691  }
1692 
1693  Entry = P;
1694  Entry--;
1695  ASSERT((ULONG_PTR)Entry % POOL_BLOCK_SIZE == 0);
1696 
1697  PoolType = Entry->PoolType - 1;
1698  BlockSize = Entry->BlockSize;
1699 
1700  if (PoolType & QUOTA_POOL_MASK)
1701  {
1702  Process = ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1];
1703  ASSERT(Process != NULL);
1704  if (Process)
1705  {
1706  if (Process->Pcb.Header.Type != ProcessObject)
1707  {
1708  DPRINT1("Object %p is not a process. Type %u, pool type 0x%x, block size %u\n",
1709  Process, Process->Pcb.Header.Type, Entry->PoolType, BlockSize);
1710  KeBugCheckEx(BAD_POOL_CALLER,
1711  0x0D,
1712  (ULONG_PTR)P,
1713  Entry->PoolTag,
1714  (ULONG_PTR)Process);
1715  }
1716  ((PVOID *)POOL_NEXT_BLOCK(Entry))[-1] = NULL;
1717  PsReturnPoolQuota(Process,
1718  PoolType & BASE_POOL_TYPE_MASK,
1719  BlockSize * POOL_BLOCK_SIZE);
1720  ObDereferenceObject(Process);
1721  }
1722  }
1723 }
DWORD *typedef PVOID
Definition: winlogon.h:52
struct _Entry Entry
Definition: kefuncs.h:640
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define POOL_FLAG_SPECIAL_POOL
Definition: miarm.h:262
VOID NTAPI ObDereferenceObject(IN PVOID Object)
Definition: obref.c:375
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define POOL_NEXT_BLOCK(x)
Definition: expool.c:54
VOID NTAPI PsReturnPoolQuota(IN PEPROCESS Process, IN POOL_TYPE PoolType, IN SIZE_T Amount)
Definition: quota.c:237
smooth NULL
Definition: ftsmooth.c:416
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
INT POOL_TYPE
Definition: typedefs.h:76
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
KPROCESS Pcb
Definition: pstypes.h:1194
#define QUOTA_POOL_MASK
Definition: ExPools.c:16
unsigned short USHORT
Definition: pedump.c:61
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
ULONG ExpPoolFlags
Definition: expool.c:47
#define POOL_BLOCK_SIZE
Definition: miarm.h:248
BOOLEAN NTAPI MmIsSpecialPoolAddress(IN PVOID P)
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:94
DISPATCHER_HEADER Header
Definition: ketypes.h:1974
#define P(row, col)
Definition: m_matrix.c:147
FORCEINLINE VOID ExUnlockPool ( IN PPOOL_DESCRIPTOR  Descriptor,
IN KIRQL  OldIrql 
)

Definition at line 1289 of file expool.c.

Referenced by ExAllocatePoolWithTag(), and ExFreePoolWithTag().

1291 {
1292  //
1293  // Check if this is nonpaged pool
1294  //
1295  if ((Descriptor->PoolType & BASE_POOL_TYPE_MASK) == NonPagedPool)
1296  {
1297  //
1298  // Use the queued spin lock
1299  //
1301  }
1302  else
1303  {
1304  //
1305  // Use the guarded mutex
1306  //
1307  KeReleaseGuardedMutex(Descriptor->LockAddress);
1308  }
1309 }
#define BASE_POOL_TYPE_MASK
Definition: ExPools.c:15
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966
VOID NTAPI INIT_SECTION InitializePool ( IN POOL_TYPE  PoolType,
IN ULONG  Threshold 
)

Definition at line 1015 of file expool.c.

Referenced by MiBuildPagedPool(), and MiInitMachineDependent().

1017 {
1019  SIZE_T TableSize;
1020  ULONG i;
1021 
1022  //
1023  // Check what kind of pool this is
1024  //
1025  if (PoolType == NonPagedPool)
1026  {
1027  //
1028  // Compute the track table size and convert it from a power of two to an
1029  // actual byte size
1030  //
1031  // NOTE: On checked builds, we'll assert if the registry table size was
1032  // invalid, while on retail builds we'll just break out of the loop at
1033  // that point.
1034  //
1036  for (i = 0; i < 32; i++)
1037  {
1038  if (TableSize & 1)
1039  {
1040  ASSERT((TableSize & ~1) == 0);
1041  if (!(TableSize & ~1)) break;
1042  }
1043  TableSize >>= 1;
1044  }
1045 
1046  //
1047  // If we hit bit 32, than no size was defined in the registry, so
1048  // we'll use the default size of 2048 entries.
1049  //
1050  // Otherwise, use the size from the registry, as long as it's not
1051  // smaller than 64 entries.
1052  //
1053  if (i == 32)
1054  {
1055  PoolTrackTableSize = 2048;
1056  }
1057  else
1058  {
1059  PoolTrackTableSize = max(1 << i, 64);
1060  }
1061 
1062  //
1063  // Loop trying with the biggest specified size first, and cut it down
1064  // by a power of two each iteration in case not enough memory exist
1065  //
1066  while (TRUE)
1067  {
1068  //
1069  // Do not allow overflow
1070  //
1071  if ((PoolTrackTableSize + 1) > (MAXULONG_PTR / sizeof(POOL_TRACKER_TABLE)))
1072  {
1073  PoolTrackTableSize >>= 1;
1074  continue;
1075  }
1076 
1077  //
1078  // Allocate the tracker table and exit the loop if this worked
1079  //
1081  (PoolTrackTableSize + 1) *
1082  sizeof(POOL_TRACKER_TABLE));
1083  if (PoolTrackTable) break;
1084 
1085  //
1086  // Otherwise, as long as we're not down to the last bit, keep
1087  // iterating
1088  //
1089  if (PoolTrackTableSize == 1)
1090  {
1091  KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
1092  TableSize,
1093  0xFFFFFFFF,
1094  0xFFFFFFFF,
1095  0xFFFFFFFF);
1096  }
1097  PoolTrackTableSize >>= 1;
1098  }
1099 
1100  //
1101  // Add one entry, compute the hash, and zero the table
1102  //
1105 
1108 
1109  //
1110  // Finally, add the most used tags to speed up those allocations
1111  //
1112  ExpSeedHotTags();
1113 
1114  //
1115  // We now do the exact same thing with the tracker table for big pages
1116  //
1118  for (i = 0; i < 32; i++)
1119  {
1120  if (TableSize & 1)
1121  {
1122  ASSERT((TableSize & ~1) == 0);
1123  if (!(TableSize & ~1)) break;
1124  }
1125  TableSize >>= 1;
1126  }
1127 
1128  //
1129  // For big pages, the default tracker table is 4096 entries, while the
1130  // minimum is still 64
1131  //
1132  if (i == 32)
1133  {
1134  PoolBigPageTableSize = 4096;
1135  }
1136  else
1137  {
1138  PoolBigPageTableSize = max(1 << i, 64);
1139  }
1140 
1141  //
1142  // Again, run the exact same loop we ran earlier, but this time for the
1143  // big pool tracker instead
1144  //
1145  while (TRUE)
1146  {
1148  {
1149  PoolBigPageTableSize >>= 1;
1150  continue;
1151  }
1152 
1155  sizeof(POOL_TRACKER_BIG_PAGES));
1156  if (PoolBigPageTable) break;
1157 
1158  if (PoolBigPageTableSize == 1)
1159  {
1160  KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
1161  TableSize,
1162  0xFFFFFFFF,
1163  0xFFFFFFFF,
1164  0xFFFFFFFF);
1165  }
1166 
1167  PoolBigPageTableSize >>= 1;
1168  }
1169 
1170  //
1171  // An extra entry is not needed for for the big pool tracker, so just
1172  // compute the hash and zero it
1173  //
1177  for (i = 0; i < PoolBigPageTableSize; i++) PoolBigPageTable[i].Va = (PVOID)1;
1178 
1179  //
1180  // During development, print this out so we can see what's happening
1181  //
1182  DPRINT("EXPOOL: Pool Tracker Table at: 0x%p with 0x%lx bytes\n",
1184  DPRINT("EXPOOL: Big Pool Tracker Table at: 0x%p with 0x%lx bytes\n",
1185  PoolBigPageTable, PoolBigPageTableSize * sizeof(POOL_TRACKER_BIG_PAGES));
1186 
1187  //
1188  // Insert the generic tracker for all of big pool
1189  //
1190  ExpInsertPoolTracker('looP',
1191  ROUND_TO_PAGES(PoolBigPageTableSize *
1192  sizeof(POOL_TRACKER_BIG_PAGES)),
1193  NonPagedPool);
1194 
1195  //
1196  // No support for NUMA systems at this time
1197  //
1198  ASSERT(KeNumberNodes == 1);
1199 
1200  //
1201  // Initialize the tag spinlock
1202  //
1204 
1205  //
1206  // Initialize the nonpaged pool descriptor
1207  //
1210  NonPagedPool,
1211  0,
1212  Threshold,
1213  NULL);
1214  }
1215  else
1216  {
1217  //
1218  // No support for NUMA systems at this time
1219  //
1220  ASSERT(KeNumberNodes == 1);
1221 
1222  //
1223  // Allocate the pool descriptor
1224  //
1225  Descriptor = ExAllocatePoolWithTag(NonPagedPool,
1226  sizeof(KGUARDED_MUTEX) +
1227  sizeof(POOL_DESCRIPTOR),
1228  'looP');
1229  if (!Descriptor)
1230  {
1231  //
1232  // This is really bad...
1233  //
1234  KeBugCheckEx(MUST_SUCCEED_POOL_EMPTY,
1235  0,
1236  -1,
1237  -1,
1238  -1);
1239  }
1240 
1241  //
1242  // Setup the vector and guarded mutex for paged pool
1243  //
1245  ExpPagedPoolMutex = (PKGUARDED_MUTEX)(Descriptor + 1);
1248  ExInitializePoolDescriptor(Descriptor,
1249  PagedPool,
1250  0,
1251  Threshold,
1253 
1254  //
1255  // Insert the generic tracker for all of nonpaged pool
1256  //
1257  ExpInsertPoolTracker('looP',
1259  NonPagedPool);
1260  }
1261 }
DWORD *typedef PVOID
Definition: winlogon.h:52
PVOID NTAPI ExAllocatePoolWithTag(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes, IN ULONG Tag)
Definition: expool.c:1732
#define max(a, b)
Definition: svc.c:63
#define TRUE
Definition: types.h:120
SIZE_T PoolTrackTableMask
Definition: expool.c:38
struct _KGUARDED_MUTEX * PKGUARDED_MUTEX
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
SIZE_T PoolTrackTableSize
Definition: expool.c:38
#define MAXULONG_PTR
Definition: basetsd.h:103
PKGUARDED_MUTEX ExpPagedPoolMutex
Definition: expool.c:37
GLenum GLclampf GLint i
Definition: glfuncs.h:14
PPOOL_DESCRIPTOR PoolVector[2]
Definition: expool.c:36
SIZE_T PoolBigPageTableSize
Definition: expool.c:39
FORCEINLINE VOID KeInitializeSpinLock(_Out_ PKSPIN_LOCK SpinLock)
Definition: kefuncs.h:251
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
PPOOL_TRACKER_TABLE PoolTrackTable
Definition: expool.c:40
PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16+1]
Definition: expool.c:35
VOID NTAPI INIT_SECTION ExpSeedHotTags(VOID)
Definition: expool.c:634
POOL_DESCRIPTOR NonPagedPoolDescriptor
Definition: expool.c:34
PVOID NTAPI MiAllocatePoolPages(IN POOL_TYPE PoolType, IN SIZE_T SizeInBytes)
Definition: pool.c:420
IN REFCLSID IN PUNKNOWN IN POOL_TYPE PoolType
Definition: unknown.h:68
UCHAR KeNumberNodes
Definition: krnlinit.c:40
ULONG_PTR SIZE_T
Definition: typedefs.h:78
VOID NTAPI INIT_SECTION ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor, IN POOL_TYPE PoolType, IN ULONG PoolIndex, IN ULONG Threshold, IN PVOID PoolLock)
Definition: expool.c:964
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
#define ROUND_TO_PAGES(Size)
VOID NTAPI ExpInsertPoolTracker(IN ULONG Key, IN SIZE_T NumberOfBytes, IN POOL_TYPE PoolType)
Definition: expool.c:845
#define min(a, b)
Definition: monoChain.cc:55
PPOOL_TRACKER_BIG_PAGES PoolBigPageTable
Definition: expool.c:41
SIZE_T PoolBigPageTableHash
Definition: expool.c:39
_Must_inspect_result_ typedef _Out_ PULONG TableSize
Definition: iotypes.h:3938
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
ULONG MmSizeOfNonPagedPoolInBytes
Definition: init.c:21
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:94
KSPIN_LOCK ExpTaggedPoolLock
Definition: expool.c:42
_In_ PSTORAGE_PROPERTY_ID _Outptr_ PSTORAGE_DESCRIPTOR_HEADER * Descriptor
Definition: classpnp.h:966

Variable Documentation

KSPIN_LOCK ExpLargePoolTableLock
ULONG ExpNumberOfPagedPools

Definition at line 33 of file expool.c.

Referenced by ExQueryPoolUsage().

ULONG ExPoolFailures

Definition at line 48 of file expool.c.

Referenced by ExAllocatePoolWithTag().

PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16+1]

Definition at line 35 of file expool.c.

PKGUARDED_MUTEX ExpPagedPoolMutex

Definition at line 37 of file expool.c.

ULONG ExpPoolBigEntriesInUse

Definition at line 46 of file expool.c.

Referenced by ExpAddTagForBigPages(), and ExpFindAndRemoveTagBigPages().

KSPIN_LOCK ExpTaggedPoolLock

Definition at line 42 of file expool.c.

Referenced by ExpInsertPoolTracker(), and InitializePool().

BOOLEAN ExStopBadTags

Definition at line 44 of file expool.c.

Referenced by ExpInsertPoolTracker().

POOL_DESCRIPTOR NonPagedPoolDescriptor

Definition at line 34 of file expool.c.

Referenced by ExQueryPoolUsage(), and InitializePool().

PPOOL_TRACKER_BIG_PAGES PoolBigPageTable

Definition at line 41 of file expool.c.

SIZE_T PoolBigPageTableHash

Definition at line 39 of file expool.c.

Referenced by ExpAddTagForBigPages(), ExpFindAndRemoveTagBigPages(), and InitializePool().

SIZE_T PoolBigPageTableSize
ULONG PoolHitTag

Definition at line 43 of file expool.c.

Referenced by ExpInsertPoolTracker(), and ExpRemovePoolTracker().

PPOOL_TRACKER_TABLE PoolTrackTable

Definition at line 40 of file expool.c.

Referenced by ExpInsertPoolTracker(), ExpRemovePoolTracker(), and ExpSeedHotTags().

SIZE_T PoolTrackTableMask
SIZE_T PoolTrackTableSize

Definition at line 38 of file expool.c.

Referenced by ExGetPoolTagInfo(), ExpInsertPoolTracker(), and ExpRemovePoolTracker().

PPOOL_DESCRIPTOR PoolVector[2]

Definition at line 36 of file expool.c.