mirror of
https://github.com/reactos/reactos.git
synced 2025-07-06 20:31:21 +00:00
[NTOS]: Use logical math operations on the various block<->entry<->free_list_head operations in the pool code, instead of works-by-chance-and-assumption pointer math operations. This will now allow pool implementations where the pool header is not the size of a pool block (and the size of a LIST_ENTRY, by definition, although, even that, could change, if we choose to implement a cache-aligned overhead).
svn path=/trunk/; revision=47594
This commit is contained in:
parent
e8b356d800
commit
fc1ffb8a44
1 changed files with 37 additions and 23 deletions
|
@ -28,6 +28,13 @@ PPOOL_DESCRIPTOR PoolVector[2];
|
||||||
PVOID PoolTrackTable;
|
PVOID PoolTrackTable;
|
||||||
PKGUARDED_MUTEX ExpPagedPoolMutex;
|
PKGUARDED_MUTEX ExpPagedPoolMutex;
|
||||||
|
|
||||||
|
/* Pool block/header/list access macros */
|
||||||
|
#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)
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -68,7 +75,11 @@ ExInitializePoolDescriptor(IN PPOOL_DESCRIPTOR PoolDescriptor,
|
||||||
//
|
//
|
||||||
NextEntry = PoolDescriptor->ListHeads;
|
NextEntry = PoolDescriptor->ListHeads;
|
||||||
LastEntry = NextEntry + POOL_LISTS_PER_PAGE;
|
LastEntry = NextEntry + POOL_LISTS_PER_PAGE;
|
||||||
while (NextEntry < LastEntry) InitializeListHead(NextEntry++);
|
while (NextEntry < LastEntry)
|
||||||
|
{
|
||||||
|
InitializeListHead(NextEntry);
|
||||||
|
NextEntry++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -239,8 +250,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// request would've been treated as a POOL_MAX_ALLOC earlier and resulted in
|
// request would've been treated as a POOL_MAX_ALLOC earlier and resulted in
|
||||||
// the direct allocation of pages.
|
// the direct allocation of pages.
|
||||||
//
|
//
|
||||||
i = (NumberOfBytes + sizeof(POOL_HEADER) + sizeof(LIST_ENTRY) - 1) /
|
i = (NumberOfBytes + sizeof(POOL_HEADER) + (POOL_BLOCK_SIZE - 1)) / POOL_BLOCK_SIZE;
|
||||||
sizeof(POOL_HEADER);
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop in the free lists looking for a block if this size. Start with the
|
// Loop in the free lists looking for a block if this size. Start with the
|
||||||
|
@ -281,7 +291,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// there is a guarantee that any block on this list will either be
|
// there is a guarantee that any block on this list will either be
|
||||||
// of the correct size, or perhaps larger.
|
// of the correct size, or perhaps larger.
|
||||||
//
|
//
|
||||||
Entry = (PPOOL_HEADER)RemoveHeadList(ListHead) - 1;
|
Entry = POOL_ENTRY(RemoveHeadList(ListHead));
|
||||||
ASSERT(Entry->BlockSize >= i);
|
ASSERT(Entry->BlockSize >= i);
|
||||||
ASSERT(Entry->PoolType == 0);
|
ASSERT(Entry->PoolType == 0);
|
||||||
|
|
||||||
|
@ -302,7 +312,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// turn it into a fragment that contains the leftover data
|
// turn it into a fragment that contains the leftover data
|
||||||
// that we don't need to satisfy the caller's request
|
// that we don't need to satisfy the caller's request
|
||||||
//
|
//
|
||||||
FragmentEntry = Entry + i;
|
FragmentEntry = POOL_BLOCK(Entry, i);
|
||||||
FragmentEntry->BlockSize = Entry->BlockSize - i;
|
FragmentEntry->BlockSize = Entry->BlockSize - i;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -314,7 +324,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// Now get the block that follows the new fragment and check
|
// Now get the block that follows the new fragment and check
|
||||||
// if it's still on the same page as us (and not at the end)
|
// if it's still on the same page as us (and not at the end)
|
||||||
//
|
//
|
||||||
NextEntry = FragmentEntry + FragmentEntry->BlockSize;
|
NextEntry = POOL_NEXT_BLOCK(FragmentEntry);
|
||||||
if (PAGE_ALIGN(NextEntry) != NextEntry)
|
if (PAGE_ALIGN(NextEntry) != NextEntry)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -346,14 +356,14 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// This is the entry that will actually end up holding the
|
// This is the entry that will actually end up holding the
|
||||||
// allocation!
|
// allocation!
|
||||||
//
|
//
|
||||||
Entry += Entry->BlockSize;
|
Entry = POOL_NEXT_BLOCK(Entry);
|
||||||
Entry->PreviousSize = FragmentEntry->BlockSize;
|
Entry->PreviousSize = FragmentEntry->BlockSize;
|
||||||
|
|
||||||
//
|
//
|
||||||
// And now let's go to the entry after that one and check if
|
// And now let's go to the entry after that one and check if
|
||||||
// it's still on the same page, and not at the end
|
// it's still on the same page, and not at the end
|
||||||
//
|
//
|
||||||
NextEntry = Entry + i;
|
NextEntry = POOL_BLOCK(Entry, i);
|
||||||
if (PAGE_ALIGN(NextEntry) != NextEntry)
|
if (PAGE_ALIGN(NextEntry) != NextEntry)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -387,7 +397,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// Insert the free entry into the free list for this size
|
// Insert the free entry into the free list for this size
|
||||||
//
|
//
|
||||||
InsertTailList(&PoolDesc->ListHeads[BlockSize - 1],
|
InsertTailList(&PoolDesc->ListHeads[BlockSize - 1],
|
||||||
(PLIST_ENTRY)FragmentEntry + 1);
|
POOL_FREE_BLOCK(FragmentEntry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +412,9 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// Return the pool allocation
|
// Return the pool allocation
|
||||||
//
|
//
|
||||||
Entry->PoolTag = Tag;
|
Entry->PoolTag = Tag;
|
||||||
return ++Entry;
|
(POOL_FREE_BLOCK(Entry))->Flink = NULL;
|
||||||
|
(POOL_FREE_BLOCK(Entry))->Blink = NULL;
|
||||||
|
return POOL_FREE_BLOCK(Entry);
|
||||||
}
|
}
|
||||||
} while (++ListHead != &PoolDesc->ListHeads[POOL_LISTS_PER_PAGE]);
|
} while (++ListHead != &PoolDesc->ListHeads[POOL_LISTS_PER_PAGE]);
|
||||||
|
|
||||||
|
@ -410,6 +422,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// There were no free entries left, so we have to allocate a new fresh page
|
// There were no free entries left, so we have to allocate a new fresh page
|
||||||
//
|
//
|
||||||
Entry = MiAllocatePoolPages(PoolType, PAGE_SIZE);
|
Entry = MiAllocatePoolPages(PoolType, PAGE_SIZE);
|
||||||
|
ASSERT(Entry != NULL);
|
||||||
Entry->Ulong1 = 0;
|
Entry->Ulong1 = 0;
|
||||||
Entry->BlockSize = i;
|
Entry->BlockSize = i;
|
||||||
Entry->PoolType = PoolType + 1;
|
Entry->PoolType = PoolType + 1;
|
||||||
|
@ -420,8 +433,8 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// to create now. The free bytes are the whole page minus what was allocated
|
// to create now. The free bytes are the whole page minus what was allocated
|
||||||
// and then converted into units of block headers.
|
// and then converted into units of block headers.
|
||||||
//
|
//
|
||||||
BlockSize = (PAGE_SIZE / sizeof(POOL_HEADER)) - i;
|
BlockSize = (PAGE_SIZE / POOL_BLOCK_SIZE) - i;
|
||||||
FragmentEntry = Entry + i;
|
FragmentEntry = POOL_BLOCK(Entry, i);
|
||||||
FragmentEntry->Ulong1 = 0;
|
FragmentEntry->Ulong1 = 0;
|
||||||
FragmentEntry->BlockSize = BlockSize;
|
FragmentEntry->BlockSize = BlockSize;
|
||||||
FragmentEntry->PreviousSize = i;
|
FragmentEntry->PreviousSize = i;
|
||||||
|
@ -442,7 +455,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// And insert the free entry into the free list for this block size
|
// And insert the free entry into the free list for this block size
|
||||||
//
|
//
|
||||||
InsertTailList(&PoolDesc->ListHeads[BlockSize - 1],
|
InsertTailList(&PoolDesc->ListHeads[BlockSize - 1],
|
||||||
(PLIST_ENTRY)FragmentEntry + 1);
|
POOL_FREE_BLOCK(FragmentEntry));
|
||||||
|
|
||||||
//
|
//
|
||||||
// Release the pool lock
|
// Release the pool lock
|
||||||
|
@ -454,7 +467,7 @@ ExAllocatePoolWithTag(IN POOL_TYPE PoolType,
|
||||||
// And return the pool allocation
|
// And return the pool allocation
|
||||||
//
|
//
|
||||||
Entry->PoolTag = Tag;
|
Entry->PoolTag = Tag;
|
||||||
return ++Entry;
|
return POOL_FREE_BLOCK(Entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -485,7 +498,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
POOL_TYPE PoolType;
|
POOL_TYPE PoolType;
|
||||||
PPOOL_DESCRIPTOR PoolDesc;
|
PPOOL_DESCRIPTOR PoolDesc;
|
||||||
BOOLEAN Combined = FALSE;
|
BOOLEAN Combined = FALSE;
|
||||||
|
#if 1
|
||||||
//
|
//
|
||||||
// Check for paged pool
|
// Check for paged pool
|
||||||
//
|
//
|
||||||
|
@ -498,6 +511,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
ExFreePagedPool(P);
|
ExFreePagedPool(P);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
// Quickly deal with big page allocations
|
// Quickly deal with big page allocations
|
||||||
|
@ -526,7 +540,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
//
|
//
|
||||||
// Get the pointer to the next entry
|
// Get the pointer to the next entry
|
||||||
//
|
//
|
||||||
NextEntry = Entry + BlockSize;
|
NextEntry = POOL_BLOCK(Entry, BlockSize);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Acquire the pool lock
|
// Acquire the pool lock
|
||||||
|
@ -559,7 +573,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
// The block is at least big enough to have a linked list, so go
|
// The block is at least big enough to have a linked list, so go
|
||||||
// ahead and remove it
|
// ahead and remove it
|
||||||
//
|
//
|
||||||
RemoveEntryList((PLIST_ENTRY)NextEntry + 1);
|
RemoveEntryList(POOL_FREE_BLOCK(NextEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -577,7 +591,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
//
|
//
|
||||||
// Great, grab that entry and check if it's free
|
// Great, grab that entry and check if it's free
|
||||||
//
|
//
|
||||||
NextEntry = Entry - Entry->PreviousSize;
|
NextEntry = POOL_PREV_BLOCK(Entry);
|
||||||
if (NextEntry->PoolType == 0)
|
if (NextEntry->PoolType == 0)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -596,7 +610,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
// The block is at least big enough to have a linked list, so go
|
// The block is at least big enough to have a linked list, so go
|
||||||
// ahead and remove it
|
// ahead and remove it
|
||||||
//
|
//
|
||||||
RemoveEntryList((PLIST_ENTRY)NextEntry + 1);
|
RemoveEntryList(POOL_FREE_BLOCK(NextEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -618,7 +632,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
// page, they could've all been combined).
|
// page, they could've all been combined).
|
||||||
//
|
//
|
||||||
if ((PAGE_ALIGN(Entry) == Entry) &&
|
if ((PAGE_ALIGN(Entry) == Entry) &&
|
||||||
(PAGE_ALIGN(Entry + Entry->BlockSize) == Entry + Entry->BlockSize))
|
(PAGE_ALIGN(POOL_NEXT_BLOCK(Entry)) == POOL_NEXT_BLOCK(Entry)))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// In this case, release the pool lock, and free the page
|
// In this case, release the pool lock, and free the page
|
||||||
|
@ -644,7 +658,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
// Get the first combined block (either our original to begin with, or
|
// Get the first combined block (either our original to begin with, or
|
||||||
// the one after the original, depending if we combined with the previous)
|
// the one after the original, depending if we combined with the previous)
|
||||||
//
|
//
|
||||||
NextEntry = Entry + BlockSize;
|
NextEntry = POOL_NEXT_BLOCK(Entry);
|
||||||
|
|
||||||
//
|
//
|
||||||
// As long as the next block isn't on a page boundary, have it point
|
// As long as the next block isn't on a page boundary, have it point
|
||||||
|
@ -656,7 +670,7 @@ ExFreePoolWithTag(IN PVOID P,
|
||||||
//
|
//
|
||||||
// Insert this new free block, and release the pool lock
|
// Insert this new free block, and release the pool lock
|
||||||
//
|
//
|
||||||
InsertHeadList(&PoolDesc->ListHeads[BlockSize - 1], (PLIST_ENTRY)Entry + 1);
|
InsertHeadList(&PoolDesc->ListHeads[BlockSize - 1], POOL_FREE_BLOCK(Entry));
|
||||||
ExUnlockPool(PoolDesc, OldIrql);
|
ExUnlockPool(PoolDesc, OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue