📄 mpheap.c
字号:
)
{
PMP_HEAP MpHeap;
DWORD i;
BOOL Success;
PMP_HEADER Header;
PMP_HEAP_ENTRY Entry;
MpHeap = (PMP_HEAP)hMpHeap;
if (lpMem == NULL) {
//
// Lock and validate each heap in turn.
//
for (i=0; i < MpHeap->HeapCount; i++) {
Entry = &MpHeap->Entry[i];
try {
EnterCriticalSection(&Entry->Lock);
Success = HeapValidate(Entry->Heap, 0, NULL);
LeaveCriticalSection(&Entry->Lock);
} except (EXCEPTION_EXECUTE_HANDLER) {
return(FALSE);
}
if (!Success) {
return(FALSE);
}
}
return(TRUE);
} else {
//
// Lock and validate the given heap entry
//
Header = ((PMP_HEADER)lpMem) - 1;
try {
EnterCriticalSection(&Header->HeapEntry->Lock);
Success = HeapValidate(Header->HeapEntry->Heap, 0, Header);
LeaveCriticalSection(&Header->HeapEntry->Lock);
} except (EXCEPTION_EXECUTE_HANDLER) {
return(FALSE);
}
return(Success);
}
}
UINT
WINAPI
MpHeapCompact(
HANDLE hMpHeap
)
{
PMP_HEAP MpHeap;
DWORD i;
DWORD LargestFreeSize=0;
DWORD FreeSize;
PMP_HEAP_ENTRY Entry;
MpHeap = (PMP_HEAP)hMpHeap;
//
// Lock and compact each heap in turn.
//
for (i=0; i < MpHeap->HeapCount; i++) {
Entry = &MpHeap->Entry[i];
EnterCriticalSection(&Entry->Lock);
FreeSize = HeapCompact(Entry->Heap, 0);
LeaveCriticalSection(&Entry->Lock);
if (FreeSize > LargestFreeSize) {
LargestFreeSize = FreeSize;
}
}
return(LargestFreeSize);
}
LPVOID
WINAPI
MpHeapAlloc(
HANDLE hMpHeap,
DWORD flOptions,
DWORD dwBytes
)
{
PMP_HEADER Header;
PMP_HEAP MpHeap;
DWORD i;
PMP_HEAP_ENTRY Entry;
DWORD Index;
DWORD Size;
MpHeap = (PMP_HEAP)hMpHeap;
flOptions |= MpHeap->Flags;
Size = ((dwBytes + 7) & (ULONG)~7) + sizeof(MP_HEADER);
Index=LookasideIndexFromSize(Size);
//
// Iterate through the heap locks looking for one
// that is not owned.
//
i=HeapHint;
if (i>=MpHeap->HeapCount) {
i=0;
HeapHint=0;
}
Entry = &MpHeap->Entry[i];
do {
//
// Check the lookaside list for a suitable allocation.
//
if ((Index != NO_LOOKASIDE) &&
(Entry->Lookaside[Index].Entry != NULL)) {
if ((Header = (PMP_HEADER)InterlockedExchange((PLONG)&Entry->Lookaside[Index].Entry,
(LONG)NULL)) != NULL) {
//
// We have a lookaside hit, return it immediately.
//
++Entry->LookasideAllocations;
if (flOptions & MPHEAP_ZERO_MEMORY) {
ZeroMemory(Header + 1, dwBytes);
}
HeapHint=i;
return(Header + 1);
}
}
//
// Attempt to lock this heap without blocking.
//
if (TryEnterCriticalSection(&Entry->Lock)) {
//
// success, go allocate immediately
//
goto LockAcquired;
}
//
// This heap is owned by another thread, try
// the next one.
//
i++;
Entry++;
if (i==MpHeap->HeapCount) {
i=0;
Entry=&MpHeap->Entry[0];
}
} while ( i != HeapHint );
//
// All of the critical sections were owned by someone else,
// so we have no choice but to wait for a critical section.
//
EnterCriticalSection(&Entry->Lock);
LockAcquired:
++Entry->Allocations;
if (Entry->DelayedFreeList != NULL) {
ProcessDelayedFreeList(Entry);
}
Header = HeapAlloc(Entry->Heap, 0, Size);
LeaveCriticalSection(&Entry->Lock);
if (Header != NULL) {
Header->HeapEntry = Entry;
Header->LookasideIndex = Index;
if (flOptions & MPHEAP_ZERO_MEMORY) {
ZeroMemory(Header + 1, dwBytes);
}
HeapHint = i;
return(Header + 1);
} else {
return(NULL);
}
}
LPVOID
WINAPI
MpHeapReAlloc(
HANDLE hMpHeap,
LPVOID lpMem,
DWORD dwBytes
)
{
PMP_HEADER Header;
PCRITICAL_SECTION Lock;
Header = ((PMP_HEADER)lpMem) - 1;
Lock = &Header->HeapEntry->Lock;
dwBytes = ((dwBytes + 7) & (ULONG)~7) + sizeof(MP_HEADER);
EnterCriticalSection(Lock);
Header = HeapReAlloc(Header->HeapEntry->Heap, 0, Header, dwBytes);
LeaveCriticalSection(Lock);
if (Header != NULL) {
Header->LookasideIndex = LookasideIndexFromSize(dwBytes);
return(Header + 1);
} else {
return(NULL);
}
}
BOOL
WINAPI
MpHeapFree(
HANDLE hMpHeap,
LPVOID lpMem
)
{
PMP_HEADER Header;
PCRITICAL_SECTION Lock;
BOOL Success;
PMP_HEAP_ENTRY HeapEntry;
PSINGLE_LIST_ENTRY Next;
PMP_HEAP MpHeap;
Header = ((PMP_HEADER)lpMem) - 1;
HeapEntry = Header->HeapEntry;
MpHeap = (PMP_HEAP)hMpHeap;
HeapHint = HeapEntry - &MpHeap->Entry[0];
if (Header->LookasideIndex != NO_LOOKASIDE) {
//
// Try and put this back on the lookaside list
//
if (InterlockedCompareExchange((PVOID *)&HeapEntry->Lookaside[Header->LookasideIndex],
(PVOID)Header,
NULL) == NULL) {
//
// Successfully freed to lookaside list.
//
++HeapEntry->LookasideFrees;
return(TRUE);
}
}
Lock = &HeapEntry->Lock;
if (TryEnterCriticalSection(Lock)) {
++HeapEntry->Frees;
Success = HeapFree(HeapEntry->Heap, 0, Header);
LeaveCriticalSection(Lock);
return(Success);
}
//
// The necessary heap critical section could not be immediately
// acquired. Post this free onto the Delayed free list and let
// whoever has the lock process it.
//
do {
Next = HeapEntry->DelayedFreeList;
Header->Next = Next;
} while ( InterlockedCompareExchange(&HeapEntry->DelayedFreeList,
&Header->Next,
Next) != Next);
return(TRUE);
}
VOID
ProcessDelayedFreeList(
IN PMP_HEAP_ENTRY HeapEntry
)
{
PSINGLE_LIST_ENTRY FreeList;
PSINGLE_LIST_ENTRY Next;
PMP_HEADER Header;
//
// Capture the entire delayed free list with a single interlocked exchange.
// Once we have removed the entire list, free each entry in turn.
//
FreeList = (PSINGLE_LIST_ENTRY)InterlockedExchange((LPLONG)&HeapEntry->DelayedFreeList, (LONG)NULL);
while (FreeList != NULL) {
Next = FreeList->Next;
Header = CONTAINING_RECORD(FreeList, MP_HEADER, Next);
++HeapEntry->DelayedFrees;
HeapFree(HeapEntry->Heap, 0, Header);
FreeList = Next;
}
}
DWORD
MpHeapGetStatistics(
HANDLE hMpHeap,
LPDWORD lpdwSize,
MPHEAP_STATISTICS Stats[]
)
{
PMP_HEAP MpHeap;
PMP_HEAP_ENTRY Entry;
DWORD i;
DWORD RequiredSize;
MpHeap = (PMP_HEAP)hMpHeap;
RequiredSize = MpHeap->HeapCount * sizeof(MPHEAP_STATISTICS);
if (*lpdwSize < RequiredSize) {
*lpdwSize = RequiredSize;
return(ERROR_MORE_DATA);
}
ZeroMemory(Stats, MpHeap->HeapCount * sizeof(MPHEAP_STATISTICS));
for (i=0; i < MpHeap->HeapCount; i++) {
Entry = &MpHeap->Entry[i];
Stats[i].Contention = Entry->Lock.DebugInfo->ContentionCount;
Stats[i].TotalAllocates = (Entry->Allocations + Entry->LookasideAllocations);
Stats[i].TotalFrees = (Entry->Frees + Entry->LookasideFrees + Entry->DelayedFrees);
Stats[i].LookasideAllocates = Entry->LookasideAllocations;
Stats[i].LookasideFrees = Entry->LookasideFrees;
Stats[i].DelayedFrees = Entry->DelayedFrees;
}
*lpdwSize = RequiredSize;
return(ERROR_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -