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 ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 BOOLEAN CmpAllocInited
;
19 KGUARDED_MUTEX CmpAllocBucketLock
, CmpDelayAllocBucketLock
;
21 LIST_ENTRY CmpFreeKCBListHead
;
22 KGUARDED_MUTEX CmpDelayAllocBucketLock
;
23 LIST_ENTRY CmpFreeDelayItemsListHead
;
25 /* 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
;
43 CmpInitCmPrivateDelayAlloc(VOID
)
45 /* Initialize the delay allocation list and lock */
46 KeInitializeGuardedMutex(&CmpDelayAllocBucketLock
);
47 InitializeListHead(&CmpFreeDelayItemsListHead
);
52 CmpFreeKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb
)
55 PCM_ALLOC_PAGE AllocPage
;
59 ASSERT(IsListEmpty(&(Kcb
->KeyBodyListHead
)) == TRUE
);
60 for (i
= 0; i
< 4; i
++) ASSERT(Kcb
->KeyBodyArray
[i
] == NULL
);
62 /* Check if it wasn't privately allocated */
63 if (!Kcb
->PrivateAlloc
)
65 /* Free it from the pool */
70 /* Acquire the private allocation lock */
71 KeAcquireGuardedMutex(&CmpAllocBucketLock
);
73 /* Sanity check on lock ownership */
74 ASSERT((GET_HASH_ENTRY(CmpCacheTable
, Kcb
->ConvKey
).Owner
==
75 KeGetCurrentThread()) ||
76 (CmpTestRegistryLockExclusive() == TRUE
));
78 /* Add us to the free list */
79 InsertTailList(&CmpFreeKCBListHead
, &Kcb
->FreeListEntry
);
81 /* Get the allocation page */
82 AllocPage
= (PCM_ALLOC_PAGE
)((ULONG_PTR
)Kcb
& 0xFFFFF000);
85 ASSERT(AllocPage
->FreeCount
!= CM_KCBS_PER_PAGE
);
87 /* Increase free count */
88 if (++AllocPage
->FreeCount
== CM_KCBS_PER_PAGE
)
90 /* Loop all the entries */
91 for (i
= CM_KCBS_PER_PAGE
; i
; i
--)
94 Kcb
= (PVOID
)((ULONG_PTR
)AllocPage
+
95 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
96 (i
- 1) * sizeof(CM_KEY_CONTROL_BLOCK
));
98 /* Remove the entry */
99 RemoveEntryList(&Kcb
->FreeListEntry
);
103 ExFreePool(AllocPage
);
106 /* Release the lock */
107 KeReleaseGuardedMutex(&CmpAllocBucketLock
);
110 PCM_KEY_CONTROL_BLOCK
112 CmpAllocateKeyControlBlock(VOID
)
114 PLIST_ENTRY NextEntry
;
115 PCM_KEY_CONTROL_BLOCK CurrentKcb
;
116 PCM_ALLOC_PAGE AllocPage
;
120 /* Check if private allocations are initialized */
123 /* They are, acquire the bucket lock */
124 KeAcquireGuardedMutex(&CmpAllocBucketLock
);
126 /* See if there's something on the free KCB list */
128 if (!IsListEmpty(&CmpFreeKCBListHead
))
130 /* Remove the entry */
131 NextEntry
= RemoveHeadList(&CmpFreeKCBListHead
);
134 CurrentKcb
= CONTAINING_RECORD(NextEntry
,
135 CM_KEY_CONTROL_BLOCK
,
138 /* Get the allocation page */
139 AllocPage
= (PCM_ALLOC_PAGE
)((ULONG_PTR
)CurrentKcb
& 0xFFFFF000);
141 /* Decrease the free count */
142 ASSERT(AllocPage
->FreeCount
!= 0);
143 AllocPage
->FreeCount
--;
145 /* Make sure this KCB is privately allocated */
146 ASSERT(CurrentKcb
->PrivateAlloc
== 1);
148 /* Release the allocation lock */
149 KeReleaseGuardedMutex(&CmpAllocBucketLock
);
155 /* Allocate an allocation page */
156 AllocPage
= ExAllocatePoolWithTag(PagedPool
, PAGE_SIZE
, TAG_CM
);
159 /* Set default entries */
160 AllocPage
->FreeCount
= CM_KCBS_PER_PAGE
;
162 /* Loop each entry */
163 for (i
= 0; i
< CM_KCBS_PER_PAGE
; i
++)
166 CurrentKcb
= (PVOID
)((ULONG_PTR
)AllocPage
+
167 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
168 i
* sizeof(CM_KEY_CONTROL_BLOCK
));
171 CurrentKcb
->PrivateAlloc
= TRUE
;
172 CurrentKcb
->DelayCloseEntry
= NULL
;
173 InsertHeadList(&CmpFreeKCBListHead
,
174 &CurrentKcb
->FreeListEntry
);
177 /* Now go back and search the list */
182 /* Allocate a KCB only */
183 CurrentKcb
= ExAllocatePoolWithTag(PagedPool
,
184 sizeof(CM_KEY_CONTROL_BLOCK
),
189 CurrentKcb
->PrivateAlloc
= 0;
190 CurrentKcb
->DelayCloseEntry
= NULL
;
199 CmpAllocateDelayItem(VOID
)
201 PCM_DELAY_ALLOC Entry
;
202 PCM_ALLOC_PAGE AllocPage
;
204 PLIST_ENTRY NextEntry
;
207 /* Lock the allocation buckets */
208 KeAcquireGuardedMutex(&CmpDelayAllocBucketLock
);
210 /* Look for an item on the free list */
212 if (!IsListEmpty(&CmpFreeDelayItemsListHead
))
214 /* Get the current entry in the list */
215 NextEntry
= RemoveHeadList(&CmpFreeDelayItemsListHead
);
218 Entry
= CONTAINING_RECORD(NextEntry
, CM_DELAY_ALLOC
, ListEntry
);
221 Entry
->ListEntry
.Flink
= Entry
->ListEntry
.Blink
= NULL
;
223 /* Grab the alloc page */
224 AllocPage
= (PCM_ALLOC_PAGE
)((ULONG_PTR
)Entry
& 0xFFFFF000);
226 /* Decrease free entries */
227 ASSERT(AllocPage
->FreeCount
!= 0);
228 AllocPage
->FreeCount
--;
230 /* Release the lock */
231 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);
235 /* Allocate an allocation page */
236 AllocPage
= ExAllocatePoolWithTag(PagedPool
, PAGE_SIZE
, TAG_CM
);
239 /* Set default entries */
240 AllocPage
->FreeCount
= CM_DELAYS_PER_PAGE
;
242 /* Loop each entry */
243 for (i
= 0; i
< CM_DELAYS_PER_PAGE
; i
++)
245 /* Get this entry and link it */
246 Entry
= (PVOID
)((ULONG_PTR
)AllocPage
+
247 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
248 i
* sizeof(CM_DELAY_ALLOC
));
249 InsertTailList(&CmpFreeDelayItemsListHead
,
252 /* Clear the KCB pointer */
258 /* Release the lock */
259 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);
263 /* Do the search again */
269 CmpFreeDelayItem(PVOID Entry
)
271 PCM_DELAY_ALLOC AllocEntry
= (PCM_DELAY_ALLOC
)Entry
;
272 PCM_ALLOC_PAGE AllocPage
;
277 KeAcquireGuardedMutex(&CmpDelayAllocBucketLock
);
279 /* Add the entry at the end */
280 InsertTailList(&CmpFreeDelayItemsListHead
, &AllocEntry
->ListEntry
);
282 /* Get the alloc page */
283 AllocPage
= (PCM_ALLOC_PAGE
)((ULONG_PTR
)Entry
& 0xFFFFF000);
284 ASSERT(AllocPage
->FreeCount
!= CM_DELAYS_PER_PAGE
);
286 /* Increase the number of free items */
287 if (++AllocPage
->FreeCount
== CM_DELAYS_PER_PAGE
)
289 /* Page is totally free now, loop each entry */
290 for (i
= 0; i
< CM_DELAYS_PER_PAGE
; i
++)
292 /* Get the entry and unlink it */
293 AllocEntry
= (PVOID
)((ULONG_PTR
)AllocPage
+
294 FIELD_OFFSET(CM_ALLOC_PAGE
, AllocPage
) +
295 i
* sizeof(CM_DELAY_ALLOC
));
296 RemoveEntryList(&AllocEntry
->ListEntry
);
299 /* Now free the page */
300 ExFreePool(AllocPage
);
303 /* Release the lock */
304 KeReleaseGuardedMutex(&CmpDelayAllocBucketLock
);