86b2efe117ff03d771e0f7161b00a79732e54137
[reactos.git] / reactos / drivers / sac / driver / memory.c
1 /*
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
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include "sacdrv.h"
12
13 /* GLOBALS ********************************************************************/
14
15 LONG TotalFrees, TotalBytesFreed, TotalAllocations, TotalBytesAllocated;
16 KSPIN_LOCK MemoryLock;
17 PSAC_MEMORY_LIST GlobalMemoryList;
18
19 /* FUNCTIONS ******************************************************************/
20
21 BOOLEAN
22 NTAPI
23 InitializeMemoryManagement(VOID)
24 {
25 PSAC_MEMORY_ENTRY Entry;
26 SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n");
27
28 /* Allocate a nonpaged heap for us to use */
29 GlobalMemoryList = ExAllocatePoolWithTagPriority(NonPagedPool,
30 SAC_MEMORY_LIST_SIZE,
31 INITIAL_BLOCK_TAG,
32 HighPoolPriority);
33 if (GlobalMemoryList)
34 {
35 /* Initialize a lock for it */
36 KeInitializeSpinLock(&MemoryLock);
37
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;
43
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);
49
50 /* All done */
51 SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with TRUE.\n");
52 return TRUE;
53 }
54
55 /* No pool available to manage our heap */
56 SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with FALSE. No pool.\n");
57 return FALSE;
58 }
59
60 VOID
61 NTAPI
62 FreeMemoryManagement(VOID)
63 {
64 PSAC_MEMORY_LIST Next;
65 KIRQL OldIrql;
66 SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering\n");
67
68 /* Acquire the memory lock while freeing the list(s) */
69 KeAcquireSpinLock(&MemoryLock, &OldIrql);
70 while (GlobalMemoryList)
71 {
72 ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE);
73
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);
78
79 /* Reacquire the lock and see if there was another list to free */
80 KeAcquireSpinLock(&MemoryLock, &OldIrql);
81 GlobalMemoryList = Next;
82 }
83
84 /* All done */
85 KeReleaseSpinLock(&MemoryLock, OldIrql);
86 SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting\n");
87 }
88
89 PVOID
90 NTAPI
91 MyAllocatePool(IN SIZE_T PoolSize,
92 IN ULONG Tag,
93 IN PCHAR File,
94 IN ULONG Line)
95 {
96 PVOID p;
97 p = ExAllocatePoolWithTag(NonPagedPool, PoolSize, 'HACK');
98 RtlZeroMemory(p, PoolSize);
99 SAC_DBG(SAC_DBG_MM, "Returning block 0x%X.\n", p);
100 return p;
101 #if 0
102 KIRQL OldIrql;
103 PSAC_MEMORY_LIST GlobalDescriptor, NewDescriptor;
104 PSAC_MEMORY_ENTRY LocalDescriptor, NextDescriptor;
105 ULONG GlobalSize, ActualSize;
106 PVOID Buffer;
107 ASSERT("Tag != FREE_POOL_TAG");
108 SAC_DBG(SAC_DBG_MM, "Entering.\n");
109
110 /* Acquire the memory allocation lock and align the size request */
111 KeAcquireSpinLock(&MemoryLock, &OldIrql);
112 PoolSize = ALIGN_UP(PoolSize, ULONGLONG);
113
114 #if _USE_SAC_HEAP_ALLOCATOR_
115 GlobalDescriptor = GlobalMemoryList;
116 KeAcquireSpinLock(&MemoryLock, &OldIrql);
117 while (GlobalDescriptor)
118 {
119 ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE);
120
121 LocalDescriptor = GlobalDescriptor->LocalDescriptor;
122
123 GlobalSize = GlobalDescriptor->Size;
124 while (GlobalSize)
125 {
126 ASSERT(LocalDescriptor->Signature == LOCAL_MEMORY_SIGNATURE);
127
128 if ((LocalDescriptor->Tag == FREE_POOL_TAG) &&
129 (LocalDescriptor->Size >= PoolSize))
130 {
131 break;
132 }
133
134 GlobalSize -= (LocalDescriptor->Size + sizeof(SAC_MEMORY_ENTRY));
135
136 LocalDescriptor =
137 (PSAC_MEMORY_ENTRY)((ULONG_PTR)LocalDescriptor +
138 LocalDescriptor->Size +
139 sizeof(SAC_MEMORY_ENTRY));
140 }
141
142 GlobalDescriptor = GlobalDescriptor->Next;
143 }
144
145 if (!GlobalDescriptor)
146 {
147 KeReleaseSpinLock(&MemoryLock, OldIrql);
148
149 ActualSize = min(
150 PAGE_SIZE,
151 PoolSize + sizeof(SAC_MEMORY_ENTRY) + sizeof(SAC_MEMORY_LIST));
152
153 SAC_DBG(SAC_DBG_MM, "Allocating new space.\n");
154
155 NewDescriptor = ExAllocatePoolWithTagPriority(NonPagedPool,
156 ActualSize,
157 ALLOC_BLOCK_TAG,
158 HighPoolPriority);
159 if (!NewDescriptor)
160 {
161 SAC_DBG(SAC_DBG_MM, "No more memory, returning NULL.\n");
162 return NULL;
163 }
164
165 KeAcquireSpinLock(&MemoryLock, &OldIrql);
166
167 NewDescriptor->Signature = GLOBAL_MEMORY_SIGNATURE;
168 NewDescriptor->LocalDescriptor = (PSAC_MEMORY_ENTRY)(NewDescriptor + 1);
169 NewDescriptor->Size = ActualSize - 16;
170 NewDescriptor->Next = GlobalMemoryList;
171
172 GlobalMemoryList = NewDescriptor;
173
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);
179 }
180
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);
184
185 if (LocalDescriptor->Size > (PoolSize + sizeof(SAC_MEMORY_ENTRY)))
186 {
187 NextDescriptor =
188 (PSAC_MEMORY_ENTRY)((ULONG_PTR)LocalDescriptor +
189 PoolSize +
190 sizeof(SAC_MEMORY_ENTRY));
191 if (NextDescriptor->Tag == FREE_POOL_TAG)
192 {
193 NextDescriptor->Tag = FREE_POOL_TAG;
194 NextDescriptor->Signature = LOCAL_MEMORY_SIGNATURE;
195 NextDescriptor->Size =
196 (LocalDescriptor->Size - PoolSize - sizeof(SAC_MEMORY_ENTRY));
197
198 LocalDescriptor->Size = PoolSize;
199 }
200 }
201 #else
202 /* Shut the compiler up */
203 NewDescriptor = GlobalDescriptor = NULL;
204 GlobalSize = (ULONG)NewDescriptor;
205 ActualSize = GlobalSize;
206 NextDescriptor = (PVOID)ActualSize;
207 NewDescriptor = (PVOID)NextDescriptor;
208
209 /* Use the NT pool allocator */
210 LocalDescriptor = ExAllocatePoolWithTag(NonPagedPool,
211 PoolSize + sizeof(*LocalDescriptor),
212 Tag);
213 LocalDescriptor->Size = PoolSize;
214 #endif
215 /* Set the tag, and release the lock */
216 LocalDescriptor->Tag = Tag;
217 KeReleaseSpinLock(&MemoryLock, OldIrql);
218
219 /* Update our performance counters */
220 InterlockedIncrement(&TotalAllocations);
221 InterlockedExchangeAdd(&TotalBytesAllocated, LocalDescriptor->Size);
222
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);
227 return Buffer;
228 #endif
229 }
230
231 VOID
232 NTAPI
233 MyFreePool(IN PVOID *Block)
234 {
235 #if 0
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;
241 KIRQL OldIrql;
242 SAC_DBG(SAC_DBG_MM, "Entering with block 0x%X.\n", LocalDescriptor);
243
244 /* Make sure this was a valid entry */
245 ASSERT(LocalDescriptor->Size > 0);
246 ASSERT(LocalDescriptor->Signature == LOCAL_MEMORY_SIGNATURE);
247
248 /* Update performance counters */
249 InterlockedIncrement(&TotalFrees);
250 InterlockedExchangeAdd(&TotalBytesFreed, LocalDescriptor->Size);
251
252 /* Acquire the memory alliocation lock */
253 GlobalDescriptor = GlobalMemoryList;
254 KeAcquireSpinLock(&MemoryLock, &OldIrql);
255
256 #if _USE_SAC_HEAP_ALLOCATOR_
257 while (GlobalDescriptor)
258 {
259 ASSERT(GlobalMemoryList->Signature == GLOBAL_MEMORY_SIGNATURE);
260
261 FoundDescriptor = NULL;
262
263 ThisDescriptor = GlobalDescriptor->LocalDescriptor;
264
265 GlobalSize = GlobalDescriptor->Size;
266 while (GlobalSize)
267 {
268 ASSERT(ThisDescriptor->Signature == LOCAL_MEMORY_SIGNATURE);
269
270 if (ThisDescriptor == LocalDescriptor) break;
271
272 GlobalSize -= (ThisDescriptor->Size + sizeof(SAC_MEMORY_ENTRY));
273
274 ThisDescriptor =
275 (PSAC_MEMORY_ENTRY)((ULONG_PTR)ThisDescriptor +
276 ThisDescriptor->Size +
277 sizeof(SAC_MEMORY_ENTRY));
278 }
279
280 if (ThisDescriptor == LocalDescriptor) break;
281
282 GlobalDescriptor = GlobalDescriptor->Next;
283 }
284
285 if (!GlobalDescriptor)
286 {
287 KeReleaseSpinLock(&MemoryLock, OldIrql);
288 SAC_DBG(SAC_DBG_MM, "Could not find block.\n");
289 return;
290 }
291
292 ASSERT(ThisDescriptor->Signature == LOCAL_MEMORY_SIGNATURE);
293
294 if (LocalDescriptor->Tag == FREE_POOL_TAG)
295 {
296 KeReleaseSpinLock(&MemoryLock, OldIrql);
297 SAC_DBG(SAC_DBG_MM, "Attempted to free something twice.\n");
298 return;
299 }
300
301 LocalSize = LocalDescriptor->Size;
302 LocalDescriptor->Tag = FREE_POOL_TAG;
303
304 if (GlobalSize > (LocalSize + sizeof(SAC_MEMORY_ENTRY)))
305 {
306 NextDescriptor =
307 (PSAC_MEMORY_ENTRY)((ULONG_PTR)LocalDescriptor +
308 LocalSize +
309 sizeof(SAC_MEMORY_ENTRY));
310 if (NextDescriptor->Tag == FREE_POOL_TAG)
311 {
312 NextDescriptor->Tag = 0;
313 NextDescriptor->Signature = 0;
314
315 LocalDescriptor->Size +=
316 (NextDescriptor->Size + sizeof(SAC_MEMORY_ENTRY));
317 }
318 }
319
320 if ((FoundDescriptor) && (FoundDescriptor->Tag == FREE_POOL_TAG))
321 {
322 LocalDescriptor->Signature = 0;
323 LocalDescriptor->Tag = 0;
324
325 FoundDescriptor->Size +=
326 (LocalDescriptor->Size + sizeof(SAC_MEMORY_ENTRY));
327 }
328 #else
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;
337
338 /* Use the NT pool allocator*/
339 ExFreePool(LocalDescriptor);
340 #endif
341
342 /* Release the lock, delete the address, and return */
343 KeReleaseSpinLock(&MemoryLock, OldIrql);
344 #endif
345 SAC_DBG(SAC_DBG_MM, "exiting: 0x%p.\n", *Block);
346 ExFreePoolWithTag(*Block, 'HACK');
347 *Block = NULL;
348 }