- Removed the hole pool allocation, because it needs to much memory and ros will not boot. - Allocate short blocks in one page. - Split the used and free header. It makes it easier to implement a red zone check. Modified: trunk/reactos/ntoskrnl/mm/npool.c _____
Modified: trunk/reactos/ntoskrnl/mm/npool.c --- trunk/reactos/ntoskrnl/mm/npool.c 2005-08-11 20:23:13 UTC (rev 17305) +++ trunk/reactos/ntoskrnl/mm/npool.c 2005-08-11 20:29:08 UTC (rev 17306) @@ -8,6 +8,7 @@
* PROGRAMMERS: David Welch (welch@cwcom.net) * Iwan Fatahi (i_fatahi@hotmail.com) * Robert Bergkvist (fragdance@hotmail.com) + * Hartmut Birr */
/* INCLUDES ****************************************************************/ @@ -54,38 +55,33 @@ /* * fields present at the start of a block (this is for internal use only) */ -typedef struct _BLOCK_HDR +typedef struct _HDR { - ULONG Magic; - ULONG Size; - struct _BLOCK_HDR* previous; - union - { - struct - { - LIST_ENTRY ListEntry; - ULONG Tag; - PVOID Caller; - LIST_ENTRY TagListEntry; - BOOLEAN Dumped; - } - Used; - struct - { - NODE Node; - } - Free; - }; -} -BLOCK_HDR; + ULONG Magic; + ULONG Size; + struct _HDR* previous; +} HDR, *PHDR;
-#define BLOCK_HDR_SIZE ROUND_UP(sizeof(BLOCK_HDR), MM_POOL_ALIGNMENT) +typedef struct _HDR_USED +{ + HDR hdr; + LIST_ENTRY ListEntry; + ULONG Tag; + PVOID Caller; + LIST_ENTRY TagListEntry; + BOOLEAN Dumped; +} HDR_USED, *PHDR_USED;
-PVOID STDCALL -ExAllocateWholePageBlock(ULONG Size); -VOID STDCALL -ExFreeWholePageBlock(PVOID Addr); +typedef struct _HDR_FREE +{ + HDR hdr; + NODE Node; +} HDR_FREE, *PHDR_FREE;
+#define HDR_FREE_SIZE ROUND_UP(sizeof(HDR_FREE), MM_POOL_ALIGNMENT) +#define HDR_USED_SIZE ROUND_UP(sizeof(HDR_USED), MM_POOL_ALIGNMENT) + + /* GLOBALS *****************************************************************/
extern PVOID MiNonPagedPoolStart; @@ -103,7 +99,6 @@
static LIST_ENTRY AddressListHead;
-#ifndef WHOLE_PAGE_ALLOCATIONS /* * Count of free blocks */ @@ -113,7 +108,6 @@ * Count of used blocks */ static ULONG EiNrUsedBlocks = 0; -#endif
/* * Lock that protects the non-paged pool data structures @@ -147,29 +141,23 @@ static LIST_ENTRY tag_hash_table[TAG_HASH_TABLE_SIZE]; #endif /* TAG_STATISTICS_TRACKING */
-#ifdef WHOLE_PAGE_ALLOCATIONS -static RTL_BITMAP NonPagedPoolAllocMap; -static ULONG NonPagedPoolAllocMapHint; -static ULONG MiCurrentNonPagedPoolLength = 0; -#else static PULONG MiNonPagedPoolAllocMap; static ULONG MiNonPagedPoolNrOfPages; -#endif /* WHOLE_PAGE_ALLOCATIONS */
/* avl helper functions ****************************************************/
void DumpFreeBlockNode(PNODE p) { static int count = 0; - BLOCK_HDR* blk; + HDR_FREE* blk;
count++;
if (p) { DumpFreeBlockNode(p->link[0]); - blk = CONTAINING_RECORD(p, BLOCK_HDR, Free.Node); - DbgPrint("%08x %8d (%d)\n", blk, blk->Size, count); + blk = CONTAINING_RECORD(p, HDR_FREE, Node); + DbgPrint("%08x %8d (%d)\n", blk, blk->hdr.Size, count); DumpFreeBlockNode(p->link[1]); }
@@ -178,17 +166,17 @@ void DumpFreeBlockTree(void) { DbgPrint("--- Begin tree ------------------\n"); - DbgPrint("%08x\n", CONTAINING_RECORD(FreeBlockListRoot, BLOCK_HDR, Free.Node)); + DbgPrint("%08x\n", CONTAINING_RECORD(FreeBlockListRoot, HDR_FREE, Node)); DumpFreeBlockNode(FreeBlockListRoot); DbgPrint("--- End tree --------------------\n"); }
int compare_node(PNODE p1, PNODE p2) { - BLOCK_HDR* blk1 = CONTAINING_RECORD(p1, BLOCK_HDR, Free.Node); - BLOCK_HDR* blk2 = CONTAINING_RECORD(p2, BLOCK_HDR, Free.Node); + HDR_FREE* blk1 = CONTAINING_RECORD(p1, HDR_FREE, Node); + HDR_FREE* blk2 = CONTAINING_RECORD(p2, HDR_FREE, Node);
- if (blk1->Size == blk2->Size) + if (blk1->hdr.Size == blk2->hdr.Size) { if (blk1 < blk2) { @@ -201,11 +189,11 @@ } else { - if (blk1->Size < blk2->Size) + if (blk1->hdr.Size < blk2->hdr.Size) { return -1; } - if (blk1->Size > blk2->Size) + if (blk1->hdr.Size > blk2->hdr.Size) { return 1; } @@ -216,14 +204,14 @@
int compare_value(PVOID value, PNODE p) { - BLOCK_HDR* blk = CONTAINING_RECORD(p, BLOCK_HDR, Free.Node); + HDR_FREE* blk = CONTAINING_RECORD(p, HDR_FREE, Node); ULONG v = *(PULONG)value;
- if (v < blk->Size) + if (v < blk->hdr.Size) { return -1; } - if (v > blk->Size) + if (v > blk->hdr.Size) { return 1; } @@ -730,39 +718,38 @@
#ifdef TAG_STATISTICS_TRACKING VOID -MiRemoveFromTagHashTable(BLOCK_HDR* block) +MiRemoveFromTagHashTable(HDR_USED* block) /* * Remove a block from the tag hash table */ { - if (block->Used.Tag == 0) + if (block->Tag == 0) { return; } - - RemoveEntryList(&block->Used.TagListEntry); + RemoveEntryList(&block->TagListEntry); }
VOID -MiAddToTagHashTable(BLOCK_HDR* block) +MiAddToTagHashTable(HDR_USED* block) /* * Add a block to the tag hash table */ { ULONG hash;
- if (block->Used.Tag == 0) + if (block->Tag == 0) { return; }
- hash = block->Used.Tag % TAG_HASH_TABLE_SIZE; + hash = block->Tag % TAG_HASH_TABLE_SIZE;
- InsertHeadList(&tag_hash_table[hash], &block->Used.TagListEntry); + InsertHeadList(&tag_hash_table[hash], &block->TagListEntry); } #endif /* TAG_STATISTICS_TRACKING */
-#if defined(TAG_STATISTICS_TRACKING) && !defined(WHOLE_PAGE_ALLOCATIONS) +#if defined(TAG_STATISTICS_TRACKING) VOID STATIC MiDumpTagStats(ULONG CurrentTag, ULONG CurrentNrBlocks, ULONG CurrentSize) { @@ -786,14 +773,14 @@ CurrentSize / CurrentNrBlocks); } } -#endif /* defined(TAG_STATISTICS_TRACKING) && !defined(WHOLE_PAGE_ALLOCATIONS); */ +#endif /* defined(TAG_STATISTICS_TRACKING) */
VOID MiDebugDumpNonPagedPoolStats(BOOLEAN NewOnly) { -#if defined(TAG_STATISTICS_TRACKING) && !defined(WHOLE_PAGE_ALLOCATIONS) +#if defined(TAG_STATISTICS_TRACKING) ULONG i; - BLOCK_HDR* current; + HDR_USED* current; ULONG CurrentTag; ULONG CurrentNrBlocks = 0; ULONG CurrentSize = 0; @@ -817,25 +804,25 @@ current_entry = tag_hash_table[i].Flink; while (current_entry != &tag_hash_table[i]) { - current = CONTAINING_RECORD(current_entry, BLOCK_HDR, Used.TagListEntry); + current = CONTAINING_RECORD(current_entry, HDR_USED, TagListEntry); current_entry = current_entry->Flink; if (CurrentTag == 0) { - CurrentTag = current->Used.Tag; + CurrentTag = current->Tag; CurrentNrBlocks = 0; CurrentSize = 0; } - if (current->Used.Tag == CurrentTag) + if (current->Tag == CurrentTag) { - RemoveEntryList(¤t->Used.TagListEntry); - InsertHeadList(&tmpListHead, ¤t->Used.TagListEntry); - if (!NewOnly || !current->Used.Dumped) + RemoveEntryList(¤t->TagListEntry); + InsertHeadList(&tmpListHead, ¤t->TagListEntry); + if (!NewOnly || !current->Dumped) { CurrentNrBlocks++; TotalBlocks++; - CurrentSize += current->Size; - TotalSize += current->Size; - current->Used.Dumped = TRUE; + CurrentSize += current->hdr.Size; + TotalSize += current->hdr.Size; + current->Dumped = TRUE; } } } @@ -866,14 +853,14 @@ DbgPrint("Freeblocks %d TotalFreeSize %d AverageFreeSize %d\n", EiNrFreeBlocks, Size, EiNrFreeBlocks ? Size / EiNrFreeBlocks : 0); DbgPrint("***************** Dump Complete ***************\n"); -#endif /* defined(TAG_STATISTICS_TRACKING) && !defined(WHOLE_PAGE_ALLOCATIONS) */ +#endif /* defined(TAG_STATISTICS_TRACKING) */ }
VOID MiDebugDumpNonPagedPool(BOOLEAN NewOnly) { -#if defined(POOL_DEBUG_APIS) && !defined(WHOLE_PAGE_ALLOCATIONS) - BLOCK_HDR* current; +#if defined(POOL_DEBUG_APIS) + HDR_USED* current; PLIST_ENTRY current_entry; KIRQL oldIrql;
@@ -883,45 +870,43 @@ current_entry = UsedBlockListHead.Flink; while (current_entry != &UsedBlockListHead) { - current = CONTAINING_RECORD(current_entry, BLOCK_HDR, Used.ListEntry); - if (!NewOnly || !current->Used.Dumped) + current = CONTAINING_RECORD(current_entry, HDR_USED, ListEntry); + if (!NewOnly || !current->Dumped) { CHAR c1, c2, c3, c4;
- c1 = (CHAR)((current->Used.Tag >> 24) & 0xFF); - c2 = (CHAR)((current->Used.Tag >> 16) & 0xFF); - c3 = (CHAR)((current->Used.Tag >> 8) & 0xFF); - c4 = (CHAR)(current->Used.Tag & 0xFF); + c1 = (CHAR)((current->Tag >> 24) & 0xFF); + c2 = (CHAR)((current->Tag >> 16) & 0xFF); + c3 = (CHAR)((current->Tag >> 8) & 0xFF); + c4 = (CHAR)(current->Tag & 0xFF);
if (isprint(c1) && isprint(c2) && isprint(c3) && isprint(c4)) { DbgPrint("Size 0x%x Tag 0x%x (%c%c%c%c) Allocator 0x%x\n", - current->Size, current->Used.Tag, c4, c3, c2, c1, - current->Used.Caller); + current->hdr.Size, current->Tag, c4, c3, c2, c1, + current->Caller); } else { DbgPrint("Size 0x%x Tag 0x%x Allocator 0x%x\n", - current->Size, current->Used.Tag, current->Used.Caller); + current->hdr.Size, current->Tag, current->Caller); } - current->Used.Dumped = TRUE; + current->Dumped = TRUE; } current_entry = current_entry->Flink; } DbgPrint("***************** Dump Complete ***************\n"); KeReleaseSpinLock(&MmNpoolLock, oldIrql); -#endif /* not WHOLE_PAGE_ALLOCATIONS */ +#endif }
-#ifndef WHOLE_PAGE_ALLOCATIONS - #ifdef ENABLE_VALIDATE_POOL static void validate_free_list(void) /* * FUNCTION: Validate the integrity of the list of free blocks */ { - BLOCK_HDR* current; + HDR_FREE* current; unsigned int blocks_seen=0; PNODE p;
@@ -931,10 +916,10 @@ { PVOID base_addr;
- current = CONTAINING_RECORD(p, BLOCK_HDR, Free.Node); + current = CONTAINING_RECORD(p, HDR_FREE, Node); base_addr = (PVOID)current;
- if (current->Magic != BLOCK_HDR_FREE_MAGIC) + if (current->hdr.Magic != BLOCK_HDR_FREE_MAGIC) { DbgPrint("Bad block magic (probable pool corruption) at %x\n", current); @@ -942,12 +927,12 @@ }
if (base_addr < MiNonPagedPoolStart || - base_addr + BLOCK_HDR_SIZE + current->Size > MiNonPagedPoolStart + MiNonPagedPoolLength) + (ULONG_PTR)base_addr + current->hdr.Size > (ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength) { DbgPrint("Block %x found outside pool area\n",current); - DbgPrint("Size %d\n",current->Size); + DbgPrint("Size %d\n",current->hdr.Size); DbgPrint("Limits are %x %x\n",MiNonPagedPoolStart, - MiNonPagedPoolStart+MiNonPagedPoolLength); + (ULONG_PTR)MiNonPagedPoolStart+MiNonPagedPoolLength); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); } blocks_seen++; @@ -965,7 +950,7 @@ * FUNCTION: Validate the integrity of the list of used blocks */ { - BLOCK_HDR* current; + HDR_USED* current; PLIST_ENTRY current_entry; unsigned int blocks_seen=0;
@@ -974,23 +959,23 @@ { PVOID base_addr;
- current = CONTAINING_RECORD(current_entry, BLOCK_HDR, Used.ListEntry); + current = CONTAINING_RECORD(current_entry, HDR_USED, ListEntry); base_addr = (PVOID)current;
- if (current->Magic != BLOCK_HDR_USED_MAGIC) + if (current->hdr.Magic != BLOCK_HDR_USED_MAGIC) { DbgPrint("Bad block magic (probable pool corruption) at %x\n", current); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); } if (base_addr < MiNonPagedPoolStart || - (base_addr+BLOCK_HDR_SIZE+current->Size) > - MiNonPagedPoolStart+MiNonPagedPoolLength) + ((ULONG_PTR)base_addr+current->hdr.Size) > + (ULONG_PTR)MiNonPagedPoolStart+MiNonPagedPoolLength) { DbgPrint("Block %x found outside pool area\n",current); - DbgPrint("Size %d\n",current->Size); + DbgPrint("Size %d\n",current->hdr.Size); DbgPrint("Limits are %x %x\n",MiNonPagedPoolStart, - MiNonPagedPoolStart+MiNonPagedPoolLength); + (ULONG_PTR)MiNonPagedPoolStart+MiNonPagedPoolLength); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); } blocks_seen++; @@ -999,13 +984,13 @@ DbgPrint("Too many blocks on used list\n"); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); } - if (current->Used.ListEntry.Flink != &UsedBlockListHead && - current->Used.ListEntry.Flink->Blink != ¤t->Used.ListEntry) + if (current->ListEntry.Flink != &UsedBlockListHead && + current->ListEntry.Flink->Blink != ¤t->ListEntry) { DbgPrint("%s:%d:Break in list (current %x next %x " "current->next->previous %x)\n", - __FILE__,__LINE__,current, current->Used.ListEntry.Flink, - current->Used.ListEntry.Flink->Blink); + __FILE__,__LINE__,current, current->ListEntry.Flink, + current->ListEntry.Flink->Blink); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); }
@@ -1013,7 +998,7 @@ } }
-static void check_duplicates(BLOCK_HDR* blk) +static void check_duplicates(HDR* blk) /* * FUNCTION: Check a block has no duplicates * ARGUMENTS: @@ -1021,33 +1006,32 @@ * NOTE: Bug checks if duplicates are found */ { - char* base = (char*)blk; - char* last = ((char*)blk) + BLOCK_HDR_SIZE + blk->Size; - BLOCK_HDR* current; + ULONG_PTR base = (ULONG_PTR)blk; + ULONG_PTR last = (ULONG_PTR)blk + blk->Size; PLIST_ENTRY current_entry; PNODE p; + HDR_FREE* free; + HDR_USED* used;
p = avl_get_first(FreeBlockListRoot);
while (p) { - current = CONTAINING_RECORD(p, BLOCK_HDR, Free.Node); - - if (current->Magic != BLOCK_HDR_FREE_MAGIC) + free = CONTAINING_RECORD(p, HDR_FREE, Node); + if (free->hdr.Magic != BLOCK_HDR_FREE_MAGIC) { DbgPrint("Bad block magic (probable pool corruption) at %x\n", - current); + free); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); }
- if ( (char*)current > base && (char*)current < last ) + if ( (ULONG_PTR)free > base && (ULONG_PTR)free < last ) { DbgPrint("intersecting blocks on list\n"); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); } - if ( (char*)current < base && - ((char*)current + current->Size + BLOCK_HDR_SIZE) - > base ) + if ( (ULONG_PTR)free < base && + ((ULONG_PTR)free + free->hdr.Size) > base ) { DbgPrint("intersecting blocks on list\n"); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); @@ -1058,16 +1042,15 @@ current_entry = UsedBlockListHead.Flink; while (current_entry != &UsedBlockListHead) { - current = CONTAINING_RECORD(current_entry, BLOCK_HDR, Used.ListEntry); + used = CONTAINING_RECORD(current_entry, HDR_USED, ListEntry);
- if ( (char*)current > base && (char*)current < last ) + if ( (ULONG_PTR)used > base && (ULONG_PTR)used < last ) { DbgPrint("intersecting blocks on list\n"); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); } - if ( (char*)current < base && - ((char*)current + current->Size + BLOCK_HDR_SIZE) - > base ) + if ( (ULONG_PTR)current < base && + ((ULONG_PTR)current + current->hdr.Size) > base ) { DbgPrint("intersecting blocks on list\n"); KEBUGCHECK(/*KBUG_POOL_FREE_LIST_CORRUPT*/0); @@ -1083,7 +1066,8 @@ * FUNCTION: Checks the integrity of the kernel memory heap */ { - BLOCK_HDR* current; + HDR_FREE* free; + HDR_USED* used; PLIST_ENTRY current_entry; PNODE p;
@@ -1093,15 +1077,15 @@ p = avl_get_first(FreeBlockListRoot); while (p) { - current = CONTAINING_RECORD(p, BLOCK_HDR, Free.Node); - check_duplicates(current); + freet = CONTAINING_RECORD(p, HDR_FREE, Node); + check_duplicates(&free->hdr); p = avl_get_next(FreeBlockListRoot, p); } current_entry = UsedBlockListHead.Flink; while (current_entry != &UsedBlockListHead) { - current = CONTAINING_RECORD(current_entry, BLOCK_HDR, Used.ListEntry); - check_duplicates(current); + used = CONTAINING_RECORD(current_entry, HDR_USED, ListEntry); + check_duplicates(&used->hdr); current_entry = current_entry->Flink; } } @@ -1109,14 +1093,13 @@
#if 0 STATIC VOID -free_pages(BLOCK_HDR* blk) +free_pages(HDR_FREE* blk) { ULONG start; ULONG end; - ULONG i;
- start = (ULONG)blk; - end = (ULONG)blk + BLOCK_HDR_SIZE + blk->Size; + start = (ULONG_PTR)blk; + end = (ULONG_PTR)blk + blk->hdr.Size;
/* * If the block doesn't contain a whole page then there is nothing to do @@ -1128,20 +1111,20 @@ } #endif
-static void remove_from_used_list(BLOCK_HDR* current) +static void remove_from_used_list(HDR_USED* current) { - RemoveEntryList(¤t->Used.ListEntry); - EiUsedNonPagedPool -= current->Size; + RemoveEntryList(¤t->ListEntry); + EiUsedNonPagedPool -= current->hdr.Size; EiNrUsedBlocks--; }
-static void remove_from_free_list(BLOCK_HDR* current) +static void remove_from_free_list(HDR_FREE* current) { - DPRINT("remove_from_free_list %d\n", current->Size); + DPRINT("remove_from_free_list %d\n", current->hdr.Size);
- avl_remove(&FreeBlockListRoot, ¤t->Free.Node, compare_node); + avl_remove(&FreeBlockListRoot, ¤t->Node, compare_node);
- EiFreeNonPagedPool -= current->Size; + EiFreeNonPagedPool -= current->hdr.Size; EiNrFreeBlocks--; DPRINT("remove_from_free_list done\n"); #ifdef DUMP_AVL @@ -1151,49 +1134,48 @@ }
static void -add_to_free_list(BLOCK_HDR* blk) +add_to_free_list(HDR_FREE* blk) /* * FUNCTION: add the block to the free list (internal) */ { - BLOCK_HDR* current; + HDR_FREE* current; BOOL UpdatePrevPtr = FALSE;
- DPRINT("add_to_free_list (%d)\n", blk->Size); + DPRINT("add_to_free_list (%d)\n", blk->hdr.Size);
EiNrFreeBlocks++;
- current = blk->previous; - if (current && current->Magic == BLOCK_HDR_FREE_MAGIC) + current = (HDR_FREE*)blk->hdr.previous; + if (current && current->hdr.Magic == BLOCK_HDR_FREE_MAGIC) { remove_from_free_list(current); - current->Size = current->Size + BLOCK_HDR_SIZE + blk->Size; - current->Magic = BLOCK_HDR_USED_MAGIC; - memset(blk, 0xcc, BLOCK_HDR_SIZE); + current->hdr.Size = current->hdr.Size + blk->hdr.Size; + current->hdr.Magic = BLOCK_HDR_USED_MAGIC; + memset(blk, 0xcc, HDR_USED_SIZE); blk = current; UpdatePrevPtr = TRUE; }
- current = (BLOCK_HDR*)((char*)blk + BLOCK_HDR_SIZE + blk->Size); + current = (HDR_FREE*)((ULONG_PTR)blk + blk->hdr.Size); if ((char*)current < (char*)MiNonPagedPoolStart + MiNonPagedPoolLength && - current->Magic == BLOCK_HDR_FREE_MAGIC) + current->hdr.Magic == BLOCK_HDR_FREE_MAGIC) { remove_from_free_list(current); - blk->Size += BLOCK_HDR_SIZE + current->Size; - memset(current, 0xcc, BLOCK_HDR_SIZE); + blk->hdr.Size += current->hdr.Size; + memset(current, 0xcc, HDR_FREE_SIZE); UpdatePrevPtr = TRUE; - current = (BLOCK_HDR*)((char*)blk + BLOCK_HDR_SIZE + blk->Size); + current = (HDR_FREE*)((ULONG_PTR)blk + blk->hdr.Size); } if (UpdatePrevPtr && (char*)current < (char*)MiNonPagedPoolStart + MiNonPagedPoolLength) { - current->previous = blk; + current->hdr.previous = &blk->hdr; } - DPRINT("%d\n", blk->Size); - blk->Magic = BLOCK_HDR_FREE_MAGIC; - EiFreeNonPagedPool += blk->Size; - avl_insert(&FreeBlockListRoot, &blk->Free.Node, compare_node); - + DPRINT("%d\n", blk->hdr.Size); + blk->hdr.Magic = BLOCK_HDR_FREE_MAGIC; + EiFreeNonPagedPool += blk->hdr.Size; + avl_insert(&FreeBlockListRoot, &blk->Node, compare_node); DPRINT("add_to_free_list done\n"); #ifdef DUMP_AVL
@@ -1201,40 +1183,26 @@ #endif }
-static void add_to_used_list(BLOCK_HDR* blk) +static void add_to_used_list(HDR_USED* blk) /* * FUNCTION: add the block to the used list (internal) */ { - InsertHeadList(&UsedBlockListHead, &blk->Used.ListEntry); - EiUsedNonPagedPool += blk->Size; + InsertHeadList(&UsedBlockListHead, &blk->ListEntry); + EiUsedNonPagedPool += blk->hdr.Size; EiNrUsedBlocks++; }
-inline static void* block_to_address(BLOCK_HDR* blk) -/* - * FUNCTION: Translate a block header address to the corresponding block - * address (internal) - */ -{ - return ( (void *) ((char*)blk + BLOCK_HDR_SIZE)); -}
-inline static BLOCK_HDR* address_to_block(void* addr) -{ - return (BLOCK_HDR *) - ( ((char*)addr) - BLOCK_HDR_SIZE ); -} - static BOOLEAN -grow_block(BLOCK_HDR* blk, PVOID end) +grow_block(HDR_FREE* blk, PVOID end) { NTSTATUS Status; PFN_TYPE Page[32]; ULONG_PTR StartIndex, EndIndex; ULONG i, j, k;
- StartIndex = (ULONG_PTR)(PAGE_ROUND_UP((ULONG_PTR)blk + BLOCK_HDR_SIZE - (ULONG_PTR)MiNonPagedPoolStart)) / PAGE_SIZE; + StartIndex = (ULONG_PTR)(PAGE_ROUND_UP((ULONG_PTR)blk + HDR_FREE_SIZE - (ULONG_PTR)MiNonPagedPoolStart)) / PAGE_SIZE; EndIndex = ((ULONG_PTR)PAGE_ROUND_UP(end) - (ULONG_PTR)MiNonPagedPoolStart) / PAGE_SIZE;
@@ -1285,72 +1253,86 @@ return TRUE; }
-static BLOCK_HDR* get_block(unsigned int size, unsigned long alignment) +static HDR_USED* get_block(unsigned int size, unsigned long alignment) { - BLOCK_HDR *blk, *current, *previous = NULL, *next = NULL, *best = NULL; + HDR_FREE *blk, *current, *previous = NULL, *next = NULL, *best = NULL; ULONG previous_size = 0, current_size, next_size = 0, new_size; PVOID end; - PVOID addr, aligned_addr; + PVOID addr, aligned_addr, best_aligned_addr; PNODE p;
DPRINT("get_block %d\n", size);
- if (alignment == 0) + p = avl_find_equal_or_greater(FreeBlockListRoot, size + HDR_USED_SIZE, compare_value); + while (p) { - p = avl_find_equal_or_greater(FreeBlockListRoot, size, compare_value); - if (p) + current = CONTAINING_RECORD(p, HDR_FREE, Node); + addr = (PVOID)((ULONG_PTR)current + HDR_USED_SIZE); + /* calculate first aligned address available within this block */ + aligned_addr = alignment > 0 ? MM_ROUND_UP(addr, alignment) : addr; + if (size < PAGE_SIZE) { - best = CONTAINING_RECORD(p, BLOCK_HDR, Free.Node); - addr = block_to_address(best); + /* check that the block is in one page */ + if (PAGE_ROUND_DOWN(aligned_addr) != PAGE_ROUND_DOWN((ULONG_PTR)aligned_addr + size - 1)) + { + aligned_addr = (PVOID)PAGE_ROUND_UP(aligned_addr); + } } - } - else - { - p = avl_find_equal_or_greater(FreeBlockListRoot, size, compare_value); - - while(p) + DPRINT("%x %x\n", addr, aligned_addr); + if (aligned_addr != addr) { - current = CONTAINING_RECORD(p, BLOCK_HDR, Free.Node); - addr = block_to_address(current); - /* calculate first aligned address available within this block */ - aligned_addr = MM_ROUND_UP(addr, alignment); - /* check to see if this address is already aligned */ - if (addr == aligned_addr) + while((ULONG_PTR)aligned_addr - (ULONG_PTR)addr < HDR_FREE_SIZE) { - if (current->Size >= size && - (best == NULL || current->Size < best->Size)) + if (alignment == 0) { - best = current; + aligned_addr = (PVOID)((ULONG_PTR)current + HDR_USED_SIZE + HDR_FREE_SIZE); } - } - else - { - /* make sure there's enough room to make a free block by the space skipped - * from alignment. If not, calculate forward to the next alignment - * and see if we allocate there... - */ - new_size = (ULONG_PTR)aligned_addr - (ULONG_PTR)addr + size; - if ((ULONG_PTR)aligned_addr - (ULONG_PTR)addr < BLOCK_HDR_SIZE) + else { - /* not enough room for a free block header, add some more bytes */ - aligned_addr = MM_ROUND_UP(block_to_address((BLOCK_HDR*)((char*)current + BLOCK_HDR_SIZE)), alignment); - new_size = (ULONG_PTR)aligned_addr - (ULONG_PTR)addr + size; + aligned_addr = MM_ROUND_UP((PVOID)((ULONG_PTR)current + HDR_USED_SIZE + HDR_FREE_SIZE), alignment); } - if (current->Size >= new_size && - (best == NULL || current->Size < best->Size)) + if (size < PAGE_SIZE) { - best = current; + /* check that the block is in one page */ + if (PAGE_ROUND_DOWN(aligned_addr) != PAGE_ROUND_DOWN((ULONG_PTR)aligned_addr + size - 1)) + { + aligned_addr = (PVOID)PAGE_ROUND_UP(aligned_addr); + } } } - if (best && current->Size >= size + alignment + 2 * BLOCK_HDR_SIZE) + } + DPRINT("%x %x\n", addr, aligned_addr); + new_size = (ULONG_PTR)aligned_addr - (ULONG_PTR)addr + size; + if (current->hdr.Size >= new_size + HDR_USED_SIZE && + (best == NULL || current->hdr.Size < best->hdr.Size)) + { + best = current; + best_aligned_addr = aligned_addr; + if (new_size <= size + 2 * HDR_FREE_SIZE) { - break; + break; } - p = avl_get_next(FreeBlockListRoot, p); - } - } - + + if (best) + { + if (size < PAGE_SIZE) + { + if (current->hdr.Size >= 2 * PAGE_SIZE + HDR_FREE_SIZE) + { + break; + } + } + else + { + if (current->hdr.Size >= size + alignment + HDR_FREE_SIZE) + { + break; + } + } + } + p = avl_get_next(FreeBlockListRoot, p); + } /* * We didn't find anything suitable at all. */ @@ -1359,40 +1341,31 @@ return NULL; }
- current = best; - current_size = current->Size; + DPRINT(":: blk %x blk->hdr.Size %d (%d) Size %d\n", best, best->hdr.Size, best->hdr.Size - HDR_USED_SIZE, size);
- if (alignment > 0) + current = best; + current_size = current->hdr.Size - HDR_USED_SIZE; + addr = (PVOID)((ULONG_PTR)current + HDR_USED_SIZE); + if (addr != best_aligned_addr) { - addr = block_to_address(current); - aligned_addr = MM_ROUND_UP(addr, alignment); - if (addr != aligned_addr) - { - blk = address_to_block(aligned_addr); - if ((char*)blk < (char*)current + BLOCK_HDR_SIZE) - { - aligned_addr = MM_ROUND_UP(block_to_address((BLOCK_HDR*)((char*)current + BLOCK_HDR_SIZE)), alignment); - blk = address_to_block(aligned_addr); - } - /* - * if size-aligned, break off the preceding bytes into their own block... - */ - previous = current; - previous_size = (ULONG_PTR)blk - (ULONG_PTR)previous - BLOCK_HDR_SIZE; - current = blk; - current_size -= ((ULONG_PTR)current - (ULONG_PTR)previous); - } + blk = (HDR_FREE*)((ULONG_PTR)best_aligned_addr - HDR_USED_SIZE); + /* + * if size-aligned, break off the preceding bytes into their own block... + */ + previous = current; + previous_size = (ULONG_PTR)blk - (ULONG_PTR)previous - HDR_FREE_SIZE; + current = blk; + current_size -= ((ULONG_PTR)current - (ULONG_PTR)previous); } + end = (PVOID)((ULONG_PTR)current + HDR_USED_SIZE + size);
- end = (char*)current + BLOCK_HDR_SIZE + size; - - if (current_size >= size + BLOCK_HDR_SIZE + MM_POOL_ALIGNMENT) + if (current_size >= size + HDR_FREE_SIZE + MM_POOL_ALIGNMENT) { /* create a new free block after our block, if the memory size is
= 4 byte for this block */
- next = (BLOCK_HDR*)((ULONG_PTR)current + size + BLOCK_HDR_SIZE); - next_size = current_size - size - BLOCK_HDR_SIZE; + next = (HDR_FREE*)((ULONG_PTR)current + size + HDR_USED_SIZE); + next_size = current_size - size - HDR_FREE_SIZE; current_size = size; - end = (char*)next + BLOCK_HDR_SIZE; + end = (PVOID)((ULONG_PTR)next + HDR_FREE_SIZE); }
if (previous) @@ -1403,17 +1376,17 @@ add_to_free_list(previous); return NULL; } - memset(current, 0, BLOCK_HDR_SIZE); - current->Size = current_size; - current->Magic = BLOCK_HDR_USED_MAGIC; - current->previous = previous; - previous->Size = previous_size; + memset(current, 0, HDR_USED_SIZE); + current->hdr.Size = current_size + HDR_USED_SIZE; + current->hdr.Magic = BLOCK_HDR_USED_MAGIC; + current->hdr.previous = &previous->hdr; + previous->hdr.Size = previous_size + HDR_FREE_SIZE; if (next == NULL) { - blk = (BLOCK_HDR*)((char*)current + BLOCK_HDR_SIZE + current->Size); - if ((char*)blk < (char*)MiNonPagedPoolStart + MiNonPagedPoolLength) + blk = (HDR_FREE*)((ULONG_PTR)current + current->hdr.Size); + if ((ULONG_PTR)blk < (ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength) { - blk->previous = current; + blk->hdr.previous = ¤t->hdr; } }
@@ -1428,56 +1401,55 @@ add_to_free_list(current); return NULL; } - - current->Magic = BLOCK_HDR_USED_MAGIC; + current->hdr.Magic = BLOCK_HDR_USED_MAGIC; if (next) { - current->Size = current_size; + current->hdr.Size = current_size + HDR_USED_SIZE; } }
if (next) { - memset(next, 0, BLOCK_HDR_SIZE); - - next->Size = next_size; - next->Magic = BLOCK_HDR_FREE_MAGIC; - next->previous = current; - blk = (BLOCK_HDR*)((char*)next + BLOCK_HDR_SIZE + next->Size); - if ((char*)blk < (char*)MiNonPagedPoolStart + MiNonPagedPoolLength) + memset(next, 0, HDR_FREE_SIZE); + next->hdr.Size = next_size + HDR_FREE_SIZE; + next->hdr.Magic = BLOCK_HDR_FREE_MAGIC; + next->hdr.previous = ¤t->hdr; + blk = (HDR_FREE*)((ULONG_PTR)next + next->hdr.Size); + if ((ULONG_PTR)blk < (ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength) { - blk->previous = next; + blk->hdr.previous = &next->hdr; } add_to_free_list(next); }
- add_to_used_list(current); + add_to_used_list((HDR_USED*)current); VALIDATE_POOL; - return current; + + if (size < PAGE_SIZE) + { + addr = (PVOID)((ULONG_PTR)current + HDR_USED_SIZE); + if (PAGE_ROUND_DOWN(addr) != PAGE_ROUND_DOWN((PVOID)((ULONG_PTR)addr + size - 1))) + { + DPRINT1("%x %x\n", addr, (ULONG_PTR)addr + size); + } + ASSERT (PAGE_ROUND_DOWN(addr) == PAGE_ROUND_DOWN((PVOID)((ULONG_PTR)addr + size - 1))); + } + if (alignment) + { + addr = (PVOID)((ULONG_PTR)current + HDR_USED_SIZE); + ASSERT(MM_ROUND_UP(addr, alignment) == addr); + } + return (HDR_USED*)current; }
-#endif /* not WHOLE_PAGE_ALLOCATIONS */ - ULONG STDCALL ExRosQueryNonPagedPoolTag ( PVOID Addr ) { -#ifdef WHOLE_PAGE_ALLOCATIONS /* WHOLE_PAGE_ALLOCATIONS */ - - UNIMPLEMENTED; - return 0; - -#else /* not WHOLE_PAGE_ALLOCATIONS */ - - BLOCK_HDR* blk=address_to_block(Addr); - - if (blk->Magic != BLOCK_HDR_USED_MAGIC) + HDR_USED* blk=(HDR_USED*)((ULONG_PTR)Addr - HDR_USED_SIZE); + if (blk->hdr.Magic != BLOCK_HDR_USED_MAGIC) KEBUGCHECK(0); - if (blk->Magic == BLOCK_HDR_FREE_MAGIC) - KEBUGCHECK(0);
- return blk->Used.Tag; [truncated at 1000 lines; 391 more skipped]