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 *****************************************************************/
28 CmpInitCmPrivateAlloc(VOID
)
30 /* Make sure we didn't already do this */
33 /* Setup the lock and list */
34 KeInitializeGuardedMutex(&CmpAllocBucketLock
);
35 InitializeListHead(&CmpFreeKCBListHead
);
36 CmpAllocInited
= TRUE
;
42 CmpInitCmPrivateDelayAlloc(VOID
)
44 /* Initialize the delay allocation list and lock */
45 KeInitializeGuardedMutex(&CmpDelayAllocBucketLock
);
46 InitializeListHead(&CmpFreeDelayItemsListHead
);
51 CmpFreeKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb
)
54 PCM_ALLOC_PAGE AllocPage
;
58 ASSERT(IsListEmpty(&Kcb
->KeyBodyListHead
) == TRUE
);
59 for (i
= 0; i
< 4; i
++) ASSERT(Kcb
->KeyBodyArray
[i
] == NULL
);
61 /* Check if it wasn't privately allocated */
62 if (!Kcb
->PrivateAlloc
)
64 /* Free it from the pool */
69 /* Acquire the private allocation lock */
70 KeAcquireGuardedMutex(&CmpAllocBucketLock
);
72 /* Sanity check on lock ownership */
73 CMP_ASSERT_HASH_ENTRY_LOCK(Kcb
->ConvKey
);
75 /* Add us to the free list */
76 InsertTailList(&CmpFreeKCBListHead
, &Kcb
->FreeListEntry
);
78 /* Get the allocation page */
79 AllocPage
= CmpGetAllocPageFromKcb(Kcb
);
82 ASSERT(AllocPage
->FreeCount
!= CM_KCBS_PER_PAGE
);
84 /* Increase free count */
85 if (++AllocPage
->FreeCount
== CM_KCBS_PER_PAGE
)
87 /* Loop all the entries */
88 for (i
= 0; i
< CM_KCBS_PER_PAGE
; i
++)
91 Kcb
= (PVOID
)((ULONG_PTR
)AllocPage
+
92 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
93 i
* sizeof(CM_KEY_CONTROL_BLOCK
));
95 /* Remove the entry */
96 RemoveEntryList(&Kcb
->FreeListEntry
);
100 CmpFree(AllocPage
, 0);
103 /* Release the lock */
104 KeReleaseGuardedMutex(&CmpAllocBucketLock
);
107 PCM_KEY_CONTROL_BLOCK
109 CmpAllocateKeyControlBlock(VOID
)
111 PLIST_ENTRY NextEntry
;
112 PCM_KEY_CONTROL_BLOCK CurrentKcb
;
113 PCM_ALLOC_PAGE AllocPage
;
117 /* Check if private allocations are initialized */
120 /* They are, acquire the bucket lock */
121 KeAcquireGuardedMutex(&CmpAllocBucketLock
);
123 /* See if there's something on the free KCB list */
125 if (!IsListEmpty(&CmpFreeKCBListHead
))
127 /* Remove the entry */
128 NextEntry
= RemoveHeadList(&CmpFreeKCBListHead
);
131 CurrentKcb
= CONTAINING_RECORD(NextEntry
,
132 CM_KEY_CONTROL_BLOCK
,
135 /* Get the allocation page */
136 AllocPage
= CmpGetAllocPageFromKcb(CurrentKcb
);
138 /* Decrease the free count */
139 ASSERT(AllocPage
->FreeCount
!= 0);
140 AllocPage
->FreeCount
--;
142 /* Make sure this KCB is privately allocated */
143 ASSERT(CurrentKcb
->PrivateAlloc
== 1);
145 /* Release the allocation lock */
146 KeReleaseGuardedMutex(&CmpAllocBucketLock
);
152 /* Allocate an allocation page */
153 AllocPage
= CmpAllocate(PAGE_SIZE
, TRUE
, TAG_CM
);
156 /* Set default entries */
157 AllocPage
->FreeCount
= CM_KCBS_PER_PAGE
;
159 /* Loop each entry */
160 for (i
= 0; i
< CM_KCBS_PER_PAGE
; i
++)
163 CurrentKcb
= (PVOID
)((ULONG_PTR
)AllocPage
+
164 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
165 i
* sizeof(CM_KEY_CONTROL_BLOCK
));
168 CurrentKcb
->PrivateAlloc
= TRUE
;
169 CurrentKcb
->DelayCloseEntry
= NULL
;
170 InsertTailList(&CmpFreeKCBListHead
,
171 &CurrentKcb
->FreeListEntry
);
174 /* Now go back and search the list */
179 /* Allocate a KCB only */
180 CurrentKcb
= CmpAllocate(sizeof(CM_KEY_CONTROL_BLOCK
), TRUE
, TAG_CM
);
184 CurrentKcb
->PrivateAlloc
= 0;
185 CurrentKcb
->DelayCloseEntry
= NULL
;
194 CmpAllocateDelayItem(VOID
)
196 PCM_DELAY_ALLOC Entry
;
197 PCM_ALLOC_PAGE AllocPage
;
199 PLIST_ENTRY NextEntry
;
202 /* Lock the allocation buckets */
203 KeAcquireGuardedMutex(&CmpDelayAllocBucketLock
);
205 /* Look for an item on the free list */
207 if (!IsListEmpty(&CmpFreeDelayItemsListHead
))
209 /* Get the current entry in the list */
210 NextEntry
= RemoveHeadList(&CmpFreeDelayItemsListHead
);
213 Entry
= CONTAINING_RECORD(NextEntry
, CM_DELAY_ALLOC
, ListEntry
);
216 Entry
->ListEntry
.Flink
= Entry
->ListEntry
.Blink
= NULL
;
218 /* Grab the alloc page */
219 AllocPage
= CmpGetAllocPageFromDelayAlloc(Entry
);
221 /* Decrease free entries */
222 ASSERT(AllocPage
->FreeCount
!= 0);
223 AllocPage
->FreeCount
--;
225 /* Release the lock */
226 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);
230 /* Allocate an allocation page */
231 AllocPage
= CmpAllocate(PAGE_SIZE
, TRUE
, TAG_CM
);
234 /* Set default entries */
235 AllocPage
->FreeCount
= CM_DELAYS_PER_PAGE
;
237 /* Loop each entry */
238 for (i
= 0; i
< CM_DELAYS_PER_PAGE
; i
++)
240 /* Get this entry and link it */
241 Entry
= (PVOID
)((ULONG_PTR
)AllocPage
+
242 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
243 i
* sizeof(CM_DELAY_ALLOC
));
244 InsertTailList(&CmpFreeDelayItemsListHead
,
247 /* Clear the KCB pointer */
253 /* Release the lock */
254 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);
258 /* Do the search again */
264 CmpFreeDelayItem(PVOID Entry
)
266 PCM_DELAY_ALLOC AllocEntry
= (PCM_DELAY_ALLOC
)Entry
;
267 PCM_ALLOC_PAGE AllocPage
;
272 KeAcquireGuardedMutex(&CmpDelayAllocBucketLock
);
274 /* Add the entry at the end */
275 InsertTailList(&CmpFreeDelayItemsListHead
, &AllocEntry
->ListEntry
);
277 /* Get the alloc page */
278 AllocPage
= CmpGetAllocPageFromDelayAlloc(Entry
);
279 ASSERT(AllocPage
->FreeCount
!= CM_DELAYS_PER_PAGE
);
281 /* Increase the number of free items */
282 if (++AllocPage
->FreeCount
== CM_DELAYS_PER_PAGE
)
284 /* Page is totally free now, loop each entry */
285 for (i
= 0; i
< CM_DELAYS_PER_PAGE
; i
++)
287 /* Get the entry and unlink it */
288 AllocEntry
= (PVOID
)((ULONG_PTR
)AllocPage
+
289 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
290 i
* sizeof(CM_DELAY_ALLOC
));
291 RemoveEntryList(&AllocEntry
->ListEntry
);
294 /* Now free the page */
295 CmpFree(AllocPage
, 0);
298 /* Release the lock */
299 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);