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
;
107 ASSERT("Tag != FREE_POOL_TAG");
108 SAC_DBG(SAC_DBG_MM
, "Entering.\n");
110 /* Acquire the memory allocation lock and align the size request */
111 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
112 PoolSize
= ALIGN_UP(PoolSize
, ULONGLONG
);
114 #if _USE_SAC_HEAP_ALLOCATOR_
115 GlobalDescriptor
= GlobalMemoryList
;
116 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
117 while (GlobalDescriptor
)
119 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
121 LocalDescriptor
= GlobalDescriptor
->LocalDescriptor
;
123 GlobalSize
= GlobalDescriptor
->Size
;
126 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
128 if ((LocalDescriptor
->Tag
== FREE_POOL_TAG
) &&
129 (LocalDescriptor
->Size
>= PoolSize
))
134 GlobalSize
-= (LocalDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
137 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
138 LocalDescriptor
->Size
+
139 sizeof(SAC_MEMORY_ENTRY
));
142 GlobalDescriptor
= GlobalDescriptor
->Next
;
145 if (!GlobalDescriptor
)
147 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
151 PoolSize
+ sizeof(SAC_MEMORY_ENTRY
) + sizeof(SAC_MEMORY_LIST
));
153 SAC_DBG(SAC_DBG_MM
, "Allocating new space.\n");
155 NewDescriptor
= ExAllocatePoolWithTagPriority(NonPagedPool
,
161 SAC_DBG(SAC_DBG_MM
, "No more memory, returning NULL.\n");
165 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
167 NewDescriptor
->Signature
= GLOBAL_MEMORY_SIGNATURE
;
168 NewDescriptor
->LocalDescriptor
= (PSAC_MEMORY_ENTRY
)(NewDescriptor
+ 1);
169 NewDescriptor
->Size
= ActualSize
- 16;
170 NewDescriptor
->Next
= GlobalMemoryList
;
172 GlobalMemoryList
= NewDescriptor
;
174 LocalDescriptor
= NewDescriptor
->LocalDescriptor
;
175 LocalDescriptor
->Signature
= LOCAL_MEMORY_SIGNATURE
;
176 LocalDescriptor
->Tag
= FREE_POOL_TAG
;
177 LocalDescriptor
->Size
=
178 GlobalMemoryList
->Size
- sizeof(SAC_MEMORY_ENTRY
);
181 SAC_DBG(SAC_DBG_MM
, "Found a good sized block.\n");
182 ASSERT(LocalDescriptor
->Tag
== FREE_POOL_TAG
);
183 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
185 if (LocalDescriptor
->Size
> (PoolSize
+ sizeof(SAC_MEMORY_ENTRY
)))
188 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
190 sizeof(SAC_MEMORY_ENTRY
));
191 if (NextDescriptor
->Tag
== FREE_POOL_TAG
)
193 NextDescriptor
->Tag
= FREE_POOL_TAG
;
194 NextDescriptor
->Signature
= LOCAL_MEMORY_SIGNATURE
;
195 NextDescriptor
->Size
=
196 (LocalDescriptor
->Size
- PoolSize
- sizeof(SAC_MEMORY_ENTRY
));
198 LocalDescriptor
->Size
= PoolSize
;
202 /* Shut the compiler up */
203 NewDescriptor
= GlobalDescriptor
= NULL
;
204 GlobalSize
= (ULONG
)NewDescriptor
;
205 ActualSize
= GlobalSize
;
206 NextDescriptor
= (PVOID
)ActualSize
;
207 NewDescriptor
= (PVOID
)NextDescriptor
;
209 /* Use the NT pool allocator */
210 LocalDescriptor
= ExAllocatePoolWithTag(NonPagedPool
,
211 PoolSize
+ sizeof(*LocalDescriptor
),
213 LocalDescriptor
->Size
= PoolSize
;
215 /* Set the tag, and release the lock */
216 LocalDescriptor
->Tag
= Tag
;
217 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
219 /* Update our performance counters */
220 InterlockedIncrement(&TotalAllocations
);
221 InterlockedExchangeAdd(&TotalBytesAllocated
, LocalDescriptor
->Size
);
223 /* Return the buffer and zero it */
224 SAC_DBG(SAC_DBG_MM
, "Returning block 0x%X.\n", LocalDescriptor
);
225 Buffer
= LocalDescriptor
+ 1;
226 RtlZeroMemory(Buffer
, PoolSize
);
233 MyFreePool(IN PVOID
*Block
)
236 PSAC_MEMORY_ENTRY NextDescriptor
;
237 PSAC_MEMORY_ENTRY ThisDescriptor
, FoundDescriptor
;
238 PSAC_MEMORY_ENTRY LocalDescriptor
= (PVOID
)((ULONG_PTR
)(*Block
) - sizeof(SAC_MEMORY_ENTRY
));
239 ULONG GlobalSize
, LocalSize
;
240 PSAC_MEMORY_LIST GlobalDescriptor
;
242 SAC_DBG(SAC_DBG_MM
, "Entering with block 0x%X.\n", LocalDescriptor
);
244 /* Make sure this was a valid entry */
245 ASSERT(LocalDescriptor
->Size
> 0);
246 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
248 /* Update performance counters */
249 InterlockedIncrement(&TotalFrees
);
250 InterlockedExchangeAdd(&TotalBytesFreed
, LocalDescriptor
->Size
);
252 /* Acquire the memory alliocation lock */
253 GlobalDescriptor
= GlobalMemoryList
;
254 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
256 #if _USE_SAC_HEAP_ALLOCATOR_
257 while (GlobalDescriptor
)
259 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
261 FoundDescriptor
= NULL
;
263 ThisDescriptor
= GlobalDescriptor
->LocalDescriptor
;
265 GlobalSize
= GlobalDescriptor
->Size
;
268 ASSERT(ThisDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
270 if (ThisDescriptor
== LocalDescriptor
) break;
272 GlobalSize
-= (ThisDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
275 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)ThisDescriptor
+
276 ThisDescriptor
->Size
+
277 sizeof(SAC_MEMORY_ENTRY
));
280 if (ThisDescriptor
== LocalDescriptor
) break;
282 GlobalDescriptor
= GlobalDescriptor
->Next
;
285 if (!GlobalDescriptor
)
287 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
288 SAC_DBG(SAC_DBG_MM
, "Could not find block.\n");
292 ASSERT(ThisDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
294 if (LocalDescriptor
->Tag
== FREE_POOL_TAG
)
296 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
297 SAC_DBG(SAC_DBG_MM
, "Attempted to free something twice.\n");
301 LocalSize
= LocalDescriptor
->Size
;
302 LocalDescriptor
->Tag
= FREE_POOL_TAG
;
304 if (GlobalSize
> (LocalSize
+ sizeof(SAC_MEMORY_ENTRY
)))
307 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
309 sizeof(SAC_MEMORY_ENTRY
));
310 if (NextDescriptor
->Tag
== FREE_POOL_TAG
)
312 NextDescriptor
->Tag
= 0;
313 NextDescriptor
->Signature
= 0;
315 LocalDescriptor
->Size
+=
316 (NextDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
320 if ((FoundDescriptor
) && (FoundDescriptor
->Tag
== FREE_POOL_TAG
))
322 LocalDescriptor
->Signature
= 0;
323 LocalDescriptor
->Tag
= 0;
325 FoundDescriptor
->Size
+=
326 (LocalDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
329 /* Shut the compiler up */
330 LocalSize
= GlobalSize
= 0;
331 ThisDescriptor
= (PVOID
)LocalSize
;
332 NextDescriptor
= (PVOID
)GlobalSize
;
333 GlobalDescriptor
= (PVOID
)ThisDescriptor
;
334 FoundDescriptor
= (PVOID
)GlobalDescriptor
;
335 GlobalDescriptor
= (PVOID
)NextDescriptor
;
336 NextDescriptor
= (PVOID
)FoundDescriptor
;
338 /* Use the NT pool allocator*/
339 ExFreePool(LocalDescriptor
);
342 /* Release the lock, delete the address, and return */
343 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
345 SAC_DBG(SAC_DBG_MM
, "exiting: 0x%p.\n", *Block
);
346 ExFreePoolWithTag(*Block
, 'HACK');