2 * PROJECT: ReactOS Boot Loader
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 ******************************************************************/
22 InitializeMemoryManagement(VOID
)
24 PSAC_MEMORY_ENTRY Entry
;
26 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
28 GlobalMemoryList
= ExAllocatePoolWithTagPriority(
35 KeInitializeSpinLock(&MemoryLock
);
37 GlobalMemoryList
->Signature
= GLOBAL_MEMORY_SIGNATURE
;
38 GlobalMemoryList
->LocalDescriptor
=
39 (PSAC_MEMORY_ENTRY
)(GlobalMemoryList
+ 1);
40 GlobalMemoryList
->Size
= SAC_MEMORY_LIST_SIZE
- sizeof(SAC_MEMORY_LIST
);
42 Entry
= GlobalMemoryList
->LocalDescriptor
;
43 Entry
->Signature
= LOCAL_MEMORY_SIGNATURE
;
44 Entry
->Tag
= FREE_POOL_TAG
;
45 Entry
->Size
= GlobalMemoryList
->Size
- sizeof(SAC_MEMORY_ENTRY
);
47 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting with TRUE.\n");
51 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting with FALSE. No pool.\n");
60 PSAC_MEMORY_LIST Next
;
63 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Entering\n");
65 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
66 while (GlobalMemoryList
)
68 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
70 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
72 Next
= GlobalMemoryList
->Next
;
74 ExFreePoolWithTag(GlobalMemoryList
, 0);
76 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
77 GlobalMemoryList
= Next
;
80 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
81 SAC_DBG(SAC_DBG_ENTRY_EXIT
, "Exiting\n");
93 PSAC_MEMORY_LIST GlobalDescriptor
, NewDescriptor
;
94 PSAC_MEMORY_ENTRY LocalDescriptor
, NextDescriptor
;
95 ULONG GlobalSize
, ActualSize
;
98 ASSERT("Tag != FREE_POOL_TAG");
100 SAC_DBG(SAC_DBG_MM
, "Entering.\n");
102 OldIrql
= KfAcquireSpinLock(&MemoryLock
);
103 PoolSize
= ALIGN_UP(PoolSize
, ULONGLONG
);
105 GlobalDescriptor
= GlobalMemoryList
;
106 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
107 while (GlobalDescriptor
)
109 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
111 LocalDescriptor
= GlobalDescriptor
->LocalDescriptor
;
113 GlobalSize
= GlobalDescriptor
->Size
;
116 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
118 if ((LocalDescriptor
->Tag
== FREE_POOL_TAG
) &&
119 (LocalDescriptor
->Size
>= PoolSize
))
124 GlobalSize
-= (LocalDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
127 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
128 LocalDescriptor
->Size
+
129 sizeof(SAC_MEMORY_ENTRY
));
132 GlobalDescriptor
= GlobalDescriptor
->Next
;
135 if (!GlobalDescriptor
)
137 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
141 PoolSize
+ sizeof(SAC_MEMORY_ENTRY
) + sizeof(SAC_MEMORY_LIST
));
143 SAC_DBG(SAC_DBG_MM
, "Allocating new space.\n");
145 NewDescriptor
= ExAllocatePoolWithTagPriority(
152 SAC_DBG(SAC_DBG_MM
, "No more memory, returning NULL.\n");
156 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
158 NewDescriptor
->Signature
= GLOBAL_MEMORY_SIGNATURE
;
159 NewDescriptor
->LocalDescriptor
= (PSAC_MEMORY_ENTRY
)(NewDescriptor
+ 1);
160 NewDescriptor
->Size
= ActualSize
- 16;
161 NewDescriptor
->Next
= GlobalMemoryList
;
163 GlobalMemoryList
= NewDescriptor
;
165 LocalDescriptor
= NewDescriptor
->LocalDescriptor
;
166 LocalDescriptor
->Signature
= LOCAL_MEMORY_SIGNATURE
;
167 LocalDescriptor
->Tag
= FREE_POOL_TAG
;
168 LocalDescriptor
->Size
=
169 GlobalMemoryList
->Size
- sizeof(SAC_MEMORY_ENTRY
);
172 SAC_DBG(SAC_DBG_MM
, "Found a good sized block.\n");
173 ASSERT(LocalDescriptor
->Tag
== FREE_POOL_TAG
);
174 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
176 if (LocalDescriptor
->Size
> (PoolSize
+ sizeof(SAC_MEMORY_ENTRY
)))
179 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
181 sizeof(SAC_MEMORY_ENTRY
));
182 if (NextDescriptor
->Tag
== FREE_POOL_TAG
)
184 NextDescriptor
->Tag
= FREE_POOL_TAG
;
185 NextDescriptor
->Signature
= LOCAL_MEMORY_SIGNATURE
;
186 NextDescriptor
->Size
=
187 (LocalDescriptor
->Size
- PoolSize
- sizeof(SAC_MEMORY_ENTRY
));
189 LocalDescriptor
->Size
= PoolSize
;
193 LocalDescriptor
->Tag
= Tag
;
194 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
196 InterlockedIncrement(&TotalAllocations
);
197 InterlockedExchangeAdd(&TotalBytesAllocated
, LocalDescriptor
->Size
);
198 SAC_DBG(1, "Returning block 0x%X.\n", LocalDescriptor
);
200 Buffer
= LocalDescriptor
+ 1;
201 RtlZeroMemory(Buffer
, PoolSize
);
210 PSAC_MEMORY_ENTRY LocalDescriptor
, NextDescriptor
;
211 PSAC_MEMORY_ENTRY ThisDescriptor
, FoundDescriptor
;
212 ULONG GlobalSize
, LocalSize
;
213 PSAC_MEMORY_LIST GlobalDescriptor
;
216 LocalDescriptor
= (PVOID
)((ULONG_PTR
)(*Block
) - sizeof(SAC_MEMORY_ENTRY
));
218 SAC_DBG(SAC_DBG_MM
, "Entering with block 0x%X.\n", LocalDescriptor
);
220 ASSERT(LocalDescriptor
->Size
> 0);
221 ASSERT(LocalDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
223 InterlockedIncrement(&TotalFrees
);
225 InterlockedExchangeAdd(&TotalBytesFreed
, LocalDescriptor
->Size
);
227 GlobalDescriptor
= GlobalMemoryList
;
228 KeAcquireSpinLock(&MemoryLock
, &OldIrql
);
229 while (GlobalDescriptor
)
231 ASSERT(GlobalMemoryList
->Signature
== GLOBAL_MEMORY_SIGNATURE
);
233 FoundDescriptor
= NULL
;
235 ThisDescriptor
= GlobalDescriptor
->LocalDescriptor
;
237 GlobalSize
= GlobalDescriptor
->Size
;
240 ASSERT(ThisDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
242 if (ThisDescriptor
== LocalDescriptor
) break;
244 GlobalSize
-= (ThisDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
247 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)ThisDescriptor
+
248 ThisDescriptor
->Size
+
249 sizeof(SAC_MEMORY_ENTRY
));
252 if (ThisDescriptor
== LocalDescriptor
) break;
254 GlobalDescriptor
= GlobalDescriptor
->Next
;
257 if (!GlobalDescriptor
)
259 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
260 SAC_DBG(SAC_DBG_MM
, "Could not find block.\n");
264 ASSERT(ThisDescriptor
->Signature
== LOCAL_MEMORY_SIGNATURE
);
266 if (LocalDescriptor
->Tag
== FREE_POOL_TAG
)
268 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
269 SAC_DBG(SAC_DBG_MM
, "Attempted to free something twice.\n");
273 LocalSize
= LocalDescriptor
->Size
;
274 LocalDescriptor
->Tag
= FREE_POOL_TAG
;
276 if (GlobalSize
> (LocalSize
+ sizeof(SAC_MEMORY_ENTRY
)))
279 (PSAC_MEMORY_ENTRY
)((ULONG_PTR
)LocalDescriptor
+
281 sizeof(SAC_MEMORY_ENTRY
));
282 if (NextDescriptor
->Tag
== FREE_POOL_TAG
)
284 NextDescriptor
->Tag
= 0;
285 NextDescriptor
->Signature
= 0;
287 LocalDescriptor
->Size
+=
288 (NextDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
292 if ((FoundDescriptor
) && (FoundDescriptor
->Tag
== FREE_POOL_TAG
))
294 LocalDescriptor
->Signature
= 0;
295 LocalDescriptor
->Tag
= 0;
297 FoundDescriptor
->Size
+=
298 (LocalDescriptor
->Size
+ sizeof(SAC_MEMORY_ENTRY
));
301 KeReleaseSpinLock(&MemoryLock
, OldIrql
);
304 SAC_DBG(SAC_DBG_MM
, "exiting.\n");