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"));
48 MessageBox("Memory allocation failed: AllocateMemory() called for 0 bytes.");
52 // Find out how many blocks it will take to
53 // satisfy this allocation
54 BlocksNeeded
= ROUND_UP(NumberOfBytes
, MEM_BLOCK_SIZE
) / MEM_BLOCK_SIZE
;
56 // Now loop through our array of blocks and
57 // see if we have enough space
58 for (Idx
=0,NumFree
=0; Idx
<HeapMemBlockCount
; Idx
++)
60 // Check this block and see if it is already allocated
61 // If so reset our counter and continue the loop
62 if (HeapMemBlockArray
[Idx
].MemBlockAllocated
)
69 // It is free memory so lets increment our count
73 // If we have found enough blocks to satisfy the request
74 // then we're done searching
75 if (NumFree
>= BlocksNeeded
)
82 // If we don't have enough available mem
84 if (NumFree
< BlocksNeeded
)
86 DbgPrint((DPRINT_MEMORY
, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", NumberOfBytes
, AllocationCount
));
87 MessageBox("Memory allocation failed: out of memory.");
91 // Subtract the block count from Idx and we have
92 // the start block of the memory
95 // Now we know which block to give them
96 MemPointer
= HeapBaseAddress
+ (Idx
* MEM_BLOCK_SIZE
);
98 // Now loop through and mark all the blocks as allocated
99 for (NumFree
=0; NumFree
<BlocksNeeded
; NumFree
++)
101 HeapMemBlockArray
[Idx
+ NumFree
].MemBlockAllocated
= TRUE
;
102 HeapMemBlockArray
[Idx
+ NumFree
].BlocksAllocated
= NumFree
? 0 : BlocksNeeded
; // Mark only the first block with the count
106 IncrementAllocationCount();
107 DbgPrint((DPRINT_MEMORY
, "Allocated %d bytes (%d blocks) of memory starting at block %d. AllocCount: %d\n", NumberOfBytes
, BlocksNeeded
, Idx
, AllocationCount
));
108 DbgPrint((DPRINT_MEMORY
, "Memory allocation pointer: 0x%x\n", MemPointer
));
112 // Now return the pointer
116 VOID
FreeMemory(PVOID MemBlock
)
124 // Make sure we didn't get a bogus pointer
125 if ((MemBlock
< HeapBaseAddress
) || (MemBlock
> (HeapBaseAddress
+ HeapLengthInBytes
)))
127 BugCheck((DPRINT_MEMORY
, "Bogus memory pointer (0x%x) passed to FreeMemory()\n", MemBlock
));
131 // Find out the block number if the first
132 // block of memory they allocated
133 BlockNumber
= (MemBlock
- HeapBaseAddress
) / MEM_BLOCK_SIZE
;
134 BlockCount
= HeapMemBlockArray
[BlockNumber
].BlocksAllocated
;
137 // Make sure we didn't get a bogus pointer
138 if ((BlockCount
< 1) || (BlockCount
> HeapMemBlockCount
))
140 BugCheck((DPRINT_MEMORY
, "Invalid block count in heap page header. HeapMemBlockArray[BlockNumber].BlocksAllocated = %d\n", HeapMemBlockArray
[BlockNumber
].BlocksAllocated
));
144 // Loop through our array and mark all the
146 for (Idx
=BlockNumber
; Idx
<(BlockNumber
+ BlockCount
); Idx
++)
148 HeapMemBlockArray
[Idx
].MemBlockAllocated
= FALSE
;
149 HeapMemBlockArray
[Idx
].BlocksAllocated
= 0;
153 DecrementAllocationCount();
154 DbgPrint((DPRINT_MEMORY
, "Freed %d blocks of memory starting at block %d. AllocationCount: %d\n", BlockCount
, BlockNumber
, AllocationCount
));
160 VOID
VerifyHeap(VOID
)
166 if (DUMP_MEM_MAP_ON_VERIFY
)
168 DumpMemoryAllocMap();
171 // Loop through the array and verify that
172 // everything is kosher
173 for (Idx
=0; Idx
<HeapMemBlockCount
; Idx
++)
175 // Check if this block is allocation
176 if (HeapMemBlockArray
[Idx
].MemBlockAllocated
)
178 // This is the first block in the run so it
179 // had better have a length that is within range
180 if ((HeapMemBlockArray
[Idx
].BlocksAllocated
< 1) || (HeapMemBlockArray
[Idx
].BlocksAllocated
> (HeapMemBlockCount
- Idx
)))
182 BugCheck((DPRINT_MEMORY
, "Allocation length out of range in heap table. HeapMemBlockArray[Idx].BlocksAllocated = %d\n", HeapMemBlockArray
[Idx
].BlocksAllocated
));
185 // Now go through and verify that the rest of
186 // this run has the blocks marked allocated
187 // with a length of zero but don't check the
188 // first one because we already did
189 Count
= HeapMemBlockArray
[Idx
].BlocksAllocated
;
190 for (Idx2
=1; Idx2
<Count
; Idx2
++)
192 // Make sure it's allocated
193 if (HeapMemBlockArray
[Idx
+ Idx2
].MemBlockAllocated
!= TRUE
)
195 BugCheck((DPRINT_MEMORY
, "Heap table indicates hole in memory allocation. HeapMemBlockArray[Idx + Idx2].MemBlockAllocated != TRUE\n"));
198 // Make sure the length is zero
199 if (HeapMemBlockArray
[Idx
+ Idx2
].BlocksAllocated
!= 0)
201 BugCheck((DPRINT_MEMORY
, "Allocation chain has non-zero value in non-first block in heap table. HeapMemBlockArray[Idx + Idx2].BlocksAllocated != 0\n"));
205 // Move on to the next run
210 // Nope, not allocated so make sure the length is zero
211 if (HeapMemBlockArray
[Idx
].BlocksAllocated
!= 0)
213 BugCheck((DPRINT_MEMORY
, "Free block is start of memory allocation. HeapMemBlockArray[Idx].BlocksAllocated != 0\n"));
219 VOID
DumpMemoryAllocMap(VOID
)
223 DbgPrint((DPRINT_MEMORY
, "----------- Memory Allocation Bitmap -----------\n"));
225 for (Idx
=0; Idx
<HeapMemBlockCount
; Idx
++)
229 DbgPrint((DPRINT_MEMORY
, "\n"));
230 DbgPrint((DPRINT_MEMORY
, "%x:\t", HeapBaseAddress
+ (Idx
* 256)));
232 else if ((Idx
% 4) == 0)
234 DbgPrint((DPRINT_MEMORY
, " "));
237 if (HeapMemBlockArray
[Idx
].MemBlockAllocated
)
239 DbgPrint((DPRINT_MEMORY
, "X"));
243 DbgPrint((DPRINT_MEMORY
, "*"));
247 DbgPrint((DPRINT_MEMORY
, "\n"));
250 VOID
IncrementAllocationCount(VOID
)
255 VOID
DecrementAllocationCount(VOID
)
260 VOID
MemAllocTest(VOID
)
268 MemPtr1
= AllocateMemory(4096);
269 printf("MemPtr1: 0x%x\n", (int)MemPtr1
);
271 MemPtr2
= AllocateMemory(4096);
272 printf("MemPtr2: 0x%x\n", (int)MemPtr2
);
274 MemPtr3
= AllocateMemory(4096);
275 printf("MemPtr3: 0x%x\n", (int)MemPtr3
);
276 DumpMemoryAllocMap();
283 MemPtr4
= AllocateMemory(2048);
284 printf("MemPtr4: 0x%x\n", (int)MemPtr4
);
286 MemPtr5
= AllocateMemory(4096);
287 printf("MemPtr5: 0x%x\n", (int)MemPtr5
);
292 // Returns the amount of total usuable memory available to the memory manager
293 ULONG
GetSystemMemorySize(VOID
)
295 return HeapLengthInBytes
;