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 PSAC_MEMORY_LIST GlobalDescriptor
, NewDescriptor
;
98 PSAC_MEMORY_ENTRY LocalDescriptor
, NextDescriptor
;
99 ULONG GlobalSize
, ActualSize
;
101 ASSERT("Tag != FREE_POOL_TAG");
102 SAC_DBG(SAC_DBG_MM
, "Entering.\n");
104 /* Acquire the memory allocation lock and align the size request */
105 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);;
106 PoolSize
= ALIGN_UP(PoolSize
, ULONGLONG
);
108 #if _USE_SAC_HEAP_ALLOCATOR_
109 GlobalDescriptor
= GlobalMemoryList
;
110 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
111 while (GlobalDescriptor
)
113 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
115 LocalDescriptor
= GlobalDescriptor
->LocalDescriptor
;
117 GlobalSize
= GlobalDescriptor
->Size
;
120 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
122 if ((LocalDescriptor
->Tag
== FREE_POOL_TAG
) &&
123 (LocalDescriptor
->Size
>= PoolSize
))
128 GlobalSize
-= (LocalDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
131 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
132 LocalDescriptor
->Size
+
133 sizeof(SAC_MEMORY_ENTRY
));
136 GlobalDescriptor
= GlobalDescriptor
->Next
;
139 if (!GlobalDescriptor
)
141 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
145 PoolSize
+ sizeof(SAC_MEMORY_ENTRY
) + sizeof(SAC_MEMORY_LIST
));
147 SAC_DBG(SAC_DBG_MM
, "Allocating new space.\n");
149 NewDescriptor
= ExAllocatePoolWithTagPriority(
156 SAC_DBG(SAC_DBG_MM
, "No more memory, returning NULL.\n");
160 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
162 NewDescriptor
->Signature
= GLOBAL_MEMORY_SIGNATURE
;
163 NewDescriptor
->LocalDescriptor
= (PSAC_MEMORY_ENTRY
)(NewDescriptor
+ 1);
164 NewDescriptor
->Size
= ActualSize
- 16;
165 NewDescriptor
->Next
= GlobalMemoryList
;
167 GlobalMemoryList
= NewDescriptor
;
169 LocalDescriptor
= NewDescriptor
->LocalDescriptor
;
170 LocalDescriptor
->Signature
= LOCAL_MEMORY_SIGNATURE
;
171 LocalDescriptor
->Tag
= FREE_POOL_TAG
;
172 LocalDescriptor
->Size
=
173 GlobalMemoryList
->Size
- sizeof(SAC_MEMORY_ENTRY
);
176 SAC_DBG(SAC_DBG_MM
, "Found a good sized block.\n");
177 ASSERT(LocalDescriptor
->Tag
== FREE_POOL_TAG
);
178 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
180 if (LocalDescriptor
->Size
> (PoolSize
+ sizeof(SAC_MEMORY_ENTRY
)))
183 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
185 sizeof(SAC_MEMORY_ENTRY
));
186 if (NextDescriptor
->Tag
== FREE_POOL_TAG
)
188 NextDescriptor
->Tag
= FREE_POOL_TAG
;
189 NextDescriptor
->Signature
= LOCAL_MEMORY_SIGNATURE
;
190 NextDescriptor
->Size
=
191 (LocalDescriptor
->Size
- PoolSize
- sizeof(SAC_MEMORY_ENTRY
));
193 LocalDescriptor
->Size
= PoolSize
;
197 /* Shut the compiler up */
198 NewDescriptor
= GlobalDescriptor
= NULL
;
199 GlobalSize
= (ULONG
)NewDescriptor
;
200 ActualSize
= GlobalSize
;
201 NextDescriptor
= (PVOID
)ActualSize
;
202 NewDescriptor
= (PVOID
)NextDescriptor
;
204 /* Use the NT pool allocator */
205 LocalDescriptor
= ExAllocatePoolWithTag(NonPagedPool
,
206 PoolSize
+ sizeof(*LocalDescriptor
),
208 LocalDescriptor
->Size
= PoolSize
;
210 /* Set the tag, and release the lock */
211 LocalDescriptor
->Tag
= Tag
;
212 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
214 /* Update our performance counters */
215 InterlockedIncrement(&TotalAllocations
);
216 InterlockedExchangeAdd(&TotalBytesAllocated
, LocalDescriptor
->Size
);
218 /* Return the buffer and zero it */
219 SAC_DBG(SAC_DBG_MM
, "Returning block 0x%X.\n", LocalDescriptor
);
220 Buffer
= LocalDescriptor
+ 1;
221 RtlZeroMemory(Buffer
, PoolSize
);
227 MyFreePool(IN PVOID
*Block
)
229 PSAC_MEMORY_ENTRY NextDescriptor
;
230 PSAC_MEMORY_ENTRY ThisDescriptor
, FoundDescriptor
;
231 PSAC_MEMORY_ENTRY LocalDescriptor
= (PVOID
)((ULONG_PTR
)(*Block
) - sizeof(SAC_MEMORY_ENTRY
));
232 ULONG GlobalSize
, LocalSize
;
233 PSAC_MEMORY_LIST GlobalDescriptor
;
235 SAC_DBG(SAC_DBG_MM
, "Entering with block 0x%X.\n", LocalDescriptor
);
237 /* Make sure this was a valid entry */
238 ASSERT(LocalDescriptor
->Size
> 0);
239 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
241 /* Update performance counters */
242 InterlockedIncrement(&TotalFrees
);
243 InterlockedExchangeAdd(&TotalBytesFreed
, LocalDescriptor
->Size
);
245 /* Acquire the memory alliocation lock */
246 GlobalDescriptor
= GlobalMemoryList
;
247 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
249 #if _USE_SAC_HEAP_ALLOCATOR_
250 while (GlobalDescriptor
)
252 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
254 FoundDescriptor
= NULL
;
256 ThisDescriptor
= GlobalDescriptor
->LocalDescriptor
;
258 GlobalSize
= GlobalDescriptor
->Size
;
261 ASSERT(ThisDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
263 if (ThisDescriptor
== LocalDescriptor
) break;
265 GlobalSize
-= (ThisDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
268 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)ThisDescriptor
+
269 ThisDescriptor
->Size
+
270 sizeof(SAC_MEMORY_ENTRY
));
273 if (ThisDescriptor
== LocalDescriptor
) break;
275 GlobalDescriptor
= GlobalDescriptor
->Next
;
278 if (!GlobalDescriptor
)
280 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
281 SAC_DBG(SAC_DBG_MM
, "Could not find block.\n");
285 ASSERT(ThisDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
287 if (LocalDescriptor
->Tag
== FREE_POOL_TAG
)
289 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
290 SAC_DBG(SAC_DBG_MM
, "Attempted to free something twice.\n");
294 LocalSize
= LocalDescriptor
->Size
;
295 LocalDescriptor
->Tag
= FREE_POOL_TAG
;
297 if (GlobalSize
> (LocalSize
+ sizeof(SAC_MEMORY_ENTRY
)))
300 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
302 sizeof(SAC_MEMORY_ENTRY
));
303 if (NextDescriptor
->Tag
== FREE_POOL_TAG
)
305 NextDescriptor
->Tag
= 0;
306 NextDescriptor
->Signature
= 0;
308 LocalDescriptor
->Size
+=
309 (NextDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
313 if ((FoundDescriptor
) && (FoundDescriptor
->Tag
== FREE_POOL_TAG
))
315 LocalDescriptor
->Signature
= 0;
316 LocalDescriptor
->Tag
= 0;
318 FoundDescriptor
->Size
+=
319 (LocalDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
322 /* Shut the compiler up */
323 LocalSize
= GlobalSize
= 0;
324 ThisDescriptor
= (PVOID
)LocalSize
;
325 NextDescriptor
= (PVOID
)GlobalSize
;
326 GlobalDescriptor
= (PVOID
) ThisDescriptor
;
327 FoundDescriptor
= (PVOID
)GlobalDescriptor
;
328 GlobalDescriptor
= (PVOID
) NextDescriptor
;
329 NextDescriptor
= (PVOID
) FoundDescriptor
;
331 /* Use the NT pool allocator*/
332 ExFreePool(LocalDescriptor
);
335 /* Release the lock, delete the address, and return */
336 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
338 SAC_DBG(SAC_DBG_MM
, "exiting.\n");