2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/config/cmalloc.c
5 * PURPOSE: Routines for allocating and freeing registry structures
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 BOOLEAN CmpAllocInited
;
18 KGUARDED_MUTEX CmpAllocBucketLock
, CmpDelayAllocBucketLock
;
20 LIST_ENTRY CmpFreeKCBListHead
;
21 KGUARDED_MUTEX CmpDelayAllocBucketLock
;
22 LIST_ENTRY CmpFreeDelayItemsListHead
;
24 /* FUNCTIONS *****************************************************************/
29 CmpInitCmPrivateAlloc(VOID
)
31 /* Make sure we didn't already do this */
34 /* Setup the lock and list */
35 KeInitializeGuardedMutex(&CmpAllocBucketLock
);
36 InitializeListHead(&CmpFreeKCBListHead
);
37 CmpAllocInited
= TRUE
;
44 CmpInitCmPrivateDelayAlloc(VOID
)
46 /* Initialize the delay allocation list and lock */
47 KeInitializeGuardedMutex(&CmpDelayAllocBucketLock
);
48 InitializeListHead(&CmpFreeDelayItemsListHead
);
53 CmpFreeKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb
)
56 PCM_ALLOC_PAGE AllocPage
;
60 ASSERT(IsListEmpty(&Kcb
->KeyBodyListHead
) == TRUE
);
61 for (i
= 0; i
< 4; i
++) ASSERT(Kcb
->KeyBodyArray
[i
] == NULL
);
63 /* Check if it wasn't privately allocated */
64 if (!Kcb
->PrivateAlloc
)
66 /* Free it from the pool */
67 CmpFree(Kcb
, TAG_KCB
);
71 /* Acquire the private allocation lock */
72 KeAcquireGuardedMutex(&CmpAllocBucketLock
);
74 /* Sanity check on lock ownership */
75 CMP_ASSERT_HASH_ENTRY_LOCK(Kcb
->ConvKey
);
77 /* Add us to the free list */
78 InsertTailList(&CmpFreeKCBListHead
, &Kcb
->FreeListEntry
);
80 /* Get the allocation page */
81 AllocPage
= CmpGetAllocPageFromKcb(Kcb
);
84 ASSERT(AllocPage
->FreeCount
!= CM_KCBS_PER_PAGE
);
86 /* Increase free count */
87 if (++AllocPage
->FreeCount
== CM_KCBS_PER_PAGE
)
89 /* Loop all the entries */
90 for (i
= 0; i
< CM_KCBS_PER_PAGE
; i
++)
93 Kcb
= (PVOID
)((ULONG_PTR
)AllocPage
+
94 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
95 i
* sizeof(CM_KEY_CONTROL_BLOCK
));
97 /* Remove the entry */
98 RemoveEntryList(&Kcb
->FreeListEntry
);
102 CmpFree(AllocPage
, TAG_KCB
);
105 /* Release the lock */
106 KeReleaseGuardedMutex(&CmpAllocBucketLock
);
109 PCM_KEY_CONTROL_BLOCK
111 CmpAllocateKeyControlBlock(VOID
)
113 PLIST_ENTRY NextEntry
;
114 PCM_KEY_CONTROL_BLOCK CurrentKcb
;
115 PCM_ALLOC_PAGE AllocPage
;
119 /* Check if private allocations are initialized */
122 /* They are, acquire the bucket lock */
123 KeAcquireGuardedMutex(&CmpAllocBucketLock
);
125 /* See if there's something on the free KCB list */
127 if (!IsListEmpty(&CmpFreeKCBListHead
))
129 /* Remove the entry */
130 NextEntry
= RemoveHeadList(&CmpFreeKCBListHead
);
133 CurrentKcb
= CONTAINING_RECORD(NextEntry
,
134 CM_KEY_CONTROL_BLOCK
,
137 /* Get the allocation page */
138 AllocPage
= CmpGetAllocPageFromKcb(CurrentKcb
);
140 /* Decrease the free count */
141 ASSERT(AllocPage
->FreeCount
!= 0);
142 AllocPage
->FreeCount
--;
144 /* Make sure this KCB is privately allocated */
145 ASSERT(CurrentKcb
->PrivateAlloc
== 1);
147 /* Release the allocation lock */
148 KeReleaseGuardedMutex(&CmpAllocBucketLock
);
154 /* Allocate an allocation page */
155 AllocPage
= CmpAllocate(PAGE_SIZE
, TRUE
, TAG_KCB
);
158 /* Set default entries */
159 AllocPage
->FreeCount
= CM_KCBS_PER_PAGE
;
161 /* Loop each entry */
162 for (i
= 0; i
< CM_KCBS_PER_PAGE
; i
++)
165 CurrentKcb
= (PVOID
)((ULONG_PTR
)AllocPage
+
166 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
167 i
* sizeof(CM_KEY_CONTROL_BLOCK
));
170 CurrentKcb
->PrivateAlloc
= TRUE
;
171 CurrentKcb
->DelayCloseEntry
= NULL
;
172 InsertTailList(&CmpFreeKCBListHead
,
173 &CurrentKcb
->FreeListEntry
);
176 /* Now go back and search the list */
181 /* Allocate a KCB only */
182 CurrentKcb
= CmpAllocate(sizeof(CM_KEY_CONTROL_BLOCK
), TRUE
, TAG_KCB
);
186 CurrentKcb
->PrivateAlloc
= 0;
187 CurrentKcb
->DelayCloseEntry
= NULL
;
196 CmpAllocateDelayItem(VOID
)
198 PCM_DELAY_ALLOC Entry
;
199 PCM_ALLOC_PAGE AllocPage
;
201 PLIST_ENTRY NextEntry
;
204 /* Lock the allocation buckets */
205 KeAcquireGuardedMutex(&CmpDelayAllocBucketLock
);
207 /* Look for an item on the free list */
209 if (!IsListEmpty(&CmpFreeDelayItemsListHead
))
211 /* Get the current entry in the list */
212 NextEntry
= RemoveHeadList(&CmpFreeDelayItemsListHead
);
215 Entry
= CONTAINING_RECORD(NextEntry
, CM_DELAY_ALLOC
, ListEntry
);
218 Entry
->ListEntry
.Flink
= Entry
->ListEntry
.Blink
= NULL
;
220 /* Grab the alloc page */
221 AllocPage
= CmpGetAllocPageFromDelayAlloc(Entry
);
223 /* Decrease free entries */
224 ASSERT(AllocPage
->FreeCount
!= 0);
225 AllocPage
->FreeCount
--;
227 /* Release the lock */
228 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);
232 /* Allocate an allocation page */
233 AllocPage
= CmpAllocate(PAGE_SIZE
, TRUE
, TAG_CM
);
236 /* Set default entries */
237 AllocPage
->FreeCount
= CM_DELAYS_PER_PAGE
;
239 /* Loop each entry */
240 for (i
= 0; i
< CM_DELAYS_PER_PAGE
; i
++)
242 /* Get this entry and link it */
243 Entry
= (PVOID
)((ULONG_PTR
)AllocPage
+
244 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
245 i
* sizeof(CM_DELAY_ALLOC
));
246 InsertTailList(&CmpFreeDelayItemsListHead
,
249 /* Clear the KCB pointer */
255 /* Release the lock */
256 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);
260 /* Do the search again */
266 CmpFreeDelayItem(PVOID Entry
)
268 PCM_DELAY_ALLOC AllocEntry
= (PCM_DELAY_ALLOC
)Entry
;
269 PCM_ALLOC_PAGE AllocPage
;
274 KeAcquireGuardedMutex(&CmpDelayAllocBucketLock
);
276 /* Add the entry at the end */
277 InsertTailList(&CmpFreeDelayItemsListHead
, &AllocEntry
->ListEntry
);
279 /* Get the alloc page */
280 AllocPage
= CmpGetAllocPageFromDelayAlloc(Entry
);
281 ASSERT(AllocPage
->FreeCount
!= CM_DELAYS_PER_PAGE
);
283 /* Increase the number of free items */
284 if (++AllocPage
->FreeCount
== CM_DELAYS_PER_PAGE
)
286 /* Page is totally free now, loop each entry */
287 for (i
= 0; i
< CM_DELAYS_PER_PAGE
; i
++)
289 /* Get the entry and unlink it */
290 AllocEntry
= (PVOID
)((ULONG_PTR
)AllocPage
+
291 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
292 i
* sizeof(CM_DELAY_ALLOC
));
293 RemoveEntryList(&AllocEntry
->ListEntry
);
296 /* Now free the page */
297 CmpFree(AllocPage
, TAG_CM
);
300 /* Release the lock */
301 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);