Advertisement
KillaMaaki

Apollo heap implementation

Sep 14th, 2019
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pascal 5.13 KB | None | 0 0
  1. unit MemUtil;
  2.  
  3. interface
  4.     function getmem( size : ushort ) : pointer;
  5.     procedure freemem( addr : pointer );
  6.    
  7. implementation
  8.     type
  9.         FreeBlock = record
  10.             length: ushort;
  11.             next: ^FreeBlock;
  12.             prev: ^FreeBlock;
  13.         end;
  14.        
  15.         PointerHead = record
  16.             length: ushort;
  17.         end;
  18.        
  19.     const
  20.         HEAP_MAX : ushort = 65535 - HEAP_START - MAX_STACK;
  21.        
  22.     var
  23.         free_head : ^FreeBlock;
  24.        
  25.     function getmem( size : ushort ) : pointer;
  26.     var
  27.         cur : ^FreeBlock;
  28.         addr : pointer;
  29.         blockTmp : FreeBlock;
  30.         addrHead : ^PointerHead;
  31.     begin
  32.         // reserve bytes for pointer header and then ensure size is aligned
  33.         size := size + sizeOf(PointerHead);
  34.         size := size + ( size and 1 );
  35.        
  36.         // traverse memory linked list, searching for a block large enough
  37.         cur := free_head;
  38.         while cur != nil && cur^.length < size do
  39.         begin
  40.             cur := cur^.next;
  41.         end;
  42.        
  43.         // couldn't find any block of memory large enough, return nil
  44.         if cur = nil then
  45.         begin
  46.             malloc := nil;
  47.             exit;
  48.         end;
  49.        
  50.         addr := cur;
  51.         blockTmp := cur^;
  52.        
  53.         // construct new free block at current + length
  54.         cur := addr + size;
  55.         cur^.length := blockTmp.length - size;
  56.         cur^.next := blockTmp.next;
  57.         cur^.prev := blockTmp.prev;
  58.        
  59.         // make sure prev block points at new start of free block
  60.         if cur^.prev != nil then
  61.             cur^.prev^.next := cur;
  62.         else
  63.             free_head := cur;
  64.        
  65.         // set up pointer head
  66.         addrHead := addr;
  67.         addrHead^.length := size;
  68.        
  69.         // move to after pointer head and return
  70.         addrHead := addrHead + 1;
  71.         malloc := addrHead;
  72.     end;
  73.    
  74.     procedure freemem( addr : pointer );
  75.     var
  76.         addrHead : ^PointerHead;
  77.         addrlen : ushort;
  78.         before : ^FreeBlock;
  79.         after : ^FreeBlock;
  80.         before_end : pointer;
  81.         addr_end : pointer;
  82.         tmpBlock : FreeBlock;
  83.         free_block : ^FreeBlock;
  84.     begin
  85.         addrHead := addr;
  86.         addrHead := addrHead - 1;
  87.        
  88.         addr := addrHead;
  89.        
  90.         addrlen := addrHead^.length;
  91.        
  92.         before := free_head;
  93.         after := nil;
  94.        
  95.         // scan through free memory to find the block that lies before this pointer and the block after
  96.         while before^.next != nil do
  97.         begin
  98.             if before^.next < addr then
  99.                 before := before^.next;
  100.             else
  101.                 break;
  102.         end;
  103.        
  104.         // if before starts after this pointer, then this pointer starts before the first free block of memory
  105.         if before > addr then
  106.         begin
  107.             after := before;
  108.             before := nil;
  109.         end;
  110.         // otherwise, next block is before->next
  111.         else
  112.             after := before^.next;
  113.            
  114.         // check and see if we can merge this pointer with the end of before
  115.         if before != nil then
  116.         begin
  117.             before_end := before;
  118.             before_end += before^.length;
  119.            
  120.             if before_end = addr then
  121.             begin
  122.                 // just expand length to include pointer
  123.                 before^.length += addrlen;
  124.                 exit;
  125.             end;
  126.         end;
  127.        
  128.         // check and see if we can merge this pointer with the beginning of after
  129.         addr_end := addr;
  130.         addr_end += addrlen;
  131.        
  132.         if after != nil && addr_end = after then
  133.         begin
  134.             tmpBlock := after^;
  135.             after := addr;
  136.             after^.length := tmpBlock.length + addrlen;
  137.             after^.next := tmpBlock.next;
  138.             after^.prev := tmpBlock.prev;
  139.            
  140.             // make sure previous free block has correct next pointer
  141.             if after^.prev != nil then
  142.                 after^.prev^.next := after;
  143.             // or alternatively make this the new free head
  144.             else
  145.                 free_head := after;
  146.         end
  147.         // otherwise this pointer becomes a new standalone block of free memory
  148.         else
  149.         begin
  150.             free_block := addr;
  151.             free_block^.length := addrlen;
  152.             free_block^.next := after;
  153.             free_block^.prev := before;
  154.            
  155.             if before != nil then
  156.                 before^.next := free_block;
  157.             // if there's no before block, this becomes the new free head
  158.             else
  159.                 free_head := free_block;
  160.                
  161.             if after != nil then
  162.             begin
  163.                 after^.prev := free_block;
  164.             end;
  165.         end;
  166.     end;
  167.  
  168. initialization
  169.     // initialize free memory to a single contiguous block
  170.     // note: HEAP_START is compiler-emitted and points at just after program globals in work RAM
  171.     free_head := pointer(HEAP_START);
  172.     free_head^.length := HEAP_MAX;
  173.     free_head^.next := nil;
  174.     free_head^.prev := nil;
  175.    
  176. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement