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 */
65 ExFreePoolWithTag(Kcb
, TAG_CM
);
69 /* Acquire the private allocation lock */
70 KeAcquireGuardedMutex(&CmpAllocBucketLock
);
72 /* Sanity check on lock ownership */
73 //ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) ||
74 // (CmpTestRegistryLockExclusive() == TRUE));
76 /* Add us to the free list */
77 InsertTailList(&CmpFreeKCBListHead
, &Kcb
->FreeListEntry
);
79 /* Get the allocation page */
80 AllocPage
= (PCM_ALLOC_PAGE
)((ULONG_PTR
)Kcb
& 0xFFFFF000);
83 ASSERT(AllocPage
->FreeCount
!= CM_KCBS_PER_PAGE
);
85 /* Increase free count */
86 if (++AllocPage
->FreeCount
== CM_KCBS_PER_PAGE
)
88 /* Loop all the entries */
89 for (i
= 0; i
< CM_KCBS_PER_PAGE
; i
++)
92 Kcb
= (PVOID
)((ULONG_PTR
)AllocPage
+
93 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
94 i
* sizeof(CM_KEY_CONTROL_BLOCK
));
96 /* Remove the entry */
97 RemoveEntryList(&Kcb
->FreeListEntry
);
101 ExFreePoolWithTag(AllocPage
, TAG_CM
);
104 /* Release the lock */
105 KeReleaseGuardedMutex(&CmpAllocBucketLock
);
108 PCM_KEY_CONTROL_BLOCK
110 CmpAllocateKeyControlBlock(VOID
)
112 PLIST_ENTRY NextEntry
;
113 PCM_KEY_CONTROL_BLOCK CurrentKcb
;
114 PCM_ALLOC_PAGE AllocPage
;
118 /* Check if private allocations are initialized */
121 /* They are, acquire the bucket lock */
122 KeAcquireGuardedMutex(&CmpAllocBucketLock
);
124 /* See if there's something on the free KCB list */
126 if (!IsListEmpty(&CmpFreeKCBListHead
))
128 /* Remove the entry */
129 NextEntry
= RemoveHeadList(&CmpFreeKCBListHead
);
132 CurrentKcb
= CONTAINING_RECORD(NextEntry
,
133 CM_KEY_CONTROL_BLOCK
,
136 /* Get the allocation page */
137 AllocPage
= (PCM_ALLOC_PAGE
)((ULONG_PTR
)CurrentKcb
& 0xFFFFF000);
139 /* Decrease the free count */
140 ASSERT(AllocPage
->FreeCount
!= 0);
141 AllocPage
->FreeCount
--;
143 /* Make sure this KCB is privately allocated */
144 ASSERT(CurrentKcb
->PrivateAlloc
== 1);
146 /* Release the allocation lock */
147 KeReleaseGuardedMutex(&CmpAllocBucketLock
);
153 /* Allocate an allocation page */
154 AllocPage
= ExAllocatePoolWithTag(PagedPool
, PAGE_SIZE
, TAG_CM
);
157 /* Set default entries */
158 AllocPage
->FreeCount
= CM_KCBS_PER_PAGE
;
160 /* Loop each entry */
161 for (i
= 0; i
< CM_KCBS_PER_PAGE
; i
++)
164 CurrentKcb
= (PVOID
)((ULONG_PTR
)AllocPage
+
165 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
166 i
* sizeof(CM_KEY_CONTROL_BLOCK
));
169 CurrentKcb
->PrivateAlloc
= TRUE
;
170 CurrentKcb
->DelayCloseEntry
= NULL
;
171 InsertHeadList(&CmpFreeKCBListHead
,
172 &CurrentKcb
->FreeListEntry
);
175 /* Now go back and search the list */
180 /* Allocate a KCB only */
181 CurrentKcb
= ExAllocatePoolWithTag(PagedPool
,
182 sizeof(CM_KEY_CONTROL_BLOCK
),
187 CurrentKcb
->PrivateAlloc
= 0;
188 CurrentKcb
->DelayCloseEntry
= NULL
;
197 CmpAllocateDelayItem(VOID
)
199 PCM_DELAY_ALLOC Entry
;
200 PCM_ALLOC_PAGE AllocPage
;
202 PLIST_ENTRY NextEntry
;
205 /* Lock the allocation buckets */
206 KeAcquireGuardedMutex(&CmpDelayAllocBucketLock
);
208 /* Look for an item on the free list */
210 if (!IsListEmpty(&CmpFreeDelayItemsListHead
))
212 /* Get the current entry in the list */
213 NextEntry
= RemoveHeadList(&CmpFreeDelayItemsListHead
);
216 Entry
= CONTAINING_RECORD(NextEntry
, CM_DELAY_ALLOC
, ListEntry
);
219 Entry
->ListEntry
.Flink
= Entry
->ListEntry
.Blink
= NULL
;
221 /* Grab the alloc page */
222 AllocPage
= (PCM_ALLOC_PAGE
)((ULONG_PTR
)Entry
& 0xFFFFF000);
224 /* Decrease free entries */
225 ASSERT(AllocPage
->FreeCount
!= 0);
226 AllocPage
->FreeCount
--;
228 /* Release the lock */
229 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);
233 /* Allocate an allocation page */
234 AllocPage
= ExAllocatePoolWithTag(PagedPool
, PAGE_SIZE
, TAG_CM
);
237 /* Set default entries */
238 AllocPage
->FreeCount
= CM_DELAYS_PER_PAGE
;
240 /* Loop each entry */
241 for (i
= 0; i
< CM_DELAYS_PER_PAGE
; i
++)
243 /* Get this entry and link it */
244 Entry
= (PVOID
)((ULONG_PTR
)AllocPage
+
245 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
246 i
* sizeof(CM_DELAY_ALLOC
));
247 InsertTailList(&CmpFreeDelayItemsListHead
,
250 /* Clear the KCB pointer */
256 /* Release the lock */
257 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);
261 /* Do the search again */
267 CmpFreeDelayItem(PVOID Entry
)
269 PCM_DELAY_ALLOC AllocEntry
= (PCM_DELAY_ALLOC
)Entry
;
270 PCM_ALLOC_PAGE AllocPage
;
275 KeAcquireGuardedMutex(&CmpDelayAllocBucketLock
);
277 /* Add the entry at the end */
278 InsertTailList(&CmpFreeDelayItemsListHead
, &AllocEntry
->ListEntry
);
280 /* Get the alloc page */
281 AllocPage
= (PCM_ALLOC_PAGE
)((ULONG_PTR
)Entry
& 0xFFFFF000);
282 ASSERT(AllocPage
->FreeCount
!= CM_DELAYS_PER_PAGE
);
284 /* Increase the number of free items */
285 if (++AllocPage
->FreeCount
== CM_DELAYS_PER_PAGE
)
287 /* Page is totally free now, loop each entry */
288 for (i
= 0; i
< CM_DELAYS_PER_PAGE
; i
++)
290 /* Get the entry and unlink it */
291 AllocEntry
= (PVOID
)((ULONG_PTR
)AllocPage
+
292 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
293 i
* sizeof(CM_DELAY_ALLOC
));
294 RemoveEntryList(&AllocEntry
->ListEntry
);
297 /* Now free the page */
298 ExFreePoolWithTag(AllocPage
, TAG_CM
);
301 /* Release the lock */
302 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);