Author: khornicek
Date: Sun Feb 26 15:05:59 2012
New Revision: 55876
URL: http://svn.reactos.org/svn/reactos?rev=55876&view=rev
Log:
[BOOTDATA]
Include unattend.inf by default (as it was almost done in r28835). No need to have it "disabled" twice.
Removed:
trunk/reactos/boot/bootdata/unattend.inf
Modified:
trunk/reactos/boot/bootdata/CMakeLists.txt
trunk/reactos/boot/bootdata/bootcd/unattend.inf
trunk/reactos/boot/bootdata/bootcdregtest/unattend.inf
Modified: trunk/reactos/boot/bootdata/CMakeLists.txt
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/CMakeLists.t…
==============================================================================
--- trunk/reactos/boot/bootdata/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/boot/bootdata/CMakeLists.txt [iso-8859-1] Sun Feb 26 15:05:59 2012
@@ -51,8 +51,7 @@
#unattend
add_cd_file(FILE ${CMAKE_CURRENT_SOURCE_DIR}/bootcdregtest/unattend.inf DESTINATION reactos NO_CAB FOR regtest)
-#uncomment this for unattend bootcd
-#add_cd_file(FILE ${CMAKE_CURRENT_SOURCE_DIR}/bootcd/unattend.inf DESTINATION reactos NO_CAB FOR bootcd)
+add_cd_file(FILE ${CMAKE_CURRENT_SOURCE_DIR}/bootcd/unattend.inf DESTINATION reactos NO_CAB FOR bootcd)
#LiveCD shortcuts
macro(add_livecd_shortcut name app dest)
Modified: trunk/reactos/boot/bootdata/bootcd/unattend.inf
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/bootcd/unatt…
==============================================================================
--- trunk/reactos/boot/bootdata/bootcd/unattend.inf [iso-8859-1] (original)
+++ trunk/reactos/boot/bootdata/bootcd/unattend.inf [iso-8859-1] Sun Feb 26 15:05:59 2012
@@ -1,6 +1,4 @@
-; In order to get unattended setup working:
-; 1. Copy unattend.inf.sample to unattend.inf, adjust as needed
-; 2. Uncomment the line in bootdata.rbuild to include it into bootcd
+; Set UnattendSetupEnabled to yes in order to get unattended setup working
[Unattend]
Signature = "$ReactOS$"
@@ -49,7 +47,7 @@
; set this option to automatically
; specify language in 2nd mode setup
; see hivesys.inf for available languages
-; LocaleID = 407
+LocaleID = 409
; enable this section to automatically launch programs
Modified: trunk/reactos/boot/bootdata/bootcdregtest/unattend.inf
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/bootcdregtes…
==============================================================================
--- trunk/reactos/boot/bootdata/bootcdregtest/unattend.inf [iso-8859-1] (original)
+++ trunk/reactos/boot/bootdata/bootcdregtest/unattend.inf [iso-8859-1] Sun Feb 26 15:05:59 2012
@@ -1,6 +1,4 @@
-; In order to get unattended setup working:
-; 1. Copy unattend.inf.sample to unattend.inf, adjust as needed
-; 2. Uncomment the line in bootdata.rbuild to include it into bootcd
+; Set UnattendSetupEnabled to yes in order to get unattended setup working
[Unattend]
Signature = "$ReactOS$"
Removed: trunk/reactos/boot/bootdata/unattend.inf
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/unattend.inf…
==============================================================================
--- trunk/reactos/boot/bootdata/unattend.inf [iso-8859-1] (original)
+++ trunk/reactos/boot/bootdata/unattend.inf (removed)
@@ -1,60 +1,0 @@
-; In order to get unattended setup working:
-; 1. Copy unattend.inf.sample to unattend.inf, adjust as needed
-; 2. Uncomment the line in bootdata.rbuild to include it into bootcd
-
-[Unattend]
-Signature = "$ReactOS$"
-
-; yes - unattend setup enabled
-; no - unattend setup disabled
-UnattendSetupEnabled = no
-
-; Install to \Device\Harddisk0\Partition1\ReactOS
-DestinationDiskNumber = 0
-DestinationPartitionNumber = 1
-InstallationDirectory=ReactOS
-
-; MBRInstallType=0 skips MBR installation
-; MBRInstallType=1 install MBR on floppy
-; MBRInstallType=2 install MBR on hdd
-MBRInstallType=2
-
-FullName="MyName"
-;OrgName="MyOrg"
-ComputerName="MYCOMPUTERNAME";
-AdminPassword="MyPassword"
-
-; TimeZone is set GMT as default
-TimeZoneIndex=85
-
-; enable this setting to disable daylight saving changes
-; DisableAutoDaylightTimeSet = 1
-
-; enable this setting to format the selected partition
-; 1 - format enabled
-; 0 - format disabled
-FormatPartition=1
-
-; enable this setting to automatically create a partition
-; during installation
-; 1 - enabled
-; 0 - disabled
-AutoPartition = 1
-
-; enable this setting to disable vmware driver install
-; yes - disabled
-; no - enabled
-DisableVmwInst = yes
-
-; set this option to automatically
-; specify language in 2nd mode setup
-; see hivesys.inf for available languages
-; LocaleID = 407
-
-
-; enable this section to automatically launch programs
-; after 3rd boot
-;
-; [GuiRunOnce]
-; %SystemRoot%\system32\cmd.exe
-
Author: sir_richard
Date: Sun Feb 26 05:53:53 2012
New Revision: 55874
URL: http://svn.reactos.org/svn/reactos?rev=55874&view=rev
Log:
[NTOS]: Implement pool tagging for large allocations too. Once again, no expansion is implemented.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/expool.c
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
trunk/reactos/ntoskrnl/mm/ARM3/pool.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/expool.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/expool.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] Sun Feb 26 05:53:53 2012
@@ -19,6 +19,8 @@
#undef ExAllocatePoolWithQuotaTag
/* GLOBALS ********************************************************************/
+
+#define POOL_BIG_TABLE_ENTRY_FREE 0x1
typedef struct _POOL_DPC_CONTEXT
{
@@ -40,6 +42,8 @@
KSPIN_LOCK ExpTaggedPoolLock;
ULONG PoolHitTag;
BOOLEAN ExStopBadTags;
+KSPIN_LOCK ExpLargePoolTableLock;
+LONG ExpPoolBigEntriesInUse;
/* Pool block/header/list access macros */
#define POOL_ENTRY(x) (PPOOL_HEADER)((ULONG_PTR)(x) - sizeof(POOL_HEADER))
@@ -311,6 +315,24 @@
//
ULONGLONG Result = 40543 * Tag;
return BucketMask & (Result ^ (Result >> 32));
+}
+
+FORCEINLINE
+ULONG
+ExpComputePartialHashForAddress(IN PVOID BaseAddress)
+{
+ ULONG Result;
+ //
+ // Compute the hash by converting the address into a page number, and then
+ // XORing each nibble with the next one.
+ //
+ // We do *NOT* AND with the bucket mask at this point because big table expansion
+ // might happen. Therefore, the final step of the hash must be performed
+ // while holding the expansion pushlock, and this is why we call this a
+ // "partial" hash only.
+ //
+ Result = (ULONG_PTR)BaseAddress >> PAGE_SHIFT;
+ return (Result >> 24) ^ (Result >> 16) ^ (Result >> 8) ^ Result;
}
/* PRIVATE FUNCTIONS **********************************************************/
@@ -1120,6 +1142,169 @@
return Status;
}
+BOOLEAN
+NTAPI
+ExpAddTagForBigPages(IN PVOID Va,
+ IN ULONG Key,
+ IN ULONG NumberOfPages,
+ IN POOL_TYPE PoolType)
+{
+ ULONG Hash, i = 0;
+ PVOID OldVa;
+ KIRQL OldIrql;
+ SIZE_T TableSize;
+ PPOOL_TRACKER_BIG_PAGES Entry, EntryEnd, EntryStart;
+ ASSERT(((ULONG_PTR)Va & POOL_BIG_TABLE_ENTRY_FREE) == 0);
+ ASSERT(!(PoolType & SESSION_POOL_MASK));
+
+ //
+ // As the table is expandable, these values must only be read after acquiring
+ // the lock to avoid a teared access during an expansion
+ //
+ Hash = ExpComputePartialHashForAddress(Va);
+ KeAcquireSpinLock(&ExpLargePoolTableLock, &OldIrql);
+ Hash &= PoolBigPageTableHash;
+ TableSize = PoolBigPageTableSize;
+
+ //
+ // We loop from the current hash bucket to the end of the table, and then
+ // rollover to hash bucket 0 and keep going from there. If we return back
+ // to the beginning, then we attempt expansion at the bottom of the loop
+ //
+ EntryStart = Entry = &PoolBigPageTable[Hash];
+ EntryEnd = &PoolBigPageTable[TableSize];
+ do
+ {
+ //
+ // Make sure that this is a free entry and attempt to atomically make the
+ // entry busy now
+ //
+ OldVa = Entry->Va;
+ if (((ULONG_PTR)OldVa & POOL_BIG_TABLE_ENTRY_FREE) &&
+ (InterlockedCompareExchangePointer(&Entry->Va, Va, OldVa) == OldVa))
+ {
+ //
+ // We now own this entry, write down the size and the pool tag
+ //
+ Entry->Key = Key;
+ Entry->NumberOfPages = NumberOfPages;
+
+ //
+ // Add one more entry to the count, and see if we're getting within
+ // 25% of the table size, at which point we'll do an expansion now
+ // to avoid blocking too hard later on.
+ //
+ // Note that we only do this if it's also been the 16th time that we
+ // keep losing the race or that we are not finding a free entry anymore,
+ // which implies a massive number of concurrent big pool allocations.
+ //
+ InterlockedIncrement(&ExpPoolBigEntriesInUse);
+ if ((i >= 16) && (ExpPoolBigEntriesInUse > (TableSize / 4)))
+ {
+ DPRINT1("Should attempt expansion since we now have %d entries\n",
+ ExpPoolBigEntriesInUse);
+ }
+
+ //
+ // We have our entry, return
+ //
+ KeReleaseSpinLock(&ExpLargePoolTableLock, OldIrql);
+ return TRUE;
+ }
+
+ //
+ // We don't have our entry yet, so keep trying, making the entry list
+ // circular if we reach the last entry. We'll eventually break out of
+ // the loop once we've rolled over and returned back to our original
+ // hash bucket
+ //
+ i++;
+ if (++Entry >= EntryEnd) Entry = &PoolBigPageTable[0];
+ } while (Entry != EntryStart);
+
+ //
+ // This means there's no free hash buckets whatsoever, so we would now have
+ // to attempt expanding the table
+ //
+ DPRINT1("Big pool expansion needed, not implemented!");
+ KeReleaseSpinLock(&ExpLargePoolTableLock, OldIrql);
+ return FALSE;
+}
+
+ULONG
+NTAPI
+ExpFindAndRemoveTagBigPages(IN PVOID Va,
+ OUT PULONG BigPages,
+ IN POOL_TYPE PoolType)
+{
+ BOOLEAN FirstTry = TRUE;
+ SIZE_T TableSize;
+ KIRQL OldIrql;
+ ULONG PoolTag, Hash;
+ PPOOL_TRACKER_BIG_PAGES Entry;
+ ASSERT(((ULONG_PTR)Va & POOL_BIG_TABLE_ENTRY_FREE) == 0);
+ ASSERT(!(PoolType & SESSION_POOL_MASK));
+
+ //
+ // As the table is expandable, these values must only be read after acquiring
+ // the lock to avoid a teared access during an expansion
+ //
+ Hash = ExpComputePartialHashForAddress(Va);
+ KeAcquireSpinLock(&ExpLargePoolTableLock, &OldIrql);
+ Hash &= PoolBigPageTableHash;
+ TableSize = PoolBigPageTableSize;
+
+ //
+ // Loop while trying to find this big page allocation
+ //
+ while (PoolBigPageTable[Hash].Va != Va)
+ {
+ //
+ // Increment the size until we go past the end of the table
+ //
+ if (++Hash >= TableSize)
+ {
+ //
+ // Is this the second time we've tried?
+ //
+ if (!FirstTry)
+ {
+ //
+ // This means it was never inserted into the pool table and it
+ // received the special "BIG" tag -- return that and return 0
+ // so that the code can ask Mm for the page count instead
+ //
+ KeReleaseSpinLock(&ExpLargePoolTableLock, OldIrql);
+ *BigPages = 0;
+ return ' GIB';
+ }
+
+ //
+ // The first time this happens, reset the hash index and try again
+ //
+ Hash = 0;
+ FirstTry = FALSE;
+ }
+ }
+
+ //
+ // Now capture all the information we need from the entry, since after we
+ // release the lock, the data can change
+ //
+ Entry = &PoolBigPageTable[Hash];
+ *BigPages = Entry->NumberOfPages;
+ PoolTag = Entry->Key;
+
+ //
+ // Set the free bit, and decrement the number of allocations. Finally, release
+ // the lock and return the tag that was located
+ //
+ InterlockedIncrement((PLONG)&Entry->Va);
+ InterlockedDecrement(&ExpPoolBigEntriesInUse);
+ KeReleaseSpinLock(&ExpLargePoolTableLock, OldIrql);
+ return PoolTag;
+}
+
/* PUBLIC FUNCTIONS ***********************************************************/
/*
@@ -1169,9 +1354,18 @@
if (NumberOfBytes > POOL_MAX_ALLOC)
{
//
- // Then just return the number of pages requested
- //
- return MiAllocatePoolPages(PoolType, NumberOfBytes);
+ // Allocate pages for it
+ //
+ Entry = MiAllocatePoolPages(PoolType, NumberOfBytes);
+ if (!Entry) return NULL;
+
+ //
+ // Add a tag for the big page allocation and switch to the generic "BIG"
+ // tag if we failed to do so, then insert a tracker for this alloation.
+ //
+ if (!ExpAddTagForBigPages(Entry, Tag, BYTES_TO_PAGES(NumberOfBytes), PoolType)) Tag = ' GIB';
+ ExpInsertPoolTracker(Tag, ROUND_TO_PAGES(NumberOfBytes), PoolType);
+ return Entry;
}
//
@@ -1465,6 +1659,7 @@
PPOOL_DESCRIPTOR PoolDesc;
ULONG Tag;
BOOLEAN Combined = FALSE;
+ PFN_NUMBER PageCount;
//
// Check if it was allocated from a special pool
@@ -1479,10 +1674,40 @@
}
//
- // Quickly deal with big page allocations
+ // Check if this is a big page allocation
//
if (PAGE_ALIGN(P) == P)
{
+ //
+ // We need to find the tag for it, so first we need to find out what
+ // kind of allocation this was (paged or nonpaged), then we can go
+ // ahead and try finding the tag for it. Remember to get rid of the
+ // PROTECTED_POOL tag if it's found.
+ //
+ // Note that if at insertion time, we failed to add the tag for a big
+ // pool allocation, we used a special tag called 'BIG' to identify the
+ // allocation, and we may get this tag back. In this scenario, we must
+ // manually get the size of the allocation by actually counting through
+ // the PFN database.
+ //
+ PoolType = MmDeterminePoolType(P);
+ Tag = ExpFindAndRemoveTagBigPages(P, &PageCount, PoolType);
+ if (!Tag)
+ {
+ DPRINT1("We do not know the size of this allocation. This is not yet supported\n");
+ ASSERT(Tag == ' GIB');
+ PageCount = 1; // We are going to lie! This might screw up accounting?
+ }
+ else if (Tag & PROTECTED_POOL)
+ {
+ Tag &= ~PROTECTED_POOL;
+ }
+
+ //
+ // We have our tag and our page count, so we can go ahead and remove this
+ // tracker now
+ //
+ ExpRemovePoolTracker(Tag, PageCount << PAGE_SHIFT, PoolType);
MiFreePoolPages(P);
return;
}
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sun Feb 26 05:53:53 2012
@@ -1443,6 +1443,12 @@
IN ULONG_PTR Vpn
);
+POOL_TYPE
+NTAPI
+MmDeterminePoolType(
+ IN PVOID PoolAddress
+);
+
//
// MiRemoveZeroPage will use inline code to zero out the page manually if only
// free pages are available. In some scenarios, we don't/can't run that piece of
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pool.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pool.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pool.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pool.c [iso-8859-1] Sun Feb 26 05:53:53 2012
@@ -367,6 +367,17 @@
MiInitializeSystemPtes(PointerPte + 1,
MiExpansionPoolPagesInitialCharge,
NonPagedPoolExpansion);
+}
+
+POOL_TYPE
+NTAPI
+MmDeterminePoolType(IN PVOID PoolAddress)
+{
+ //
+ // Use a simple bounds check
+ //
+ return (PoolAddress >= MmPagedPoolStart) && (PoolAddress <= MmPagedPoolEnd) ?
+ PagedPool : NonPagedPool;
}
PVOID
Author: sir_richard
Date: Sat Feb 25 23:14:37 2012
New Revision: 55872
URL: http://svn.reactos.org/svn/reactos?rev=55872&view=rev
Log:
[NTOS]: Implement pool tag tracking and pool tag querying. Big Pool tags are not yet supported, but will be shortly. Expansion is not yet supported.
Modified:
trunk/reactos/ntoskrnl/ex/sysinfo.c
trunk/reactos/ntoskrnl/include/internal/ex.h
trunk/reactos/ntoskrnl/mm/ARM3/expool.c
trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
Modified: trunk/reactos/ntoskrnl/ex/sysinfo.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/sysinfo.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ex/sysinfo.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ex/sysinfo.c [iso-8859-1] Sat Feb 25 23:14:37 2012
@@ -1239,9 +1239,8 @@
/* Class 22 - Pool Tag Information */
QSI_DEF(SystemPoolTagInformation)
{
- /* FIXME */
- DPRINT1("NtQuerySystemInformation - SystemPoolTagInformation not implemented\n");
- return STATUS_NOT_IMPLEMENTED;
+ if (Size < sizeof(SYSTEM_POOLTAG_INFORMATION)) return STATUS_INFO_LENGTH_MISMATCH;
+ return ExGetPoolTagInfo(Buffer, Size, ReqSize);
}
/* Class 23 - Interrupt Information for all processors */
Modified: trunk/reactos/ntoskrnl/include/internal/ex.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ex.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ex.h [iso-8859-1] Sat Feb 25 23:14:37 2012
@@ -130,6 +130,14 @@
#define ExpChangePushlock(x, y, z) InterlockedCompareExchangePointer((PVOID*)x, (PVOID)y, (PVOID)z)
#define ExpSetRundown(x, y) InterlockedExchangePointer(&x->Ptr, (PVOID)y)
+NTSTATUS
+NTAPI
+ExGetPoolTagInfo(
+ IN PSYSTEM_POOLTAG_INFORMATION SystemInformation,
+ IN ULONG SystemInformationLength,
+ IN OUT PULONG ReturnLength OPTIONAL
+);
+
/* INITIALIZATION FUNCTIONS *************************************************/
VOID
Modified: trunk/reactos/ntoskrnl/mm/ARM3/expool.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/expool.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/expool.c [iso-8859-1] Sat Feb 25 23:14:37 2012
@@ -20,6 +20,14 @@
/* GLOBALS ********************************************************************/
+typedef struct _POOL_DPC_CONTEXT
+{
+ PPOOL_TRACKER_TABLE PoolTrackTable;
+ SIZE_T PoolTrackTableSize;
+ PPOOL_TRACKER_TABLE PoolTrackTableExpansion;
+ SIZE_T PoolTrackTableSizeExpansion;
+} POOL_DPC_CONTEXT, *PPOOL_DPC_CONTEXT;
+
ULONG ExpNumberOfPagedPools;
POOL_DESCRIPTOR NonPagedPoolDescriptor;
PPOOL_DESCRIPTOR ExpPagedPoolDescriptor[16 + 1];
@@ -27,8 +35,11 @@
PKGUARDED_MUTEX ExpPagedPoolMutex;
SIZE_T PoolTrackTableSize, PoolTrackTableMask;
SIZE_T PoolBigPageTableSize, PoolBigPageTableHash;
-PPOOL_TRACKER_TABLE PoolTrackTable, PoolBigPageTable;
+PPOOL_TRACKER_TABLE PoolTrackTable;
+PPOOL_TRACKER_BIG_PAGES PoolBigPageTable;
KSPIN_LOCK ExpTaggedPoolLock;
+ULONG PoolHitTag;
+BOOLEAN ExStopBadTags;
/* Pool block/header/list access macros */
#define POOL_ENTRY(x) (PPOOL_HEADER)((ULONG_PTR)(x) - sizeof(POOL_HEADER))
@@ -286,7 +297,344 @@
}
}
+FORCEINLINE
+ULONG
+ExpComputeHashForTag(IN ULONG Tag,
+ IN SIZE_T BucketMask)
+{
+ //
+ // Compute the hash by multiplying with a large prime number and then XORing
+ // with the HIDWORD of the result.
+ //
+ // Finally, AND with the bucket mask to generate a valid index/bucket into
+ // the table
+ //
+ ULONGLONG Result = 40543 * Tag;
+ return BucketMask & (Result ^ (Result >> 32));
+}
+
/* PRIVATE FUNCTIONS **********************************************************/
+
+VOID
+NTAPI
+INIT_FUNCTION
+ExpSeedHotTags(VOID)
+{
+ ULONG i, Key, Hash, Index;
+ PPOOL_TRACKER_TABLE TrackTable = PoolTrackTable;
+ ULONG TagList[] =
+ {
+ ' oI',
+ ' laH',
+ 'PldM',
+ 'LooP',
+ 'tSbO',
+ ' prI',
+ 'bdDN',
+ 'LprI',
+ 'pOoI',
+ ' ldM',
+ 'eliF',
+ 'aVMC',
+ 'dSeS',
+ 'CFtN',
+ 'looP',
+ 'rPCT',
+ 'bNMC',
+ 'dTeS',
+ 'sFtN',
+ 'TPCT',
+ 'CPCT',
+ ' yeK',
+ 'qSbO',
+ 'mNoI',
+ 'aEoI',
+ 'cPCT',
+ 'aFtN',
+ '0ftN',
+ 'tceS',
+ 'SprI',
+ 'ekoT',
+ ' eS',
+ 'lCbO',
+ 'cScC',
+ 'lFtN',
+ 'cAeS',
+ 'mfSF',
+ 'kWcC',
+ 'miSF',
+ 'CdfA',
+ 'EdfA',
+ 'orSF',
+ 'nftN',
+ 'PRIU',
+ 'rFpN',
+ 'RFpN',
+ 'aPeS',
+ 'sUeS',
+ 'FpcA',
+ 'MpcA',
+ 'cSeS',
+ 'mNbO',
+ 'sFpN',
+ 'uLeS',
+ 'DPcS',
+ 'nevE',
+ 'vrqR',
+ 'ldaV',
+ ' pP',
+ 'SdaV',
+ ' daV',
+ 'LdaV',
+ 'FdaV',
+ ' GIB',
+ };
+
+ //
+ // Loop all 64 hot tags
+ //
+ ASSERT((sizeof(TagList) / sizeof(ULONG)) == 64);
+ for (i = 0; i < sizeof(TagList) / sizeof(ULONG); i++)
+ {
+ //
+ // Get the current tag, and compute its hash in the tracker table
+ //
+ Key = TagList[i];
+ Hash = ExpComputeHashForTag(Key, PoolTrackTableMask);
+
+ //
+ // Loop all the hashes in this index/bucket
+ //
+ Index = Hash;
+ while (TRUE)
+ {
+ //
+ // Find an empty entry, and make sure this isn't the last hash that
+ // can fit.
+ //
+ // On checked builds, also make sure this is the first time we are
+ // seeding this tag.
+ //
+ ASSERT(TrackTable[Hash].Key != Key);
+ if (!(TrackTable[Hash].Key) && (Hash != PoolTrackTableSize - 1))
+ {
+ //
+ // It has been seeded, move on to the next tag
+ //
+ TrackTable[Hash].Key = Key;
+ break;
+ }
+
+ //
+ // This entry was already taken, compute the next possible hash while
+ // making sure we're not back at our initial index.
+ //
+ ASSERT(TrackTable[Hash].Key != Key);
+ Hash = (Hash + 1) & PoolTrackTableMask;
+ if (Hash == Index) break;
+ }
+ }
+}
+
+VOID
+NTAPI
+ExpRemovePoolTracker(IN ULONG Key,
+ IN SIZE_T NumberOfBytes,
+ IN POOL_TYPE PoolType)
+{
+ ULONG Hash, Index;
+ PPOOL_TRACKER_TABLE Table, TableEntry;
+ SIZE_T TableMask, TableSize;
+
+ //
+ // Remove the PROTECTED_POOL flag which is not part of the tag
+ //
+ Key &= ~PROTECTED_POOL;
+
+ //
+ // With WinDBG you can set a tag you want to break on when an allocation is
+ // attempted
+ //
+ if (Key == PoolHitTag) DbgBreakPoint();
+
+ //
+ // Why the double indirection? Because normally this function is also used
+ // when doing session pool allocations, which has another set of tables,
+ // sizes, and masks that live in session pool. Now we don't support session
+ // pool so we only ever use the regular tables, but I'm keeping the code this
+ // way so that the day we DO support session pool, it won't require that
+ // many changes
+ //
+ Table = PoolTrackTable;
+ TableMask = PoolTrackTableMask;
+ TableSize = PoolTrackTableSize;
+
+ //
+ // Compute the hash for this key, and loop all the possible buckets
+ //
+ Hash = ExpComputeHashForTag(Key, TableMask);
+ Index = Hash;
+ while (TRUE)
+ {
+ //
+ // Have we found the entry for this tag? */
+ //
+ TableEntry = &Table[Hash];
+ if (TableEntry->Key == Key)
+ {
+ //
+ // Decrement the counters depending on if this was paged or nonpaged
+ // pool
+ //
+ if ((PoolType & BASE_POOL_TYPE_MASK) == NonPagedPool)
+ {
+ InterlockedIncrement(&TableEntry->NonPagedFrees);
+ InterlockedExchangeAddSizeT(&TableEntry->NonPagedBytes, -NumberOfBytes);
+ return;
+ }
+ InterlockedIncrement(&TableEntry->PagedFrees);
+ InterlockedExchangeAddSizeT(&TableEntry->PagedBytes, -NumberOfBytes);
+ return;
+ }
+
+ //
+ // We should have only ended up with an empty entry if we've reached
+ // the last bucket
+ //
+ if (!TableEntry->Key) ASSERT(Hash == TableMask);
+
+ //
+ // This path is hit when we don't have an entry, and the current bucket
+ // is full, so we simply try the next one
+ //
+ Hash = (Hash + 1) & TableMask;
+ if (Hash == Index) break;
+ }
+
+ //
+ // And finally this path is hit when all the buckets are full, and we need
+ // some expansion. This path is not yet supported in ReactOS and so we'll
+ // ignore the tag
+ //
+ DPRINT1("Out of pool tag space, ignoring...\n");
+}
+
+VOID
+NTAPI
+ExpInsertPoolTracker(IN ULONG Key,
+ IN SIZE_T NumberOfBytes,
+ IN POOL_TYPE PoolType)
+{
+ ULONG Hash, Index;
+ KIRQL OldIrql;
+ PPOOL_TRACKER_TABLE Table, TableEntry;
+ SIZE_T TableMask, TableSize;
+
+ //
+ // Remove the PROTECTED_POOL flag which is not part of the tag
+ //
+ Key &= ~PROTECTED_POOL;
+
+ //
+ // With WinDBG you can set a tag you want to break on when an allocation is
+ // attempted
+ //
+ if (Key == PoolHitTag) DbgBreakPoint();
+
+ //
+ // There is also an internal flag you can set to break on malformed tags
+ //
+ if (ExStopBadTags) ASSERT(Key & 0xFFFFFF00);
+
+ //
+ // ASSERT on ReactOS features not yet supported
+ //
+ ASSERT(!(PoolType & SESSION_POOL_MASK));
+ ASSERT(KeGetCurrentProcessorNumber() == 0);
+
+ //
+ // Why the double indirection? Because normally this function is also used
+ // when doing session pool allocations, which has another set of tables,
+ // sizes, and masks that live in session pool. Now we don't support session
+ // pool so we only ever use the regular tables, but I'm keeping the code this
+ // way so that the day we DO support session pool, it won't require that
+ // many changes
+ //
+ Table = PoolTrackTable;
+ TableMask = PoolTrackTableMask;
+ TableSize = PoolTrackTableSize;
+
+ //
+ // Compute the hash for this key, and loop all the possible buckets
+ //
+ Hash = ExpComputeHashForTag(Key, TableMask);
+ Index = Hash;
+ while (TRUE)
+ {
+ //
+ // Do we already have an entry for this tag? */
+ //
+ TableEntry = &Table[Hash];
+ if (TableEntry->Key == Key)
+ {
+ //
+ // Increment the counters depending on if this was paged or nonpaged
+ // pool
+ //
+ if ((PoolType & BASE_POOL_TYPE_MASK) == NonPagedPool)
+ {
+ InterlockedIncrement(&TableEntry->NonPagedAllocs);
+ InterlockedExchangeAddSizeT(&TableEntry->NonPagedBytes, NumberOfBytes);
+ return;
+ }
+ InterlockedIncrement(&TableEntry->PagedAllocs);
+ InterlockedExchangeAddSizeT(&TableEntry->PagedBytes, NumberOfBytes);
+ return;
+ }
+
+ //
+ // We don't have an entry yet, but we've found a free bucket for it
+ //
+ if (!(TableEntry->Key) && (Hash != PoolTrackTableSize - 1))
+ {
+ //
+ // We need to hold the lock while creating a new entry, since other
+ // processors might be in this code path as well
+ //
+ ExAcquireSpinLock(&ExpTaggedPoolLock, &OldIrql);
+ if (!PoolTrackTable[Hash].Key)
+ {
+ //
+ // We've won the race, so now create this entry in the bucket
+ //
+ ASSERT(Table[Hash].Key == 0);
+ PoolTrackTable[Hash].Key = Key;
+ TableEntry->Key = Key;
+ }
+ ExReleaseSpinLock(&ExpTaggedPoolLock, OldIrql);
+
+ //
+ // Now we force the loop to run again, and we should now end up in
+ // the code path above which does the interlocked increments...
+ //
+ continue;
+ }
+
+ //
+ // This path is hit when we don't have an entry, and the current bucket
+ // is full, so we simply try the next one
+ //
+ Hash = (Hash + 1) & TableMask;
+ if (Hash == Index) break;
+ }
+
+ //
+ // And finally this path is hit when all the buckets are full, and we need
+ // some expansion. This path is not yet supported in ReactOS and so we'll
+ // ignore the tag
+ //
+ DPRINT1("Out of pool tag space, ignoring...\n");
+}
VOID
NTAPI
@@ -499,6 +847,7 @@
PoolBigPageTableHash = PoolBigPageTableSize - 1;
RtlZeroMemory(PoolBigPageTable,
PoolBigPageTableSize * sizeof(POOL_TRACKER_BIG_PAGES));
+ for (i = 0; i < PoolBigPageTableSize; i++) PoolBigPageTable[i].Va = (PVOID)1;
//
// During development, print this out so we can see what's happening
@@ -507,6 +856,14 @@
PoolTrackTable, PoolTrackTableSize * sizeof(POOL_TRACKER_TABLE));
DPRINT1("EXPOOL: Big Pool Tracker Table at: 0x%p with 0x%lx bytes\n",
PoolBigPageTable, PoolBigPageTableSize * sizeof(POOL_TRACKER_BIG_PAGES));
+
+ //
+ // Insert the generic tracker for all of big pool
+ //
+ ExpInsertPoolTracker('looP',
+ ROUND_TO_PAGES(PoolBigPageTableSize *
+ sizeof(POOL_TRACKER_BIG_PAGES)),
+ NonPagedPool);
//
// No support for NUMA systems at this time
@@ -565,6 +922,13 @@
0,
Threshold,
ExpPagedPoolMutex);
+
+ //
+ // Insert the generic tracker for all of nonpaged pool
+ //
+ ExpInsertPoolTracker('looP',
+ ROUND_TO_PAGES(PoolTrackTableSize * sizeof(POOL_TRACKER_TABLE)),
+ NonPagedPool);
}
}
@@ -614,6 +978,146 @@
//
KeReleaseGuardedMutex(Descriptor->LockAddress);
}
+}
+
+VOID
+NTAPI
+ExpGetPoolTagInfoTarget(IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2)
+{
+ PPOOL_DPC_CONTEXT Context = DeferredContext;
+ UNREFERENCED_PARAMETER(Dpc);
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ //
+ // Make sure we win the race, and if we did, copy the data atomically
+ //
+ if (KeSignalCallDpcSynchronize(SystemArgument2))
+ {
+ RtlCopyMemory(Context->PoolTrackTable,
+ PoolTrackTable,
+ Context->PoolTrackTableSize * sizeof(POOL_TRACKER_TABLE));
+
+ //
+ // This is here because ReactOS does not yet support expansion
+ //
+ ASSERT(Context->PoolTrackTableSizeExpansion == 0);
+ }
+
+ //
+ // Regardless of whether we won or not, we must now synchronize and then
+ // decrement the barrier since this is one more processor that has completed
+ // the callback.
+ //
+ KeSignalCallDpcSynchronize(SystemArgument2);
+ KeSignalCallDpcDone(SystemArgument1);
+}
+
+NTSTATUS
+NTAPI
+ExGetPoolTagInfo(IN PSYSTEM_POOLTAG_INFORMATION SystemInformation,
+ IN ULONG SystemInformationLength,
+ IN OUT PULONG ReturnLength OPTIONAL)
+{
+ SIZE_T TableSize, CurrentLength;
+ ULONG EntryCount;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PSYSTEM_POOLTAG TagEntry;
+ PPOOL_TRACKER_TABLE Buffer, TrackerEntry;
+ POOL_DPC_CONTEXT Context;
+ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+ //
+ // Keep track of how much data the caller's buffer must hold
+ //
+ CurrentLength = FIELD_OFFSET(SYSTEM_POOLTAG_INFORMATION, TagInfo);
+
+ //
+ // Initialize the caller's buffer
+ //
+ TagEntry = &SystemInformation->TagInfo[0];
+ SystemInformation->Count = 0;
+
+ //
+ // Capture the number of entries, and the total size needed to make a copy
+ // of the table
+ //
+ EntryCount = PoolTrackTableSize;
+ TableSize = EntryCount * sizeof(POOL_TRACKER_TABLE);
+
+ //
+ // Allocate the "Generic DPC" temporary buffer
+ //
+ Buffer = ExAllocatePoolWithTag(NonPagedPool, TableSize, 'ofnI');
+ if (!Buffer) return STATUS_INSUFFICIENT_RESOURCES;
+
+ //
+ // Do a "Generic DPC" to atomically retrieve the tag and allocation data
+ //
+ Context.PoolTrackTable = Buffer;
+ Context.PoolTrackTableSize = PoolTrackTableSize;
+ Context.PoolTrackTableExpansion = NULL;
+ Context.PoolTrackTableSizeExpansion = 0;
+ KeGenericCallDpc(ExpGetPoolTagInfoTarget, &Context);
+
+ //
+ // Now parse the results
+ //
+ for (TrackerEntry = Buffer; TrackerEntry < (Buffer + EntryCount); TrackerEntry++)
+ {
+ //
+ // If the entry is empty, skip it
+ //
+ if (!TrackerEntry->Key) continue;
+
+ //
+ // Otherwise, add one more entry to the caller's buffer, and ensure that
+ // enough space has been allocated in it
+ //
+ SystemInformation->Count++;
+ CurrentLength += sizeof(*TagEntry);
+ if (SystemInformationLength < CurrentLength)
+ {
+ //
+ // The caller's buffer is too small, so set a failure code. The
+ // caller will know the count, as well as how much space is needed.
+ //
+ // We do NOT break out of the loop, because we want to keep incrementing
+ // the Count as well as CurrentLength so that the caller can know the
+ // final numbers
+ //
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ }
+ else
+ {
+ //
+ // Small sanity check that our accounting is working correctly
+ //
+ ASSERT(TrackerEntry->PagedAllocs >= TrackerEntry->PagedFrees);
+ ASSERT(TrackerEntry->NonPagedAllocs >= TrackerEntry->NonPagedFrees);
+
+ //
+ // Return the data into the caller's buffer
+ //
+ TagEntry->TagUlong = TrackerEntry->Key;
+ TagEntry->PagedAllocs = TrackerEntry->PagedAllocs;
+ TagEntry->PagedFrees = TrackerEntry->PagedFrees;
+ TagEntry->PagedUsed = TrackerEntry->PagedBytes;
+ TagEntry->NonPagedAllocs = TrackerEntry->NonPagedAllocs;
+ TagEntry->NonPagedFrees = TrackerEntry->NonPagedFrees;
+ TagEntry->NonPagedUsed = TrackerEntry->NonPagedBytes;
+ TagEntry++;
+ }
+ }
+
+ //
+ // Free the "Generic DPC" temporary buffer, return the buffer length and status
+ //
+ ExFreePool(Buffer);
+ if (ReturnLength) *ReturnLength = CurrentLength;
+ return Status;
}
/* PUBLIC FUNCTIONS ***********************************************************/
@@ -852,6 +1356,13 @@
ExUnlockPool(PoolDesc, OldIrql);
//
+ // Track this allocation
+ //
+ ExpInsertPoolTracker(Tag,
+ Entry->BlockSize * POOL_BLOCK_SIZE,
+ PoolType);
+
+ //
// Return the pool allocation
//
Entry->PoolTag = Tag;
@@ -865,8 +1376,7 @@
// There were no free entries left, so we have to allocate a new fresh page
//
Entry = MiAllocatePoolPages(PoolType, PAGE_SIZE);
- if (Entry == NULL)
- return NULL;
+ if (Entry == NULL) return NULL;
Entry->Ulong1 = 0;
Entry->BlockSize = i;
@@ -912,6 +1422,13 @@
}
//
+ // Track this allocation
+ //
+ ExpInsertPoolTracker(Tag,
+ Entry->BlockSize * POOL_BLOCK_SIZE,
+ PoolType);
+
+ //
// And return the pool allocation
//
ExpCheckPoolBlocks(Entry);
@@ -946,6 +1463,7 @@
KIRQL OldIrql;
POOL_TYPE PoolType;
PPOOL_DESCRIPTOR PoolDesc;
+ ULONG Tag;
BOOLEAN Combined = FALSE;
//
@@ -983,6 +1501,19 @@
BlockSize = Entry->BlockSize;
PoolType = (Entry->PoolType - 1) & BASE_POOL_TYPE_MASK;
PoolDesc = PoolVector[PoolType];
+
+ //
+ // Get the pool tag and get rid of the PROTECTED_POOL flag
+ //
+ Tag = Entry->PoolTag;
+ if (Tag & PROTECTED_POOL) Tag &= ~PROTECTED_POOL;
+
+ //
+ // Stop tracking this allocation
+ //
+ ExpRemovePoolTracker(Tag,
+ BlockSize * POOL_BLOCK_SIZE,
+ Entry->PoolType - 1);
//
// Get the pointer to the next entry
Modified: trunk/reactos/ntoskrnl/mm/ARM3/miarm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/miarm.h?r…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/miarm.h [iso-8859-1] Sat Feb 25 23:14:37 2012
@@ -348,11 +348,11 @@
typedef struct _POOL_TRACKER_TABLE
{
ULONG Key;
- ULONG NonPagedAllocs;
- ULONG NonPagedFrees;
+ LONG NonPagedAllocs;
+ LONG NonPagedFrees;
SIZE_T NonPagedBytes;
- ULONG PagedAllocs;
- ULONG PagedFrees;
+ LONG PagedAllocs;
+ LONG PagedFrees;
SIZE_T PagedBytes;
} POOL_TRACKER_TABLE, *PPOOL_TRACKER_TABLE;
Author: cgutman
Date: Sat Feb 25 22:27:27 2012
New Revision: 55871
URL: http://svn.reactos.org/svn/reactos?rev=55871&view=rev
Log:
[NTOSKRNL]
- Set the SYNCHRONIZE flag in desired access when opening a registry hive for synchronous I/O
Modified:
trunk/reactos/ntoskrnl/config/cminit.c
Modified: trunk/reactos/ntoskrnl/config/cminit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/config/cminit.c?r…
==============================================================================
--- trunk/reactos/ntoskrnl/config/cminit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/config/cminit.c [iso-8859-1] Sat Feb 25 22:27:27 2012
@@ -334,7 +334,7 @@
/* Now create the file */
Status = ZwCreateFile(Primary,
- DesiredAccess,
+ DesiredAccess | SYNCHRONIZE,
&ObjectAttributes,
&IoStatusBlock,
NULL,