1 constant FREE_MAGIC $FAEE;
2 constant ALLOC_MAGIC $A10C;
8 constant FB__SIZE (4*2);
12 constant AB__SIZE (2*2);
15 global mem_bottom = 0;
16 global mem_firstfree = 0;
18 ! Initialise the heap manager, given a value for TOP. It's assumed that the
19 ! heap will stretch to HIMEM.
21 [ mem_init bottom top;
24 ! Create a free chunk spanning the length of the block.
25 mem_firstfree = mem_bottom;
26 mem_firstfree-->FB_MAGIC = FREE_MAGIC;
27 mem_firstfree-->FB_PREV = 0;
28 mem_firstfree-->FB_NEXT = 0;
29 mem_firstfree-->FB_SIZE = mem_top - mem_bottom;
32 ! Zero a block of memory.
42 ! Remove a node from the list.
45 if (p == mem_firstfree)
46 mem_firstfree = p-->FB_NEXT;
48 p-->FB_PREV-->FB_NEXT = p-->FB_NEXT;
50 p-->FB_NEXT-->FB_PREV = p-->FB_PREV;
53 ! Try and allocate a block.
56 ! Add space for the AB_ header.
58 size = size + AB__SIZE;
60 ! This block will eventually have to be a FB, once it's freed. So it
61 ! has to be big enough for the FB_ structure.
66 ! Iterate through the list trying to find a free chunk large enough.
69 while ((p ~= 0) && (p-->FB_SIZE < size))
76 ! No sufficiently large chunk could be found.
80 ! Can the block be shrunk, or is there not enough room?
82 if ((p-->FB_SIZE - size) < FB__SIZE)
84 ! Yes; remove the node completely.
90 ! No. Instead of removing the node, we shrink it
91 p-->FB_SIZE = p-->FB_SIZE - size;
95 ! Initialise the allocated node.
98 p-->AB_MAGIC = ALLOC_MAGIC;
104 ! Try to free a block.
107 ! Adjust the pointer to point to the alloc node itself.
111 ! Check the magic number.
112 if (p-->AB_MAGIC ~= ALLOC_MAGIC)
114 print "Trying to free invalid node ", p, "!^";
115 print "Magic was "; phex(p-->AB_MAGIC, 4);
116 print " when it should have been "; phex(ALLOC_MAGIC, 4);
122 ! Turn the alloc node into a free node.
128 p-->FB_MAGIC = FREE_MAGIC;
129 p-->FB_NEXT = mem_firstfree;
133 mem_firstfree-->FB_PREV = p;
136 ! Right. We've successfully freed the block; p points to the FB
139 ! Unfortunately, they way we use memory leads to lots of
140 ! fragmentation, which is bad. So we need to find out if we can coalesce
141 ! with the block immediately afterwards.
143 if ((p+q)-->0 ~= FREE_MAGIC)
145 ! Nothing coalescable.
149 ! Change the size of our block to encompass the next block...
151 p-->FB_SIZE = q + (p+q)-->FB_SIZE;
153 ! ...and remove the next block from the free list.
155 mem_node_remove(p+q);
158 ! Get amount of free memory.
160 [ mem_countfree p size;
165 size = size + p-->FB_SIZE;
171 ! Get total amount of memory.
174 return (mem_top - mem_bottom);
177 ! Get amount of used memory.
180 return mem_counttotal() - mem_countfree();
184 ! Dump the free list.
186 [ mem_show_free_list p;
187 print "Free list start^";
191 print " node ", p, " prev=", p-->FB_PREV, " next=", p-->FB_NEXT;
192 print " size=", p-->FB_SIZE;
193 if (p-->FB_MAGIC ~= FREE_MAGIC)
194 print " invalid magic";
198 print "Free list end; used=", mem_countused(), " total=", mem_counttotal(), "^";