heapmgr.pp 6.4 KB

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