tinyheap.inc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  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 i8086 near heap, embedded targets, etc.
  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. { The heap, implemented here is TP7-compatible in the i8086 far data memory
  12. models. It's basically a linked list of free blocks, which are kept ordered by
  13. start address. The FreeList variable points to the start of the list. Each
  14. free block, except the last one, contains a TTinyHeapBlock structure, which
  15. holds the block size and a pointer to the next free block. The HeapPtr
  16. variable points to the last free block, indicating the end of the list. The
  17. last block is special in that it doesn't contain a TTinyHeapBlock structure.
  18. Instead its size is determined by the pointer difference (HeapEnd-HeapPtr).
  19. It *can* become zero sized, when all the memory inside of it is allocated, in
  20. which case, HeapPtr will become equal to HeapEnd. }
  21. {$ifdef FPC_TINYHEAP_HUGE}
  22. {$HugePointerArithmeticNormalization On}
  23. {$HugePointerComparisonNormalization On}
  24. {$endif FPC_TINYHEAP_HUGE}
  25. type
  26. { TTinyHeapMemBlockSize holds the size of an *allocated* memory block,
  27. and is written at position:
  28. memblockstart-sizeof(TTinyHeapMemBlockSize) }
  29. PTinyHeapMemBlockSize = ^TTinyHeapMemBlockSize; {$ifdef FPC_TINYHEAP_HUGE}huge;{$endif}
  30. TTinyHeapMemBlockSize = PtrUInt;
  31. { TTinyHeapFreeBlockSize holds the size of a *free* memory block, as a
  32. part of the TTinyHeapBlock structure }
  33. {$ifdef FPC_TINYHEAP_HUGE}
  34. TTinyHeapFreeBlockSize = record
  35. OfsSize: Word;
  36. SegSize: Word;
  37. end;
  38. {$else FPC_TINYHEAP_HUGE}
  39. TTinyHeapFreeBlockSize = PtrUInt;
  40. {$endif FPC_TINYHEAP_HUGE}
  41. TTinyHeapPointerArithmeticType = ^Byte; {$ifdef FPC_TINYHEAP_HUGE}huge;{$endif}
  42. PTinyHeapBlock = ^TTinyHeapBlock;
  43. TTinyHeapBlock = record
  44. Next: PTinyHeapBlock;
  45. Size: TTinyHeapFreeBlockSize;
  46. end;
  47. const
  48. TinyHeapMinBlock = sizeof(TTinyHeapBlock);
  49. TinyHeapAllocGranularity = sizeof(TTinyHeapBlock);
  50. procedure RegisterTinyHeapBlock(AAddress: Pointer; ASize:{$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif}); forward;
  51. function EncodeTinyHeapFreeBlockSize(Size: PtrUInt): TTinyHeapFreeBlockSize; inline;
  52. begin
  53. {$ifdef FPC_TINYHEAP_HUGE}
  54. EncodeTinyHeapFreeBlockSize.OfsSize := Size and 15;
  55. EncodeTinyHeapFreeBlockSize.SegSize := Size shr 4;
  56. {$else FPC_TINYHEAP_HUGE}
  57. EncodeTinyHeapFreeBlockSize := Size;
  58. {$endif FPC_TINYHEAP_HUGE}
  59. end;
  60. function DecodeTinyHeapFreeBlockSize(Size: TTinyHeapFreeBlockSize): PtrUInt; inline;
  61. begin
  62. {$ifdef FPC_TINYHEAP_HUGE}
  63. DecodeTinyHeapFreeBlockSize := (PtrUInt(Size.SegSize) shl 4) + Size.OfsSize;
  64. {$else FPC_TINYHEAP_HUGE}
  65. DecodeTinyHeapFreeBlockSize := Size;
  66. {$endif FPC_TINYHEAP_HUGE}
  67. end;
  68. procedure InternalTinyFreeMem(Addr: Pointer; Size: PtrUInt); forward;
  69. function FindSize(p: pointer): TTinyHeapMemBlockSize;
  70. begin
  71. FindSize := PTinyHeapMemBlockSize(p)[-1];
  72. end;
  73. function SysGetMem(Size: ptruint): pointer;
  74. var
  75. p, prev, p2: PTinyHeapBlock;
  76. AllocSize, RestSize: ptruint;
  77. begin
  78. {$ifdef DEBUG_TINY_HEAP}
  79. Write('SysGetMem(', Size, ')=');
  80. {$endif DEBUG_TINY_HEAP}
  81. AllocSize := align(size+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  82. p := FreeList;
  83. prev := nil;
  84. while (p<>HeapPtr) and (DecodeTinyHeapFreeBlockSize(p^.Size) < AllocSize) do
  85. begin
  86. prev := p;
  87. p := p^.Next;
  88. end;
  89. if p<>HeapPtr then
  90. begin
  91. result := @PTinyHeapMemBlockSize(p)[1];
  92. if DecodeTinyHeapFreeBlockSize(p^.Size)-AllocSize >= TinyHeapMinBlock then
  93. RestSize := DecodeTinyHeapFreeBlockSize(p^.Size)-AllocSize
  94. else
  95. begin
  96. AllocSize := DecodeTinyHeapFreeBlockSize(p^.Size);
  97. RestSize := 0;
  98. end;
  99. if RestSize > 0 then
  100. begin
  101. p2 := pointer(TTinyHeapPointerArithmeticType(p)+AllocSize);
  102. p2^.Next := p^.Next;
  103. p2^.Size := EncodeTinyHeapFreeBlockSize(RestSize);
  104. if prev = nil then
  105. FreeList := p2
  106. else
  107. prev^.next := p2;
  108. end
  109. else
  110. begin
  111. if prev = nil then
  112. FreeList := p^.Next
  113. else
  114. prev^.next := p^.next;
  115. end;
  116. PTinyHeapMemBlockSize(p)^ := size;
  117. end
  118. else
  119. begin
  120. { p=HeapPtr }
  121. if PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr))<AllocSize then
  122. begin
  123. { align to 16 bytes }
  124. AllocSize:= (AllocSize + $f) and (not $f);
  125. p:=SysOSAlloc(AllocSize);
  126. if assigned(p) then
  127. begin
  128. { This needs toi be fixed because
  129. HeapEnd and HeapSize are not updated correctly
  130. if p > HeapPtr then
  131. begin
  132. prev:=HeapPtr;
  133. HeapPtr:=p;
  134. end
  135. else }
  136. begin
  137. {$ifdef DEBUG_TINY_HEAP}
  138. Writeln('SysAlloc returned: ',HexStr(p));
  139. {$endif DEBUG_TINY_HEAP}
  140. RegisterTinyHeapBlock(p,AllocSize);
  141. { Recursive call }
  142. SysGetMem:=SysGetMem(Size);
  143. exit;
  144. end;
  145. end
  146. else
  147. begin
  148. if ReturnNilIfGrowHeapFails then
  149. begin
  150. Result := nil;
  151. exit;
  152. end
  153. else
  154. HandleError(203);
  155. end;
  156. end;
  157. result := @PTinyHeapMemBlockSize(HeapPtr)[1];
  158. PTinyHeapMemBlockSize(HeapPtr)^ := size;
  159. HeapPtr := pointer(TTinyHeapPointerArithmeticType(HeapPtr)+AllocSize);
  160. if prev = nil then
  161. FreeList := HeapPtr
  162. else
  163. prev^.next := HeapPtr;
  164. end;
  165. {$ifdef DEBUG_TINY_HEAP}
  166. Writeln(HexStr(Result));
  167. {$endif DEBUG_TINY_HEAP}
  168. end;
  169. function TinyGetAlignedMem(Size, Alignment: ptruint): pointer;
  170. var
  171. mem: Pointer;
  172. memp: ptruint;
  173. begin
  174. if alignment <= sizeof(pointer) then
  175. result := GetMem(size)
  176. else
  177. begin
  178. mem := GetMem(Size+Alignment-1);
  179. memp := align(ptruint(mem), Alignment);
  180. InternalTinyFreeMem(mem, TTinyHeapPointerArithmeticType(memp)-TTinyHeapPointerArithmeticType(mem));
  181. result := pointer(memp);
  182. end;
  183. end;
  184. procedure InternalTinyFreeMem(Addr: Pointer; Size: PtrUInt);
  185. var
  186. p, prev: PTinyHeapBlock;
  187. begin
  188. p := FreeList;
  189. prev := nil;
  190. while (p<>HeapPtr) and (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(Addr)) do
  191. begin
  192. prev := p;
  193. p := p^.Next;
  194. end;
  195. { join with previous block? }
  196. if assigned(prev) and ((TTinyHeapPointerArithmeticType(prev)+DecodeTinyHeapFreeBlockSize(prev^.Size)) = TTinyHeapPointerArithmeticType(Addr)) then
  197. begin
  198. Addr:=prev;
  199. Size:=DecodeTinyHeapFreeBlockSize(prev^.size)+Size;
  200. end
  201. else
  202. if assigned(prev) then
  203. prev^.Next := Addr
  204. else
  205. FreeList := Addr;
  206. { join with next block? }
  207. if TTinyHeapPointerArithmeticType(p)=(TTinyHeapPointerArithmeticType(Addr)+Size) then
  208. begin
  209. if p=HeapPtr then
  210. HeapPtr:=Addr
  211. else
  212. begin
  213. PTinyHeapBlock(Addr)^.Next:=p^.Next;
  214. PTinyHeapBlock(Addr)^.Size:=EncodeTinyHeapFreeBlockSize(Size+DecodeTinyHeapFreeBlockSize(p^.Size));
  215. end;
  216. end
  217. else
  218. begin
  219. PTinyHeapBlock(Addr)^.Next:=p;
  220. PTinyHeapBlock(Addr)^.Size:=EncodeTinyHeapFreeBlockSize(Size);
  221. end;
  222. end;
  223. function SysFreeMem(p: Pointer): ptruint;
  224. var
  225. sz: ptruint;
  226. begin
  227. {$ifdef DEBUG_TINY_HEAP}
  228. Writeln('SysFreeMem(', HexStr(p), ')');
  229. {$endif DEBUG_TINY_HEAP}
  230. if p=nil then
  231. begin
  232. result:=0;
  233. exit;
  234. end;
  235. if (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(HeapOrg)) or
  236. (TTinyHeapPointerArithmeticType(p) >= TTinyHeapPointerArithmeticType(HeapPtr)) then
  237. HandleError(204);
  238. sz := Align(FindSize(p)+SizeOf(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  239. InternalTinyFreeMem(@PTinyHeapMemBlockSize(p)[-1], sz);
  240. result := sz;
  241. end;
  242. function SysFreeMemSize(p: Pointer; Size: Ptruint): ptruint;
  243. begin
  244. result := SysFreeMem(p);
  245. end;
  246. function SysMemSize(p: pointer): ptruint;
  247. begin
  248. result := findsize(p);
  249. end;
  250. function SysTryResizeMem(var p: pointer; size: ptruint) : boolean;
  251. begin
  252. result := false;
  253. end;
  254. function SysAllocMem(size: ptruint): pointer;
  255. begin
  256. result := SysGetMem(size);
  257. if result<>nil then
  258. FillChar(result^,SysMemSize(result),0);
  259. end;
  260. function SysReAllocMem(var p: pointer; size: ptruint):pointer;
  261. var
  262. oldsize, OldAllocSize, NewAllocSize: ptruint;
  263. after_block, before_block, before_before_block: PTinyHeapBlock;
  264. after_block_size, before_block_size: PtrUInt;
  265. new_after_block: PTinyHeapBlock;
  266. begin
  267. {$ifdef DEBUG_TINY_HEAP}
  268. Write('SysReAllocMem(', HexStr(p), ',', size, ')=');
  269. {$endif DEBUG_TINY_HEAP}
  270. if size=0 then
  271. begin
  272. SysFreeMem(p);
  273. result := nil;
  274. p := nil;
  275. end
  276. else if p=nil then
  277. begin
  278. result := AllocMem(size);
  279. p := result;
  280. end
  281. else
  282. begin
  283. if (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(HeapOrg)) or
  284. (TTinyHeapPointerArithmeticType(p) >= TTinyHeapPointerArithmeticType(HeapPtr)) then
  285. HandleError(204);
  286. oldsize := FindSize(p);
  287. OldAllocSize := align(oldsize+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  288. NewAllocSize := align(size+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  289. if OldAllocSize = NewAllocSize then
  290. begin
  291. { old and new size are the same after alignment, so the memory block is already allocated }
  292. { we just need to update the size }
  293. PTinyHeapMemBlockSize(p)[-1] := size;
  294. if size > oldsize then
  295. FillChar((TTinyHeapPointerArithmeticType(p)+oldsize)^, size-oldsize, 0);
  296. end
  297. else if OldAllocSize > NewAllocSize then
  298. begin
  299. { we're decreasing the memory block size, so we can just free the remaining memory at the end }
  300. PTinyHeapMemBlockSize(p)[-1] := size;
  301. InternalTinyFreeMem(Pointer(TTinyHeapPointerArithmeticType(p)+(NewAllocSize-PtrUInt(SizeOf(TTinyHeapMemBlockSize)))), OldAllocSize-NewAllocSize);
  302. end
  303. else
  304. begin
  305. { we're increasing the memory block size. First, find if there are free memory blocks immediately
  306. before and after our memory block. }
  307. after_block := FreeList;
  308. before_block := nil;
  309. before_before_block := nil;
  310. while (after_block<>HeapPtr) and (TTinyHeapPointerArithmeticType(after_block) < TTinyHeapPointerArithmeticType(p)) do
  311. begin
  312. before_before_block := before_block;
  313. before_block := after_block;
  314. after_block := after_block^.Next;
  315. end;
  316. { is after_block immediately after our block? }
  317. if after_block=Pointer(TTinyHeapPointerArithmeticType(p)+(OldAllocSize-PtrUInt(SizeOf(TTinyHeapMemBlockSize)))) then
  318. begin
  319. if after_block = HeapPtr then
  320. after_block_size := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr))
  321. else
  322. after_block_size := DecodeTinyHeapFreeBlockSize(after_block^.size);
  323. end
  324. else
  325. after_block_size := 0;
  326. { is there enough room after the block? }
  327. if (OldAllocSize+after_block_size)>=NewAllocSize then
  328. begin
  329. if after_block = HeapPtr then
  330. begin
  331. HeapPtr:=Pointer(TTinyHeapPointerArithmeticType(HeapPtr)+(NewAllocSize-OldAllocSize));
  332. if assigned(before_block) then
  333. before_block^.Next := HeapPtr
  334. else
  335. FreeList := HeapPtr;
  336. end
  337. else
  338. begin
  339. if (NewAllocSize-OldAllocSize)=after_block_size then
  340. begin
  341. if assigned(before_block) then
  342. before_block^.Next := after_block^.Next
  343. else
  344. FreeList := after_block^.Next;
  345. end
  346. else
  347. begin
  348. new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(after_block)+(NewAllocSize-OldAllocSize));
  349. new_after_block^.Next:=after_block^.Next;
  350. new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(after_block_size-(NewAllocSize-OldAllocSize));
  351. if assigned(before_block) then
  352. before_block^.Next := new_after_block
  353. else
  354. FreeList := new_after_block;
  355. end;
  356. end;
  357. PTinyHeapMemBlockSize(p)[-1] := size;
  358. FillChar((TTinyHeapPointerArithmeticType(p)+oldsize)^, size-oldsize, 0);
  359. end
  360. else
  361. begin
  362. { is before_block immediately before our block? }
  363. if assigned(before_block) and (Pointer(TTinyHeapPointerArithmeticType(before_block)+DecodeTinyHeapFreeBlockSize(before_block^.Size))=Pointer(TTinyHeapPointerArithmeticType(p)-SizeOf(TTinyHeapMemBlockSize))) then
  364. before_block_size := DecodeTinyHeapFreeBlockSize(before_block^.Size)
  365. else
  366. before_block_size := 0;
  367. { if there's enough space, we can slide our current block back and reclaim before_block }
  368. if (before_block_size<NewAllocSize) and ((before_block_size+OldAllocSize+after_block_size)>=NewAllocSize) and
  369. { todo: implement this also for after_block_size>0 }
  370. (after_block_size>0) then
  371. begin
  372. if (before_block_size+OldAllocSize+after_block_size)=NewAllocSize then
  373. begin
  374. if after_block=HeapPtr then
  375. begin
  376. HeapPtr := HeapEnd;
  377. if assigned(before_before_block) then
  378. before_before_block^.Next := HeapPtr
  379. else
  380. FreeList := HeapPtr;
  381. end
  382. else
  383. if assigned(before_before_block) then
  384. before_before_block^.Next := after_block^.Next
  385. else
  386. FreeList := after_block^.Next;
  387. end;
  388. Result := Pointer(TTinyHeapPointerArithmeticType(before_block)+SizeOf(TTinyHeapMemBlockSize));
  389. Move(p^, Result^, oldsize);
  390. PTinyHeapMemBlockSize(before_block)^ := size;
  391. if (before_block_size+OldAllocSize+after_block_size)>NewAllocSize then
  392. begin
  393. new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(before_block)+NewAllocSize);
  394. new_after_block^.Next:=after_block^.Next;
  395. new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(before_block_size+after_block_size-(NewAllocSize-OldAllocSize));
  396. if assigned(before_before_block) then
  397. before_before_block^.Next := new_after_block
  398. else
  399. FreeList := new_after_block;
  400. end;
  401. FillChar((TTinyHeapPointerArithmeticType(Result)+oldsize)^, size-oldsize, 0);
  402. p := Result;
  403. end
  404. else
  405. begin
  406. result := AllocMem(size);
  407. if result <> nil then
  408. begin
  409. if oldsize > size then
  410. oldsize := size;
  411. move(pbyte(p)^, pbyte(result)^, oldsize);
  412. end;
  413. SysFreeMem(p);
  414. p := result;
  415. end;
  416. end;
  417. end;
  418. end;
  419. {$ifdef DEBUG_TINY_HEAP}
  420. Writeln(HexStr(result));
  421. {$endif DEBUG_TINY_HEAP}
  422. end;
  423. function MemAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif};
  424. var
  425. p: PTinyHeapBlock;
  426. begin
  427. MemAvail := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr));
  428. if MemAvail > 0 then
  429. Dec(MemAvail, SizeOf(TTinyHeapMemBlockSize));
  430. p := FreeList;
  431. while p <> HeapPtr do
  432. begin
  433. Inc(MemAvail, DecodeTinyHeapFreeBlockSize(p^.Size)-SizeOf(TTinyHeapMemBlockSize));
  434. p := p^.Next;
  435. end;
  436. end;
  437. function MaxAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif};
  438. var
  439. p: PTinyHeapBlock;
  440. begin
  441. MaxAvail := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr));
  442. p := FreeList;
  443. while p <> HeapPtr do
  444. begin
  445. if DecodeTinyHeapFreeBlockSize(p^.Size) > MaxAvail then
  446. MaxAvail := DecodeTinyHeapFreeBlockSize(p^.Size);
  447. p := p^.Next;
  448. end;
  449. if MaxAvail > 0 then
  450. Dec(MaxAvail, SizeOf(TTinyHeapMemBlockSize));
  451. end;
  452. procedure Mark(var p: Pointer);
  453. begin
  454. p := HeapPtr;
  455. end;
  456. procedure Release(var p: Pointer);
  457. begin
  458. HeapPtr := p;
  459. FreeList := p;
  460. end;
  461. procedure InternalTinyAlign(var AAddress: Pointer; var ASize: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif});
  462. var
  463. alignment_inc: smallint;
  464. begin
  465. alignment_inc := TTinyHeapPointerArithmeticType(align(AAddress,TinyHeapAllocGranularity))-TTinyHeapPointerArithmeticType(AAddress);
  466. Inc(AAddress,alignment_inc);
  467. Dec(ASize,alignment_inc);
  468. Dec(ASize,ASize mod TinyHeapAllocGranularity);
  469. end;
  470. { Strongly simplified version of RegisterTinyHeapBlock, which can be used when
  471. the heap is only a single contiguous memory block. If you want to add
  472. multiple blocks to the heap, you should use RegisterTinyHeapBlock instead. }
  473. procedure RegisterTinyHeapBlock_Simple(AAddress: Pointer; ASize:{$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif});
  474. begin
  475. {$ifdef DEBUG_TINY_HEAP}
  476. Writeln('RegisterTinyHeapBlock_Simple(', HexStr(AAddress), ',', ASize, ')');
  477. {$endif DEBUG_TINY_HEAP}
  478. InternalTinyAlign(AAddress, ASize);
  479. HeapSize:=HeapSize + ASize;
  480. HeapOrg:=AAddress;
  481. HeapPtr:=AAddress;
  482. FreeList:=AAddress;
  483. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  484. end;
  485. { Strongly simplified version of RegisterTinyHeapBlock, which can be used when
  486. the heap is only a single contiguous memory block and the address and size
  487. are already aligned on a TinyHeapAllocGranularity boundary. }
  488. procedure RegisterTinyHeapBlock_Simple_Prealigned(AAddress: Pointer; ASize: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif});
  489. begin
  490. {$ifdef DEBUG_TINY_HEAP}
  491. Writeln('RegisterTinyHeapBlock_Simple_Prealigned(', HexStr(AAddress), ',', ASize, ')');
  492. {$endif DEBUG_TINY_HEAP}
  493. HeapOrg:=AAddress;
  494. HeapPtr:=AAddress;
  495. FreeList:=AAddress;
  496. HeapSize:=HeapSize + ASize;
  497. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  498. end;
  499. procedure RegisterTinyHeapBlock(AAddress: pointer; ASize: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif});
  500. var
  501. alignment_inc: smallint;
  502. p: PTinyHeapBlock;
  503. begin
  504. {$ifdef DEBUG_TINY_HEAP}
  505. Writeln('RegisterTinyHeapBlock(', HexStr(AAddress), ',', ASize, ')');
  506. {$endif DEBUG_TINY_HEAP}
  507. InternalTinyAlign(AAddress, ASize);
  508. HeapSize:=HeapSize + ASize;
  509. if HeapOrg=nil then
  510. begin
  511. HeapOrg:=AAddress;
  512. HeapPtr:=AAddress;
  513. FreeList:=AAddress;
  514. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  515. end
  516. else
  517. begin
  518. if (TTinyHeapPointerArithmeticType(HeapOrg) > TTinyHeapPointerArithmeticType(AAddress)) then
  519. HeapOrg:=AAddress;
  520. if TTinyHeapPointerArithmeticType(AAddress) > TTinyHeapPointerArithmeticType(HeapEnd) then
  521. begin
  522. if TTinyHeapPointerArithmeticType(HeapPtr) = TTinyHeapPointerArithmeticType(HeapEnd) then
  523. begin
  524. if FreeList=HeapPtr then
  525. FreeList:=AAddress
  526. else
  527. begin
  528. p:=FreeList;
  529. while p^.Next<>HeapPtr do
  530. p:=p^.Next;
  531. PTinyHeapBlock(p)^.Next:=AAddress;
  532. end;
  533. end
  534. else
  535. begin
  536. PTinyHeapBlock(HeapPtr)^.Size:=EncodeTinyHeapFreeBlockSize(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr));
  537. PTinyHeapBlock(HeapPtr)^.Next:=AAddress;
  538. end;
  539. HeapPtr:=AAddress;
  540. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  541. end
  542. else if TTinyHeapPointerArithmeticType(AAddress) = TTinyHeapPointerArithmeticType(HeapEnd) then
  543. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize)
  544. else
  545. InternalTinyFreeMem(AAddress, ASize);
  546. end;
  547. end;
  548. function SysGetFPCHeapStatus : TFPCHeapStatus;
  549. {
  550. TFPCHeapStatus = record
  551. MaxHeapSize,
  552. MaxHeapUsed,
  553. CurrHeapSize,
  554. CurrHeapUsed,
  555. CurrHeapFree : ptruint;
  556. end;
  557. }
  558. begin
  559. SysGetFPCHeapStatus.MaxHeapSize:=MaxAvail;
  560. { How can we compute this? }
  561. SysGetFPCHeapStatus.MaxHeapUsed:=0;
  562. SysGetFPCHeapStatus.CurrHeapFree:=MemAvail;
  563. SysGetFPCHeapStatus.CurrHeapUsed:=HeapSize-SysGetFPCHeapStatus.CurrHeapFree;
  564. SysGetFPCHeapStatus.CurrHeapSize:=HeapSize;
  565. end;
  566. function SysGetHeapStatus : THeapStatus;
  567. begin
  568. SysGetHeapStatus.TotalAddrSpace:= HeapSize;
  569. SysGetHeapStatus.TotalUncommitted:= 0;
  570. SysGetHeapStatus.TotalCommitted:= 0;
  571. SysGetHeapStatus.TotalAllocated:= HeapSize-MemAvail;
  572. SysGetHeapStatus.TotalFree:= MemAvail;
  573. SysGetHeapStatus.FreeSmall:= 0;
  574. SysGetHeapStatus.FreeBig:= 0;
  575. SysGetHeapStatus.Unused:= 0;
  576. SysGetHeapStatus.Overhead:= 0;
  577. SysGetHeapStatus.HeapErrorCode:= 0;
  578. end;
  579. procedure FinalizeHeap;
  580. begin
  581. end;