3 * Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 ULONG AllocationCount
= 0;
31 VOID
VerifyHeap(VOID
);
32 VOID
DumpMemoryAllocMap(VOID
);
33 VOID
IncrementAllocationCount(VOID
);
34 VOID
DecrementAllocationCount(VOID
);
35 VOID
MemAllocTest(VOID
);
38 PVOID
AllocateMemory(ULONG NumberOfBytes
)
45 if (NumberOfBytes
== 0)
47 DbgPrint((DPRINT_MEMORY
, "AllocateMemory() called for 0 bytes. Returning NULL.\n"));
51 // Find out how many blocks it will take to
52 // satisfy this allocation
53 BlocksNeeded
= ROUND_UP(NumberOfBytes
, MEM_BLOCK_SIZE
) / MEM_BLOCK_SIZE
;
55 // Now loop through our array of blocks and
56 // see if we have enough space
57 for (Idx
=0,NumFree
=0; Idx
<HeapMemBlockCount
; Idx
++)
59 // Check this block and see if it is already allocated
60 // If so reset our counter and continue the loop
61 if (HeapMemBlockArray
[Idx
].MemBlockAllocated
)
68 // It is free memory so lets increment our count
72 // If we have found enough blocks to satisfy the request
73 // then we're done searching
74 if (NumFree
>= BlocksNeeded
)
81 // If we don't have enough available mem
83 if (NumFree
< BlocksNeeded
)
85 DbgPrint((DPRINT_MEMORY
, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", NumberOfBytes
, AllocationCount
));
86 MessageBox("Memory allocation failed: out of memory.");
90 // Subtract the block count from Idx and we have
91 // the start block of the memory
94 // Now we know which block to give them
95 MemPointer
= HeapBaseAddress
+ (Idx
* MEM_BLOCK_SIZE
);
97 // Now loop through and mark all the blocks as allocated
98 for (NumFree
=0; NumFree
<BlocksNeeded
; NumFree
++)
100 HeapMemBlockArray
[Idx
+ NumFree
].MemBlockAllocated
= TRUE
;
101 HeapMemBlockArray
[Idx
+ NumFree
].BlocksAllocated
= NumFree
? 0 : BlocksNeeded
; // Mark only the first block with the count
105 IncrementAllocationCount();
106 DbgPrint((DPRINT_MEMORY
, "Allocated %d bytes (%d blocks) of memory starting at block %d. AllocCount: %d\n", NumberOfBytes
, BlocksNeeded
, Idx
, AllocationCount
));
110 // Now return the pointer
114 VOID
FreeMemory(PVOID MemBlock
)
122 // Make sure we didn't get a bogus pointer
123 if ((MemBlock
< HeapBaseAddress
) || (MemBlock
> (HeapBaseAddress
+ HeapLengthInBytes
)))
125 BugCheck((DPRINT_MEMORY
, "Bogus memory pointer (0x%x) passed to FreeMemory()\n", MemBlock
));
129 // Find out the block number if the first
130 // block of memory they allocated
131 BlockNumber
= (MemBlock
- HeapBaseAddress
) / MEM_BLOCK_SIZE
;
132 BlockCount
= HeapMemBlockArray
[BlockNumber
].BlocksAllocated
;
135 // Make sure we didn't get a bogus pointer
136 if ((BlockCount
< 1) || (BlockCount
> HeapMemBlockCount
))
138 BugCheck((DPRINT_MEMORY
, "Invalid block count in heap page header. HeapMemBlockArray[BlockNumber].BlocksAllocated = %d\n", HeapMemBlockArray
[BlockNumber
].BlocksAllocated
));
142 // Loop through our array and mark all the
144 for (Idx
=BlockNumber
; Idx
<(BlockNumber
+ BlockCount
); Idx
++)
146 HeapMemBlockArray
[Idx
].MemBlockAllocated
= FALSE
;
147 HeapMemBlockArray
[Idx
].BlocksAllocated
= 0;
151 DecrementAllocationCount();
152 DbgPrint((DPRINT_MEMORY
, "Freed %d blocks of memory starting at block %d. AllocationCount: %d\n", BlockCount
, BlockNumber
, AllocationCount
));
158 VOID
VerifyHeap(VOID
)
164 if (DUMP_MEM_MAP_ON_VERIFY
)
166 DumpMemoryAllocMap();
169 // Loop through the array and verify that
170 // everything is kosher
171 for (Idx
=0; Idx
<HeapMemBlockCount
; Idx
++)
173 // Check if this block is allocation
174 if (HeapMemBlockArray
[Idx
].MemBlockAllocated
)
176 // This is the first block in the run so it
177 // had better have a length that is within range
178 if ((HeapMemBlockArray
[Idx
].BlocksAllocated
< 1) || (HeapMemBlockArray
[Idx
].BlocksAllocated
> (HeapMemBlockCount
- Idx
)))
180 BugCheck((DPRINT_MEMORY
, "Allocation length out of range in heap table. HeapMemBlockArray[Idx].BlocksAllocated = %d\n", HeapMemBlockArray
[Idx
].BlocksAllocated
));
183 // Now go through and verify that the rest of
184 // this run has the blocks marked allocated
185 // with a length of zero but don't check the
186 // first one because we already did
187 Count
= HeapMemBlockArray
[Idx
].BlocksAllocated
;
188 for (Idx2
=1; Idx2
<Count
; Idx2
++)
190 // Make sure it's allocated
191 if (HeapMemBlockArray
[Idx
+ Idx2
].MemBlockAllocated
!= TRUE
)
193 BugCheck((DPRINT_MEMORY
, "Heap table indicates hole in memory allocation. HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE\n"));
196 // Make sure the length is zero
197 if (HeapMemBlockArray
[Idx
+ Idx2
].BlocksAllocated
!= 0)
199 BugCheck((DPRINT_MEMORY
, "Allocation chain has non-zero value in non-first block in heap table. HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0\n"));
203 // Move on to the next run
208 // Nope, not allocated so make sure the length is zero
209 if (HeapMemBlockArray
[Idx
].BlocksAllocated
!= 0)
211 BugCheck((DPRINT_MEMORY
, "Free block is start of memory allocation. HeapMemBlockArray[Idx].BlocksAllocated != 0\n"));
217 VOID
DumpMemoryAllocMap(VOID
)
221 DbgPrint((DPRINT_MEMORY
, "----------- Memory Allocation Bitmap -----------\n"));
223 for (Idx
=0; Idx
<HeapMemBlockCount
; Idx
++)
227 DbgPrint((DPRINT_MEMORY
, "\n"));
228 DbgPrint((DPRINT_MEMORY
, "%x:\t", (Idx
* 256)));
230 else if ((Idx
% 4) == 0)
232 DbgPrint((DPRINT_MEMORY
, " "));
235 if (HeapMemBlockArray
[Idx
].MemBlockAllocated
)
237 DbgPrint((DPRINT_MEMORY
, "X"));
241 DbgPrint((DPRINT_MEMORY
, "*"));
245 DbgPrint((DPRINT_MEMORY
, "\n"));
248 VOID
IncrementAllocationCount(VOID
)
253 VOID
DecrementAllocationCount(VOID
)
258 VOID
MemAllocTest(VOID
)
266 MemPtr1
= AllocateMemory(4096);
267 printf("MemPtr1: 0x%x\n", (int)MemPtr1
);
269 MemPtr2
= AllocateMemory(4096);
270 printf("MemPtr2: 0x%x\n", (int)MemPtr2
);
272 MemPtr3
= AllocateMemory(4096);
273 printf("MemPtr3: 0x%x\n", (int)MemPtr3
);
274 DumpMemoryAllocMap();
281 MemPtr4
= AllocateMemory(2048);
282 printf("MemPtr4: 0x%x\n", (int)MemPtr4
);
284 MemPtr5
= AllocateMemory(4096);
285 printf("MemPtr5: 0x%x\n", (int)MemPtr5
);
290 // Returns the amount of total usuable memory available to the memory manager
291 ULONG
GetSystemMemorySize(VOID
)
293 return HeapLengthInBytes
;