heapmgr.pp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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. {$modeswitch result}
  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(pointer), 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) and
  50. (p^.Size-AllocSize >= MinBlock) then
  51. RestSize := p^.Size-AllocSize
  52. else
  53. begin
  54. AllocSize := p^.Size;
  55. RestSize := 0;
  56. end;
  57. if prev = nil then
  58. Blocks := p^.Next
  59. else
  60. prev^.next := p^.next;
  61. pptruint(p)^ := size;
  62. InternalFreemem(pointer(ptruint(p)+AllocSize), RestSize);
  63. end
  64. else
  65. Result := nil;
  66. end;
  67. function GetAlignedMem(Size, Alignment: ptruint): pointer;
  68. var
  69. mem: Pointer;
  70. memp: ptruint;
  71. begin
  72. if alignment <= sizeof(pointer) then
  73. result := GetMem(size)
  74. else
  75. begin
  76. mem := GetMem(Size+Alignment-1+MinBlock);
  77. memp := align(ptruint(mem)+MinBlock, Alignment);
  78. InternalFreemem(mem, ptruint(memp)-ptruint(mem));
  79. result := pointer(memp);
  80. end;
  81. end;
  82. procedure InternalFreeMem(Addr: Pointer; Size: ptruint);
  83. var
  84. b, p, prev: PHeapBlock;
  85. concatenated: boolean;
  86. begin
  87. if size<=0 then
  88. exit;
  89. concatenated := true;
  90. while concatenated do
  91. begin
  92. concatenated := false;
  93. b := addr;
  94. b^.Next := Blocks;
  95. b^.Size := Size;
  96. b^.EndAddr := pointer(ptruint(addr)+size);
  97. if Blocks = nil then
  98. Blocks := b
  99. else
  100. begin
  101. p := Blocks;
  102. prev := nil;
  103. while assigned(p) do
  104. begin
  105. if p^.EndAddr = addr then
  106. begin
  107. addr:=p;
  108. size:=p^.size+size;
  109. if prev = nil then
  110. blocks:=p^.next
  111. else
  112. prev^.next:=p^.next;
  113. concatenated:=true;
  114. break;
  115. end
  116. else if p = b^.EndAddr then
  117. begin
  118. size:=p^.size+size;
  119. if prev = nil then
  120. blocks:=p^.next
  121. else
  122. prev^.next:=p^.next;
  123. concatenated:=true;
  124. break;
  125. end;
  126. prev := p;
  127. p := p^.next;
  128. end;
  129. if not concatenated then
  130. begin
  131. p := Blocks;
  132. prev := nil;
  133. while assigned(p) and (p^.Size < size) do
  134. begin
  135. prev := p;
  136. p := p^.Next;
  137. end;
  138. if assigned(prev) then
  139. begin
  140. b^.Next := p;
  141. prev^.Next := b;
  142. end
  143. else
  144. Blocks := b;
  145. end;
  146. end;
  147. end;
  148. end;
  149. function SysFreeMem(Addr: Pointer): ptruint;
  150. var
  151. sz: ptruint;
  152. begin
  153. if addr=nil then
  154. begin
  155. result:=0;
  156. exit;
  157. end;
  158. sz := Align(FindSize(addr)+SizeOf(pointer), sizeof(pointer));
  159. InternalFreeMem(@pptruint(addr)[-1], sz);
  160. result := sz;
  161. end;
  162. function SysFreeMemSize(Addr: Pointer; Size: Ptruint): ptruint;
  163. begin
  164. result := SysFreeMem(addr);
  165. end;
  166. function SysMemSize(p: pointer): ptruint;
  167. begin
  168. result := findsize(p);
  169. end;
  170. function SysAllocMem(size: ptruint): pointer;
  171. begin
  172. result := SysGetMem(size);
  173. if result<>nil then
  174. FillChar(pbyte(result)^,size,0);
  175. end;
  176. function SysReAllocMem(var p: pointer; size: ptruint):pointer;
  177. var
  178. sz: ptruint;
  179. begin
  180. if size=0 then
  181. begin
  182. SysFreeMem(p);
  183. result := nil;
  184. p := nil;
  185. end
  186. else if p=nil then
  187. begin
  188. result := AllocMem(size);
  189. p := result;
  190. end
  191. else
  192. begin
  193. result := AllocMem(size);
  194. if result <> nil then
  195. begin
  196. if p <> nil then
  197. begin
  198. sz := FindSize(p);
  199. if sz > size then
  200. sz := size;
  201. move(pbyte(p)^, pbyte(result)^, sz);
  202. end;
  203. end;
  204. SysFreeMem(p);
  205. p := result;
  206. end;
  207. end;
  208. procedure RegisterHeapBlock(AAddress: pointer; ASize: ptruint);
  209. begin
  210. InternalFreeMem(AAddress, ASize);
  211. end;
  212. const
  213. MyMemoryManager: TMemoryManager = (
  214. NeedLock: false; // Obsolete
  215. GetMem: @SysGetMem;
  216. FreeMem: @SysFreeMem;
  217. FreeMemSize: @SysFreeMemSize;
  218. AllocMem: @SysAllocMem;
  219. ReAllocMem: @SysReAllocMem;
  220. MemSize: @SysMemSize;
  221. InitThread: nil;
  222. DoneThread: nil;
  223. RelocateHeap: nil;
  224. GetHeapStatus: nil;
  225. GetFPCHeapStatus: nil;
  226. );
  227. var
  228. initialheap : record end; external name '__fpc_initialheap';
  229. heapsize : PtrInt; external name '__heapsize';
  230. initialization
  231. SetMemoryManager(MyMemoryManager);
  232. RegisterHeapBlock(@initialheap,heapsize);
  233. finalization
  234. //FinalizeHeap;
  235. end.