2 * PROJECT: ReactOS Drivers
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/sac/driver/memory.c
5 * PURPOSE: Driver for the Server Administration Console (SAC) for EMS
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
13 /* GLOBALS ********************************************************************/
15 LONG TotalFrees
, TotalBytesFreed
, TotalAllocations
, TotalBytesAllocated
;
16 KSPIN_LOCK MemoryLock
;
17 PSAC_MEMORY_LIST GlobalMemoryList
;
19 /* FUNCTIONS ******************************************************************/
23 InitializeMemoryManagement(VOID
)
25 PSAC_MEMORY_ENTRY Entry
;
26 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
28 /* Allocate a nonpaged heap for us to use */
29 GlobalMemoryList
= ExAllocatePoolWithTagPriority(NonPagedPool
,
35 /* Initialize a lock for it */
36 KeInitializeSpinLock(&MemoryLock
);
38 /* Initialize the head of the list */
39 GlobalMemoryList
->Signature
= GLOBAL_MEMORY_SIGNATURE
;
40 GlobalMemoryList
->LocalDescriptor
= (PSAC_MEMORY_ENTRY
)(GlobalMemoryList
+ 1);
41 GlobalMemoryList
->Size
= SAC_MEMORY_LIST_SIZE
- sizeof(SAC_MEMORY_LIST
);
42 GlobalMemoryList
->Next
= NULL
;
44 /* Initialize the first free entry */
45 Entry
= GlobalMemoryList
->LocalDescriptor
;
46 Entry
->Signature
= LOCAL_MEMORY_SIGNATURE
;
47 Entry
->Tag
= FREE_POOL_TAG
;
48 Entry
->Size
= GlobalMemoryList
->Size
- sizeof(SAC_MEMORY_ENTRY
);
51 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting with TRUE.\n");
55 /* No pool available to manage our heap */
56 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting with FALSE. No pool.\n");
62 FreeMemoryManagement(VOID
)
64 PSAC_MEMORY_LIST Next
;
66 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
68 /* Acquire the memory lock while freeing the list(s) */
69 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
70 while (GlobalMemoryList
)
72 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
74 /* While outisde of the lock, save the next list and free this one */
75 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
76 Next
= GlobalMemoryList
->Next
;
77 ExFreePoolWithTag(GlobalMemoryList
, 0);
79 /* Reacquire the lock and see if there was another list to free */
80 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
81 GlobalMemoryList
= Next
;
85 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
86 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting\n");
91 MyAllocatePool(IN SIZE_T PoolSize
,
97 p
= ExAllocatePoolWithTag(NonPagedPool
, PoolSize
, 'HACK');
98 RtlZeroMemory(p
, PoolSize
);
99 SAC_DBG(SAC_DBG_MM
, "Returning block 0x%X.\n", p
);
103 PSAC_MEMORY_LIST GlobalDescriptor
, NewDescriptor
;
104 PSAC_MEMORY_ENTRY LocalDescriptor
, NextDescriptor
;
105 ULONG GlobalSize
, ActualSize
;
108 ASSERT(Tag
!= FREE_POOL_TAG
);
109 SAC_DBG(SAC_DBG_MM
, "Entering.\n");
111 /* Acquire the memory allocation lock and align the size request */
112 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
113 PoolSize
= ALIGN_UP(PoolSize
, ULONGLONG
);
115 #if _USE_SAC_HEAP_ALLOCATOR_
116 GlobalDescriptor
= GlobalMemoryList
;
117 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
118 while (GlobalDescriptor
)
120 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
122 LocalDescriptor
= GlobalDescriptor
->LocalDescriptor
;
124 GlobalSize
= GlobalDescriptor
->Size
;
127 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
129 if ((LocalDescriptor
->Tag
== FREE_POOL_TAG
) &&
130 (LocalDescriptor
->Size
>= PoolSize
))
135 GlobalSize
-= (LocalDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
138 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
139 LocalDescriptor
->Size
+
140 sizeof(SAC_MEMORY_ENTRY
));
143 GlobalDescriptor
= GlobalDescriptor
->Next
;
146 if (!GlobalDescriptor
)
148 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
152 PoolSize
+ sizeof(SAC_MEMORY_ENTRY
) + sizeof(SAC_MEMORY_LIST
));
154 SAC_DBG(SAC_DBG_MM
, "Allocating new space.\n");
156 NewDescriptor
= ExAllocatePoolWithTagPriority(NonPagedPool
,
162 SAC_DBG(SAC_DBG_MM
, "No more memory, returning NULL.\n");
166 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
168 NewDescriptor
->Signature
= GLOBAL_MEMORY_SIGNATURE
;
169 NewDescriptor
->LocalDescriptor
= (PSAC_MEMORY_ENTRY
)(NewDescriptor
+ 1);
170 NewDescriptor
->Size
= ActualSize
- 16;
171 NewDescriptor
->Next
= GlobalMemoryList
;
173 GlobalMemoryList
= NewDescriptor
;
175 LocalDescriptor
= NewDescriptor
->LocalDescriptor
;
176 LocalDescriptor
->Signature
= LOCAL_MEMORY_SIGNATURE
;
177 LocalDescriptor
->Tag
= FREE_POOL_TAG
;
178 LocalDescriptor
->Size
=
179 GlobalMemoryList
->Size
- sizeof(SAC_MEMORY_ENTRY
);
182 SAC_DBG(SAC_DBG_MM
, "Found a good sized block.\n");
183 ASSERT(LocalDescriptor
->Tag
== FREE_POOL_TAG
);
184 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
186 if (LocalDescriptor
->Size
> (PoolSize
+ sizeof(SAC_MEMORY_ENTRY
)))
189 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
191 sizeof(SAC_MEMORY_ENTRY
));
192 if (NextDescriptor
->Tag
== FREE_POOL_TAG
)
194 NextDescriptor
->Tag
= FREE_POOL_TAG
;
195 NextDescriptor
->Signature
= LOCAL_MEMORY_SIGNATURE
;
196 NextDescriptor
->Size
=
197 (LocalDescriptor
->Size
- PoolSize
- sizeof(SAC_MEMORY_ENTRY
));
199 LocalDescriptor
->Size
= PoolSize
;
203 /* Shut the compiler up */
204 NewDescriptor
= GlobalDescriptor
= NULL
;
205 GlobalSize
= (ULONG
)NewDescriptor
;
206 ActualSize
= GlobalSize
;
207 NextDescriptor
= (PVOID
)ActualSize
;
208 NewDescriptor
= (PVOID
)NextDescriptor
;
210 /* Use the NT pool allocator */
211 LocalDescriptor
= ExAllocatePoolWithTag(NonPagedPool
,
212 PoolSize
+ sizeof(*LocalDescriptor
),
214 LocalDescriptor
->Size
= PoolSize
;
216 /* Set the tag, and release the lock */
217 LocalDescriptor
->Tag
= Tag
;
218 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
220 /* Update our performance counters */
221 InterlockedIncrement(&TotalAllocations
);
222 InterlockedExchangeAdd(&TotalBytesAllocated
, LocalDescriptor
->Size
);
224 /* Return the buffer and zero it */
225 SAC_DBG(SAC_DBG_MM
, "Returning block 0x%X.\n", LocalDescriptor
);
226 Buffer
= LocalDescriptor
+ 1;
227 RtlZeroMemory(Buffer
, PoolSize
);
234 MyFreePool(IN PVOID
*Block
)
237 PSAC_MEMORY_ENTRY NextDescriptor
;
238 PSAC_MEMORY_ENTRY ThisDescriptor
, FoundDescriptor
;
239 PSAC_MEMORY_ENTRY LocalDescriptor
= (PVOID
)((ULONG_PTR
)(*Block
) - sizeof(SAC_MEMORY_ENTRY
));
240 ULONG GlobalSize
, LocalSize
;
241 PSAC_MEMORY_LIST GlobalDescriptor
;
243 SAC_DBG(SAC_DBG_MM
, "Entering with block 0x%X.\n", LocalDescriptor
);
245 /* Make sure this was a valid entry */
246 ASSERT(LocalDescriptor
->Size
> 0);
247 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
249 /* Update performance counters */
250 InterlockedIncrement(&TotalFrees
);
251 InterlockedExchangeAdd(&TotalBytesFreed
, LocalDescriptor
->Size
);
253 /* Acquire the memory alliocation lock */
254 GlobalDescriptor
= GlobalMemoryList
;
255 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
257 #if _USE_SAC_HEAP_ALLOCATOR_
258 while (GlobalDescriptor
)
260 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
262 FoundDescriptor
= NULL
;
264 ThisDescriptor
= GlobalDescriptor
->LocalDescriptor
;
266 GlobalSize
= GlobalDescriptor
->Size
;
269 ASSERT(ThisDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
271 if (ThisDescriptor
== LocalDescriptor
) break;
273 GlobalSize
-= (ThisDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
276 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)ThisDescriptor
+
277 ThisDescriptor
->Size
+
278 sizeof(SAC_MEMORY_ENTRY
));
281 if (ThisDescriptor
== LocalDescriptor
) break;
283 GlobalDescriptor
= GlobalDescriptor
->Next
;
286 if (!GlobalDescriptor
)
288 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
289 SAC_DBG(SAC_DBG_MM
, "Could not find block.\n");
293 ASSERT(ThisDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
295 if (LocalDescriptor
->Tag
== FREE_POOL_TAG
)
297 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
298 SAC_DBG(SAC_DBG_MM
, "Attempted to free something twice.\n");
302 LocalSize
= LocalDescriptor
->Size
;
303 LocalDescriptor
->Tag
= FREE_POOL_TAG
;
305 if (GlobalSize
> (LocalSize
+ sizeof(SAC_MEMORY_ENTRY
)))
308 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
310 sizeof(SAC_MEMORY_ENTRY
));
311 if (NextDescriptor
->Tag
== FREE_POOL_TAG
)
313 NextDescriptor
->Tag
= 0;
314 NextDescriptor
->Signature
= 0;
316 LocalDescriptor
->Size
+=
317 (NextDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
321 if ((FoundDescriptor
) && (FoundDescriptor
->Tag
== FREE_POOL_TAG
))
323 LocalDescriptor
->Signature
= 0;
324 LocalDescriptor
->Tag
= 0;
326 FoundDescriptor
->Size
+=
327 (LocalDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
330 /* Shut the compiler up */
331 LocalSize
= GlobalSize
= 0;
332 ThisDescriptor
= (PVOID
)LocalSize
;
333 NextDescriptor
= (PVOID
)GlobalSize
;
334 GlobalDescriptor
= (PVOID
)ThisDescriptor
;
335 FoundDescriptor
= (PVOID
)GlobalDescriptor
;
336 GlobalDescriptor
= (PVOID
)NextDescriptor
;
337 NextDescriptor
= (PVOID
)FoundDescriptor
;
339 /* Use the NT pool allocator*/
340 ExFreePool(LocalDescriptor
);
343 /* Release the lock, delete the address, and return */
344 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
346 SAC_DBG(SAC_DBG_MM
, "exiting: 0x%p.\n", *Block
);
347 ExFreePoolWithTag(*Block
, 'HACK');