heapmgr.pp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2011 by the Free Pascal development team.
  4. Tiny heap manager for the FPC embedded target
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$mode objfpc}
  12. Unit heapmgr;
  13. interface
  14. procedure RegisterHeapBlock(AAddress: pointer; ASize: ptruint);
  15. function GetAlignedMem(Size, Alignment: ptruint): pointer;
  16. implementation
  17. const
  18. MinBlock = 16;
  19. type
  20. PHeapBlock = ^THeapBlock;
  21. THeapBlock = record
  22. Size: ptruint;
  23. Next: PHeapBlock;
  24. EndAddr: pointer;
  25. end;
  26. var
  27. Blocks: PHeapBlock = nil;
  28. procedure InternalFreeMem(Addr: Pointer; Size: ptruint); forward;
  29. function FindSize(p: pointer): ptruint; inline;
  30. begin
  31. FindSize := PPtrUInt(p)[-1];
  32. end;
  33. function SysGetMem(Size: ptruint): pointer;
  34. var
  35. p, prev: PHeapBlock;
  36. AllocSize, RestSize: ptruint;
  37. begin
  38. AllocSize := align(size+sizeof(ptruint), sizeof(pointer));
  39. p := Blocks;
  40. prev := nil;
  41. while assigned(p) and (p^.Size < AllocSize) do
  42. begin
  43. prev := p;
  44. p := p^.Next;
  45. end;
  46. if assigned(p) then
  47. begin
  48. result := @pptruint(p)[1];
  49. if p^.Size-AllocSize >= MinBlock then
  50. RestSize := p^.Size-AllocSize
  51. else
  52. begin
  53. AllocSize := p^.Size;
  54. RestSize := 0;
  55. end;
  56. if prev = nil then
  57. Blocks := p^.Next
  58. else
  59. prev^.next := p^.next;
  60. pptruint(p)^ := size;
  61. InternalFreemem(pointer(ptruint(p)+AllocSize), RestSize);
  62. end
  63. else
  64. Result := nil;
  65. end;
  66. function GetAlignedMem(Size, Alignment: ptruint): pointer;
  67. var
  68. mem: Pointer;
  69. memp: ptruint;
  70. begin
  71. if alignment <= sizeof(pointer) then
  72. result := GetMem(size)
  73. else
  74. begin
  75. mem := GetMem(Size+Alignment-1);
  76. memp := align(ptruint(mem), Alignment);
  77. InternalFreemem(mem, ptruint(memp)-ptruint(mem));
  78. result := pointer(memp);
  79. end;
  80. end;
  81. procedure InternalFreeMem(Addr: Pointer; Size: ptruint);
  82. var
  83. b, p, prev: PHeapBlock;
  84. concatenated: boolean;
  85. begin
  86. concatenated := true;
  87. while concatenated do
  88. begin
  89. concatenated := false;
  90. b := addr;
  91. b^.Next := Blocks;
  92. b^.Size := Size;
  93. b^.EndAddr := pointer(ptruint(addr)+size);
  94. if Blocks = nil then
  95. Blocks := b
  96. else
  97. begin
  98. p := Blocks;
  99. prev := nil;
  100. while assigned(p) do
  101. begin
  102. if p^.EndAddr = addr then
  103. begin
  104. addr:=p;
  105. size:=p^.size+size;
  106. if prev = nil then
  107. blocks:=p^.next
  108. else
  109. prev^.next:=p^.next;
  110. concatenated:=true;
  111. break;
  112. end
  113. else if p = b^.EndAddr then
  114. begin
  115. size:=p^.size+size;
  116. if prev = nil then
  117. blocks:=p^.next
  118. else
  119. prev^.next:=p^.next;
  120. concatenated:=true;
  121. break;
  122. end;
  123. prev := p;
  124. p := p^.next;
  125. end;
  126. if not concatenated then
  127. begin
  128. p := Blocks;
  129. prev := nil;
  130. while assigned(p) and (p^.Size < size) do
  131. begin
  132. prev := p;
  133. p := p^.Next;
  134. end;
  135. if assigned(prev) then
  136. begin
  137. b^.Next := p;
  138. prev^.Next := b;
  139. end
  140. else
  141. Blocks := b;
  142. end;
  143. end;
  144. end;
  145. end;
  146. function SysFreeMem(Addr: Pointer): ptruint;
  147. var
  148. sz: ptruint;
  149. begin
  150. sz := Align(FindSize(addr)+SizeOf(ptruint), sizeof(pointer));
  151. InternalFreeMem(@pptruint(addr)[-1], sz);
  152. result := sz;
  153. end;
  154. function SysFreeMemSize(Addr: Pointer; Size: Ptruint): ptruint;
  155. begin
  156. result := SysFreeMem(addr);
  157. end;
  158. function SysMemSize(p: pointer): ptruint;
  159. begin
  160. result := findsize(p);
  161. end;
  162. function SysAllocMem(size: ptruint): pointer;
  163. begin
  164. result := SysGetMem(size);
  165. if result<>nil then
  166. FillChar(result^,SysMemSize(result),0);
  167. end;
  168. function SysReAllocMem(var p: pointer; size: ptruint):pointer;
  169. var
  170. sz: ptruint;
  171. begin
  172. result := AllocMem(size);
  173. if result <> nil then
  174. begin
  175. if p <> nil then
  176. begin
  177. sz := FindSize(p);
  178. if sz > size then
  179. sz := size;
  180. move(pbyte(p)^, pbyte(result)^, sz);
  181. end;
  182. end;
  183. SysFreeMem(p);
  184. p := result;
  185. end;
  186. procedure RegisterHeapBlock(AAddress: pointer; ASize: ptruint);
  187. begin
  188. InternalFreeMem(AAddress, ASize);
  189. end;
  190. const
  191. MyMemoryManager: TMemoryManager = (
  192. NeedLock: false; // Obsolete
  193. GetMem: @SysGetMem;
  194. FreeMem: @SysFreeMem;
  195. FreeMemSize: @SysFreeMemSize;
  196. AllocMem: @SysAllocMem;
  197. ReAllocMem: @SysReAllocMem;
  198. MemSize: @SysMemSize;
  199. InitThread: nil;
  200. DoneThread: nil;
  201. RelocateHeap: nil;
  202. GetHeapStatus: nil;
  203. GetFPCHeapStatus: nil;
  204. );
  205. var
  206. initialheap : record end; external name '__fpc_initialheap';
  207. heapsize : PtrInt; external name '__heapsize';
  208. initialization
  209. SetMemoryManager(MyMemoryManager);
  210. RegisterHeapBlock(@initialheap,heapsize);
  211. finalization
  212. //FinalizeHeap;
  213. end.