ReactOS  0.4.14-dev-342-gdc047f9
cmalloc.c
Go to the documentation of this file.
1 /*
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)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* GLOBALS *******************************************************************/
16 
19 
23 
24 /* FUNCTIONS *****************************************************************/
25 
26 INIT_FUNCTION
27 VOID
28 NTAPI
30 {
31  /* Make sure we didn't already do this */
32  if (!CmpAllocInited)
33  {
34  /* Setup the lock and list */
38  }
39 }
40 
41 INIT_FUNCTION
42 VOID
43 NTAPI
45 {
46  /* Initialize the delay allocation list and lock */
49 }
50 
51 VOID
52 NTAPI
54 {
55  ULONG i;
56  PCM_ALLOC_PAGE AllocPage;
57  PAGED_CODE();
58 
59  /* Sanity checks */
60  ASSERT(IsListEmpty(&Kcb->KeyBodyListHead) == TRUE);
61  for (i = 0; i < 4; i++) ASSERT(Kcb->KeyBodyArray[i] == NULL);
62 
63  /* Check if it wasn't privately allocated */
64  if (!Kcb->PrivateAlloc)
65  {
66  /* Free it from the pool */
67  CmpFree(Kcb, TAG_KCB);
68  return;
69  }
70 
71  /* Acquire the private allocation lock */
73 
74  /* Sanity check on lock ownership */
75  CMP_ASSERT_HASH_ENTRY_LOCK(Kcb->ConvKey);
76 
77  /* Add us to the free list */
78  InsertTailList(&CmpFreeKCBListHead, &Kcb->FreeListEntry);
79 
80  /* Get the allocation page */
81  AllocPage = CmpGetAllocPageFromKcb(Kcb);
82 
83  /* Sanity check */
84  ASSERT(AllocPage->FreeCount != CM_KCBS_PER_PAGE);
85 
86  /* Increase free count */
87  if (++AllocPage->FreeCount == CM_KCBS_PER_PAGE)
88  {
89  /* Loop all the entries */
90  for (i = 0; i < CM_KCBS_PER_PAGE; i++)
91  {
92  /* Get the KCB */
93  Kcb = (PVOID)((ULONG_PTR)AllocPage +
94  FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) +
95  i * sizeof(CM_KEY_CONTROL_BLOCK));
96 
97  /* Remove the entry */
98  RemoveEntryList(&Kcb->FreeListEntry);
99  }
100 
101  /* Free the page */
102  CmpFree(AllocPage, TAG_KCB);
103  }
104 
105  /* Release the lock */
107 }
108 
110 NTAPI
112 {
113  PLIST_ENTRY NextEntry;
114  PCM_KEY_CONTROL_BLOCK CurrentKcb;
115  PCM_ALLOC_PAGE AllocPage;
116  ULONG i;
117  PAGED_CODE();
118 
119  /* Check if private allocations are initialized */
120  if (CmpAllocInited)
121  {
122  /* They are, acquire the bucket lock */
124 
125  /* See if there's something on the free KCB list */
126 SearchKcbList:
128  {
129  /* Remove the entry */
130  NextEntry = RemoveHeadList(&CmpFreeKCBListHead);
131 
132  /* Get the KCB */
133  CurrentKcb = CONTAINING_RECORD(NextEntry,
135  FreeListEntry);
136 
137  /* Get the allocation page */
138  AllocPage = CmpGetAllocPageFromKcb(CurrentKcb);
139 
140  /* Decrease the free count */
141  ASSERT(AllocPage->FreeCount != 0);
142  AllocPage->FreeCount--;
143 
144  /* Make sure this KCB is privately allocated */
145  ASSERT(CurrentKcb->PrivateAlloc == 1);
146 
147  /* Release the allocation lock */
149 
150  /* Return the KCB */
151  return CurrentKcb;
152  }
153 
154  /* Allocate an allocation page */
155  AllocPage = CmpAllocate(PAGE_SIZE, TRUE, TAG_KCB);
156  if (AllocPage)
157  {
158  /* Set default entries */
159  AllocPage->FreeCount = CM_KCBS_PER_PAGE;
160 
161  /* Loop each entry */
162  for (i = 0; i < CM_KCBS_PER_PAGE; i++)
163  {
164  /* Get this entry */
165  CurrentKcb = (PVOID)((ULONG_PTR)AllocPage +
166  FIELD_OFFSET(CM_ALLOC_PAGE, AllocPage) +
167  i * sizeof(CM_KEY_CONTROL_BLOCK));
168 
169  /* Set it up */
170  CurrentKcb->PrivateAlloc = TRUE;
171  CurrentKcb->DelayCloseEntry = NULL;
173  &CurrentKcb->FreeListEntry);
174  }
175 
176  /* Now go back and search the list */
177  goto SearchKcbList;
178  }
179  }
180 
181  /* Allocate a KCB only */
182  CurrentKcb = CmpAllocate(sizeof(CM_KEY_CONTROL_BLOCK), TRUE, TAG_KCB);
183  if (CurrentKcb)
184  {
185  /* Set it up */
186  CurrentKcb->PrivateAlloc = 0;
187  CurrentKcb->DelayCloseEntry = NULL;
188  }
189 
190  /* Return it */
191  return CurrentKcb;
192 }
193 
194 PVOID
195 NTAPI
197 {
199  PCM_ALLOC_PAGE AllocPage;
200  ULONG i;
201  PLIST_ENTRY NextEntry;
202  PAGED_CODE();
203 
204  /* Lock the allocation buckets */
206 
207  /* Look for an item on the free list */
208 SearchList:
210  {
211  /* Get the current entry in the list */
213 
214  /* Grab the item */
215  Entry = CONTAINING_RECORD(NextEntry, CM_DELAY_ALLOC, ListEntry);
216 
217  /* Clear the list */
218  Entry->ListEntry.Flink = Entry->ListEntry.Blink = NULL;
219 
220  /* Grab the alloc page */
222 
223  /* Decrease free entries */
224  ASSERT(AllocPage->FreeCount != 0);
225  AllocPage->FreeCount--;
226 
227  /* Release the lock */
229  return Entry;
230  }
231 
232  /* Allocate an allocation page */
233  AllocPage = CmpAllocate(PAGE_SIZE, TRUE, TAG_CM);
234  if (AllocPage)
235  {
236  /* Set default entries */
237  AllocPage->FreeCount = CM_DELAYS_PER_PAGE;
238 
239  /* Loop each entry */
240  for (i = 0; i < CM_DELAYS_PER_PAGE; i++)
241  {
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));
247  &Entry->ListEntry);
248 
249  /* Clear the KCB pointer */
250  Entry->Kcb = NULL;
251  }
252  }
253  else
254  {
255  /* Release the lock */
257  return NULL;
258  }
259 
260  /* Do the search again */
261  goto SearchList;
262 }
263 
264 VOID
265 NTAPI
267 {
268  PCM_DELAY_ALLOC AllocEntry = (PCM_DELAY_ALLOC)Entry;
269  PCM_ALLOC_PAGE AllocPage;
270  ULONG i;
271  PAGED_CODE();
272 
273  /* Lock the table */
275 
276  /* Add the entry at the end */
278 
279  /* Get the alloc page */
281  ASSERT(AllocPage->FreeCount != CM_DELAYS_PER_PAGE);
282 
283  /* Increase the number of free items */
284  if (++AllocPage->FreeCount == CM_DELAYS_PER_PAGE)
285  {
286  /* Page is totally free now, loop each entry */
287  for (i = 0; i < CM_DELAYS_PER_PAGE; i++)
288  {
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);
294  }
295 
296  /* Now free the page */
297  CmpFree(AllocPage, TAG_CM);
298  }
299 
300  /* Release the lock */
302 }
INIT_FUNCTION VOID NTAPI CmpInitCmPrivateAlloc(VOID)
Definition: cmalloc.c:29
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
struct _Entry Entry
Definition: kefuncs.h:640
ULONG FreeCount
Definition: cm.h:340
VOID FASTCALL KeAcquireGuardedMutex(IN PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:42
PVOID NTAPI CmpAllocate(_In_ SIZE_T Size, _In_ BOOLEAN Paged, _In_ ULONG Tag)
Definition: bootreg.c:90
#define InsertTailList(ListHead, Entry)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define PAGED_CODE()
Definition: video.h:57
#define CMP_ASSERT_HASH_ENTRY_LOCK(k)
Definition: cm_x.h:235
PVOID NTAPI CmpAllocateDelayItem(VOID)
Definition: cmalloc.c:196
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
KGUARDED_MUTEX CmpDelayAllocBucketLock
Definition: cmalloc.c:18
ULONG PrivateAlloc
Definition: cm.h:265
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
#define CM_KCBS_PER_PAGE
Definition: cm.h:124
struct _CM_KEY_CONTROL_BLOCK CM_KEY_CONTROL_BLOCK
void * PVOID
Definition: retypes.h:9
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID NTAPI CmpFree(_In_ PVOID Ptr, _In_ ULONG Quota)
Definition: bootreg.c:105
struct _CM_DELAY_ALLOC * PCM_DELAY_ALLOC
LIST_ENTRY CmpFreeKCBListHead
Definition: cmalloc.c:20
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define TAG_CM
Definition: cmlib.h:203
PCM_KEY_CONTROL_BLOCK NTAPI CmpAllocateKeyControlBlock(VOID)
Definition: cmalloc.c:111
#define PAGE_SIZE
Definition: env_spec_w32.h:49
Definition: typedefs.h:117
#define TAG_KCB
Definition: cmlib.h:204
LIST_ENTRY ListEntry
Definition: cm.h:350
BOOLEAN CmpAllocInited
Definition: cmalloc.c:17
VOID FASTCALL KeInitializeGuardedMutex(OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:31
#define CmpGetAllocPageFromKcb(k)
Definition: cm_x.h:254
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
VOID NTAPI CmpFreeKeyControlBlock(IN PCM_KEY_CONTROL_BLOCK Kcb)
Definition: cmalloc.c:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define CmpGetAllocPageFromDelayAlloc(a)
Definition: cm_x.h:260
VOID NTAPI CmpFreeDelayItem(PVOID Entry)
Definition: cmalloc.c:266
VOID FASTCALL KeReleaseGuardedMutex(IN OUT PKGUARDED_MUTEX GuardedMutex)
Definition: gmutex.c:53
struct _CM_DELAY_ALLOC CM_DELAY_ALLOC
KGUARDED_MUTEX CmpAllocBucketLock
Definition: cmalloc.c:18
unsigned int ULONG
Definition: retypes.h:1
INIT_FUNCTION VOID NTAPI CmpInitCmPrivateDelayAlloc(VOID)
Definition: cmalloc.c:44
PVOID DelayCloseEntry
Definition: cm.h:297
LIST_ENTRY FreeListEntry
Definition: cm.h:294
#define CM_DELAYS_PER_PAGE
Definition: cm.h:126
base of all file and directory entries
Definition: entries.h:82
LIST_ENTRY CmpFreeDelayItemsListHead
Definition: cmalloc.c:22