Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304/* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/config/cmalloc.c * PURPOSE: Routines for allocating and freeing registry structures * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>#define NDEBUG#include <debug.h>
/* GLOBALS *******************************************************************/
BOOLEAN CmpAllocInited;KGUARDED_MUTEX CmpAllocBucketLock;LIST_ENTRY CmpFreeKCBListHead;
KGUARDED_MUTEX CmpDelayAllocBucketLock;LIST_ENTRY CmpFreeDelayItemsListHead;
/* FUNCTIONS *****************************************************************/
CODE_SEG("INIT")VOIDNTAPICmpInitCmPrivateAlloc(VOID){ /* Make sure we didn't already do this */ if (!CmpAllocInited) { /* Setup the lock and list */ KeInitializeGuardedMutex(&CmpAllocBucketLock); InitializeListHead(&CmpFreeKCBListHead); CmpAllocInited = TRUE; }}
CODE_SEG("INIT")VOIDNTAPICmpInitCmPrivateDelayAlloc(VOID){ /* Initialize the delay allocation list and lock */ KeInitializeGuardedMutex(&CmpDelayAllocBucketLock); InitializeListHead(&CmpFreeDelayItemsListHead);}
VOIDNTAPICmpFreeKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb){ ULONG i; PCM_ALLOC_PAGE AllocPage; PAGED_CODE();
/* Sanity checks */ ASSERT(IsListEmpty(&Kcb->KeyBodyListHead) == TRUE); for (i = 0; i < 4; i++) ASSERT(Kcb->KeyBodyArray[i] == NULL);
/* Check if it wasn't privately allocated */ if (!Kcb->PrivateAlloc) { /* Free it from the pool */ CmpFree(Kcb, TAG_KCB); return; }
/* Acquire the private allocation lock */ KeAcquireGuardedMutex(&CmpAllocBucketLock);
/* Sanity check on lock ownership */ CMP_ASSERT_HASH_ENTRY_LOCK(Kcb->ConvKey);
/* Add us to the free list */ InsertTailList(&CmpFreeKCBListHead, &Kcb->FreeListEntry);
/* Get the allocation page */ AllocPage = CmpGetAllocPageFromKcb(Kcb);
/* Sanity check */ ASSERT(AllocPage->FreeCount != CM_KCBS_PER_PAGE);
/* Increase free count */ if (++AllocPage->FreeCount == CM_KCBS_PER_PAGE) { /* Loop all the entries */ for (i = 0; i < CM_KCBS_PER_PAGE; i++) { /* Get the KCB */ Kcb = (PVOID)((ULONG_PTR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) + i * sizeof(CM_KEY_CONTROL_BLOCK));
/* Remove the entry */ RemoveEntryList(&Kcb->FreeListEntry); }
/* Free the page */ CmpFree(AllocPage, TAG_KCB); }
/* Release the lock */ KeReleaseGuardedMutex(&CmpAllocBucketLock);}
PCM_KEY_CONTROL_BLOCKNTAPICmpAllocateKeyControlBlock(VOID){ PLIST_ENTRY NextEntry; PCM_KEY_CONTROL_BLOCK CurrentKcb; PCM_ALLOC_PAGE AllocPage; ULONG i; PAGED_CODE();
/* Check if private allocations are initialized */ if (CmpAllocInited) { /* They are, acquire the bucket lock */ KeAcquireGuardedMutex(&CmpAllocBucketLock);
/* See if there's something on the free KCB list */SearchKcbList: if (!IsListEmpty(&CmpFreeKCBListHead)) { /* Remove the entry */ NextEntry = RemoveHeadList(&CmpFreeKCBListHead);
/* Get the KCB */ CurrentKcb = CONTAINING_RECORD(NextEntry, CM_KEY_CONTROL_BLOCK, FreeListEntry);
/* Get the allocation page */ AllocPage = CmpGetAllocPageFromKcb(CurrentKcb);
/* Decrease the free count */ ASSERT(AllocPage->FreeCount != 0); AllocPage->FreeCount--;
/* Make sure this KCB is privately allocated */ ASSERT(CurrentKcb->PrivateAlloc == 1);
/* Release the allocation lock */ KeReleaseGuardedMutex(&CmpAllocBucketLock);
/* Return the KCB */ return CurrentKcb; }
/* Allocate an allocation page */ AllocPage = CmpAllocate(PAGE_SIZE, TRUE, TAG_KCB); if (AllocPage) { /* Set default entries */ AllocPage->FreeCount = CM_KCBS_PER_PAGE;
/* Loop each entry */ for (i = 0; i < CM_KCBS_PER_PAGE; i++) { /* Get this entry */ CurrentKcb = (PVOID)((ULONG_PTR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) + i * sizeof(CM_KEY_CONTROL_BLOCK));
/* Set it up */ CurrentKcb->PrivateAlloc = TRUE; CurrentKcb->DelayCloseEntry = NULL; InsertTailList(&CmpFreeKCBListHead, &CurrentKcb->FreeListEntry); }
/* Now go back and search the list */ goto SearchKcbList; }
/* Release the allocation lock */ KeReleaseGuardedMutex(&CmpAllocBucketLock); }
/* Allocate a KCB only */ CurrentKcb = CmpAllocate(sizeof(CM_KEY_CONTROL_BLOCK), TRUE, TAG_KCB); if (CurrentKcb) { /* Set it up */ CurrentKcb->PrivateAlloc = 0; CurrentKcb->DelayCloseEntry = NULL; }
/* Return it */ return CurrentKcb;}
PVOIDNTAPICmpAllocateDelayItem(VOID){ PCM_DELAY_ALLOC Entry; PCM_ALLOC_PAGE AllocPage; ULONG i; PLIST_ENTRY NextEntry; PAGED_CODE();
/* Lock the allocation buckets */ KeAcquireGuardedMutex(&CmpDelayAllocBucketLock);
/* Look for an item on the free list */SearchList: if (!IsListEmpty(&CmpFreeDelayItemsListHead)) { /* Get the current entry in the list */ NextEntry = RemoveHeadList(&CmpFreeDelayItemsListHead);
/* Grab the item */ Entry = CONTAINING_RECORD(NextEntry, CM_DELAY_ALLOC, ListEntry);
/* Clear the list */ Entry->ListEntry.Flink = Entry->ListEntry.Blink = NULL;
/* Grab the alloc page */ AllocPage = CmpGetAllocPageFromDelayAlloc(Entry);
/* Decrease free entries */ ASSERT(AllocPage->FreeCount != 0); AllocPage->FreeCount--;
/* Release the lock */ KeReleaseGuardedMutex(&CmpDelayAllocBucketLock); return Entry; }
/* Allocate an allocation page */ AllocPage = CmpAllocate(PAGE_SIZE, TRUE, TAG_CM); if (AllocPage) { /* Set default entries */ AllocPage->FreeCount = CM_DELAYS_PER_PAGE;
/* Loop each entry */ for (i = 0; i < CM_DELAYS_PER_PAGE; i++) { /* Get this entry and link it */ Entry = (PVOID)((ULONG_PTR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) + i * sizeof(CM_DELAY_ALLOC)); InsertTailList(&CmpFreeDelayItemsListHead, &Entry->ListEntry);
/* Clear the KCB pointer */ Entry->Kcb = NULL; }
/* Do the search again */ goto SearchList; }
/* Release the lock */ KeReleaseGuardedMutex(&CmpDelayAllocBucketLock); return NULL;}
VOIDNTAPICmpFreeDelayItem(PVOID Entry){ PCM_DELAY_ALLOC AllocEntry = (PCM_DELAY_ALLOC)Entry; PCM_ALLOC_PAGE AllocPage; ULONG i; PAGED_CODE();
/* Lock the table */ KeAcquireGuardedMutex(&CmpDelayAllocBucketLock);
/* Add the entry at the end */ InsertTailList(&CmpFreeDelayItemsListHead, &AllocEntry->ListEntry);
/* Get the alloc page */ AllocPage = CmpGetAllocPageFromDelayAlloc(Entry); ASSERT(AllocPage->FreeCount != CM_DELAYS_PER_PAGE);
/* Increase the number of free items */ if (++AllocPage->FreeCount == CM_DELAYS_PER_PAGE) { /* Page is totally free now, loop each entry */ for (i = 0; i < CM_DELAYS_PER_PAGE; i++) { /* Get the entry and unlink it */ AllocEntry = (PVOID)((ULONG_PTR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) + i * sizeof(CM_DELAY_ALLOC)); RemoveEntryList(&AllocEntry->ListEntry); }
/* Now free the page */ CmpFree(AllocPage, TAG_CM); }
/* Release the lock */ KeReleaseGuardedMutex(&CmpDelayAllocBucketLock);}