tinyheap.inc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  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: ptruint); 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. if p > HeapPtr then
  129. begin
  130. prev:=HeapPtr;
  131. HeapPtr:=p;
  132. end
  133. else
  134. begin
  135. RegisterTinyHeapBlock(p,AllocSize);
  136. { Recursive call }
  137. SysGetMem:=SysGetMem(Size);
  138. exit;
  139. end;
  140. end
  141. else
  142. begin
  143. if ReturnNilIfGrowHeapFails then
  144. Result := nil
  145. else
  146. HandleError(203);
  147. end;
  148. end;
  149. result := @PTinyHeapMemBlockSize(HeapPtr)[1];
  150. PTinyHeapMemBlockSize(HeapPtr)^ := size;
  151. HeapPtr := pointer(TTinyHeapPointerArithmeticType(HeapPtr)+AllocSize);
  152. if prev = nil then
  153. FreeList := HeapPtr
  154. else
  155. prev^.next := HeapPtr;
  156. end;
  157. {$ifdef DEBUG_TINY_HEAP}
  158. Writeln(HexStr(Result));
  159. {$endif DEBUG_TINY_HEAP}
  160. end;
  161. function TinyGetAlignedMem(Size, Alignment: ptruint): pointer;
  162. var
  163. mem: Pointer;
  164. memp: ptruint;
  165. begin
  166. if alignment <= sizeof(pointer) then
  167. result := GetMem(size)
  168. else
  169. begin
  170. mem := GetMem(Size+Alignment-1);
  171. memp := align(ptruint(mem), Alignment);
  172. InternalTinyFreeMem(mem, TTinyHeapPointerArithmeticType(memp)-TTinyHeapPointerArithmeticType(mem));
  173. result := pointer(memp);
  174. end;
  175. end;
  176. procedure InternalTinyFreeMem(Addr: Pointer; Size: PtrUInt);
  177. var
  178. p, prev: PTinyHeapBlock;
  179. begin
  180. p := FreeList;
  181. prev := nil;
  182. while (p<>HeapPtr) and (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(Addr)) do
  183. begin
  184. prev := p;
  185. p := p^.Next;
  186. end;
  187. { join with previous block? }
  188. if assigned(prev) and ((TTinyHeapPointerArithmeticType(prev)+DecodeTinyHeapFreeBlockSize(prev^.Size)) = TTinyHeapPointerArithmeticType(Addr)) then
  189. begin
  190. Addr:=prev;
  191. Size:=DecodeTinyHeapFreeBlockSize(prev^.size)+Size;
  192. end
  193. else
  194. if assigned(prev) then
  195. prev^.Next := Addr
  196. else
  197. FreeList := Addr;
  198. { join with next block? }
  199. if TTinyHeapPointerArithmeticType(p)=(TTinyHeapPointerArithmeticType(Addr)+Size) then
  200. begin
  201. if p=HeapPtr then
  202. HeapPtr:=Addr
  203. else
  204. begin
  205. PTinyHeapBlock(Addr)^.Next:=p^.Next;
  206. PTinyHeapBlock(Addr)^.Size:=EncodeTinyHeapFreeBlockSize(Size+DecodeTinyHeapFreeBlockSize(p^.Size));
  207. end;
  208. end
  209. else
  210. begin
  211. PTinyHeapBlock(Addr)^.Next:=p;
  212. PTinyHeapBlock(Addr)^.Size:=EncodeTinyHeapFreeBlockSize(Size);
  213. end;
  214. end;
  215. function SysFreeMem(p: Pointer): ptruint;
  216. var
  217. sz: ptruint;
  218. begin
  219. {$ifdef DEBUG_TINY_HEAP}
  220. Writeln('SysFreeMem(', HexStr(p), ')');
  221. {$endif DEBUG_TINY_HEAP}
  222. if p=nil then
  223. begin
  224. result:=0;
  225. exit;
  226. end;
  227. if (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(HeapOrg)) or
  228. (TTinyHeapPointerArithmeticType(p) >= TTinyHeapPointerArithmeticType(HeapPtr)) then
  229. HandleError(204);
  230. sz := Align(FindSize(p)+SizeOf(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  231. InternalTinyFreeMem(@PTinyHeapMemBlockSize(p)[-1], sz);
  232. result := sz;
  233. end;
  234. function SysFreeMemSize(p: Pointer; Size: Ptruint): ptruint;
  235. begin
  236. result := SysFreeMem(p);
  237. end;
  238. function SysMemSize(p: pointer): ptruint;
  239. begin
  240. result := findsize(p);
  241. end;
  242. function SysTryResizeMem(var p: pointer; size: ptruint) : boolean;
  243. begin
  244. result := false;
  245. end;
  246. function SysAllocMem(size: ptruint): pointer;
  247. begin
  248. result := SysGetMem(size);
  249. if result<>nil then
  250. FillChar(result^,SysMemSize(result),0);
  251. end;
  252. function SysReAllocMem(var p: pointer; size: ptruint):pointer;
  253. var
  254. oldsize, OldAllocSize, NewAllocSize: ptruint;
  255. after_block, before_block, before_before_block: PTinyHeapBlock;
  256. after_block_size, before_block_size: PtrUInt;
  257. new_after_block: PTinyHeapBlock;
  258. begin
  259. {$ifdef DEBUG_TINY_HEAP}
  260. Write('SysReAllocMem(', HexStr(p), ',', size, ')=');
  261. {$endif DEBUG_TINY_HEAP}
  262. if size=0 then
  263. begin
  264. SysFreeMem(p);
  265. result := nil;
  266. p := nil;
  267. end
  268. else if p=nil then
  269. begin
  270. result := AllocMem(size);
  271. p := result;
  272. end
  273. else
  274. begin
  275. if (TTinyHeapPointerArithmeticType(p) < TTinyHeapPointerArithmeticType(HeapOrg)) or
  276. (TTinyHeapPointerArithmeticType(p) >= TTinyHeapPointerArithmeticType(HeapPtr)) then
  277. HandleError(204);
  278. oldsize := FindSize(p);
  279. OldAllocSize := align(oldsize+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  280. NewAllocSize := align(size+sizeof(TTinyHeapMemBlockSize), TinyHeapAllocGranularity);
  281. if OldAllocSize = NewAllocSize then
  282. begin
  283. { old and new size are the same after alignment, so the memory block is already allocated }
  284. { we just need to update the size }
  285. PTinyHeapMemBlockSize(p)[-1] := size;
  286. if size > oldsize then
  287. FillChar((TTinyHeapPointerArithmeticType(p)+oldsize)^, size-oldsize, 0);
  288. end
  289. else if OldAllocSize > NewAllocSize then
  290. begin
  291. { we're decreasing the memory block size, so we can just free the remaining memory at the end }
  292. PTinyHeapMemBlockSize(p)[-1] := size;
  293. InternalTinyFreeMem(Pointer(TTinyHeapPointerArithmeticType(p)+(NewAllocSize-PtrUInt(SizeOf(TTinyHeapMemBlockSize)))), OldAllocSize-NewAllocSize);
  294. end
  295. else
  296. begin
  297. { we're increasing the memory block size. First, find if there are free memory blocks immediately
  298. before and after our memory block. }
  299. after_block := FreeList;
  300. before_block := nil;
  301. before_before_block := nil;
  302. while (after_block<>HeapPtr) and (TTinyHeapPointerArithmeticType(after_block) < TTinyHeapPointerArithmeticType(p)) do
  303. begin
  304. before_before_block := before_block;
  305. before_block := after_block;
  306. after_block := after_block^.Next;
  307. end;
  308. { is after_block immediately after our block? }
  309. if after_block=Pointer(TTinyHeapPointerArithmeticType(p)+(OldAllocSize-PtrUInt(SizeOf(TTinyHeapMemBlockSize)))) then
  310. begin
  311. if after_block = HeapPtr then
  312. after_block_size := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr))
  313. else
  314. after_block_size := DecodeTinyHeapFreeBlockSize(after_block^.size);
  315. end
  316. else
  317. after_block_size := 0;
  318. { is there enough room after the block? }
  319. if (OldAllocSize+after_block_size)>=NewAllocSize then
  320. begin
  321. if after_block = HeapPtr then
  322. begin
  323. HeapPtr:=Pointer(TTinyHeapPointerArithmeticType(HeapPtr)+(NewAllocSize-OldAllocSize));
  324. if assigned(before_block) then
  325. before_block^.Next := HeapPtr
  326. else
  327. FreeList := HeapPtr;
  328. end
  329. else
  330. begin
  331. if (NewAllocSize-OldAllocSize)=after_block_size then
  332. begin
  333. if assigned(before_block) then
  334. before_block^.Next := after_block^.Next
  335. else
  336. FreeList := after_block^.Next;
  337. end
  338. else
  339. begin
  340. new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(after_block)+(NewAllocSize-OldAllocSize));
  341. new_after_block^.Next:=after_block^.Next;
  342. new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(after_block_size-(NewAllocSize-OldAllocSize));
  343. if assigned(before_block) then
  344. before_block^.Next := new_after_block
  345. else
  346. FreeList := new_after_block;
  347. end;
  348. end;
  349. PTinyHeapMemBlockSize(p)[-1] := size;
  350. FillChar((TTinyHeapPointerArithmeticType(p)+oldsize)^, size-oldsize, 0);
  351. end
  352. else
  353. begin
  354. { is before_block immediately before our block? }
  355. if assigned(before_block) and (Pointer(TTinyHeapPointerArithmeticType(before_block)+DecodeTinyHeapFreeBlockSize(before_block^.Size))=Pointer(TTinyHeapPointerArithmeticType(p)-SizeOf(TTinyHeapMemBlockSize))) then
  356. before_block_size := DecodeTinyHeapFreeBlockSize(before_block^.Size)
  357. else
  358. before_block_size := 0;
  359. { if there's enough space, we can slide our current block back and reclaim before_block }
  360. if (before_block_size<NewAllocSize) and ((before_block_size+OldAllocSize+after_block_size)>=NewAllocSize) and
  361. { todo: implement this also for after_block_size>0 }
  362. (after_block_size>0) then
  363. begin
  364. if (before_block_size+OldAllocSize+after_block_size)=NewAllocSize then
  365. begin
  366. if after_block=HeapPtr then
  367. begin
  368. HeapPtr := HeapEnd;
  369. if assigned(before_before_block) then
  370. before_before_block^.Next := HeapPtr
  371. else
  372. FreeList := HeapPtr;
  373. end
  374. else
  375. if assigned(before_before_block) then
  376. before_before_block^.Next := after_block^.Next
  377. else
  378. FreeList := after_block^.Next;
  379. end;
  380. Result := Pointer(TTinyHeapPointerArithmeticType(before_block)+SizeOf(TTinyHeapMemBlockSize));
  381. Move(p^, Result^, oldsize);
  382. PTinyHeapMemBlockSize(before_block)^ := size;
  383. if (before_block_size+OldAllocSize+after_block_size)>NewAllocSize then
  384. begin
  385. new_after_block := PTinyHeapBlock(TTinyHeapPointerArithmeticType(before_block)+NewAllocSize);
  386. new_after_block^.Next:=after_block^.Next;
  387. new_after_block^.Size:=EncodeTinyHeapFreeBlockSize(before_block_size+after_block_size-(NewAllocSize-OldAllocSize));
  388. if assigned(before_before_block) then
  389. before_before_block^.Next := new_after_block
  390. else
  391. FreeList := new_after_block;
  392. end;
  393. FillChar((TTinyHeapPointerArithmeticType(Result)+oldsize)^, size-oldsize, 0);
  394. p := Result;
  395. end
  396. else
  397. begin
  398. result := AllocMem(size);
  399. if result <> nil then
  400. begin
  401. if oldsize > size then
  402. oldsize := size;
  403. move(pbyte(p)^, pbyte(result)^, oldsize);
  404. end;
  405. SysFreeMem(p);
  406. p := result;
  407. end;
  408. end;
  409. end;
  410. end;
  411. {$ifdef DEBUG_TINY_HEAP}
  412. Writeln(HexStr(result));
  413. {$endif DEBUG_TINY_HEAP}
  414. end;
  415. function MemAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif};
  416. var
  417. p: PTinyHeapBlock;
  418. begin
  419. MemAvail := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr));
  420. if MemAvail > 0 then
  421. Dec(MemAvail, SizeOf(TTinyHeapMemBlockSize));
  422. p := FreeList;
  423. while p <> HeapPtr do
  424. begin
  425. Inc(MemAvail, DecodeTinyHeapFreeBlockSize(p^.Size)-SizeOf(TTinyHeapMemBlockSize));
  426. p := p^.Next;
  427. end;
  428. end;
  429. function MaxAvail: {$ifdef FPC_TINYHEAP_HUGE}LongInt{$else}PtrUInt{$endif};
  430. var
  431. p: PTinyHeapBlock;
  432. begin
  433. MaxAvail := PtrUInt(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr));
  434. p := FreeList;
  435. while p <> HeapPtr do
  436. begin
  437. if DecodeTinyHeapFreeBlockSize(p^.Size) > MaxAvail then
  438. MaxAvail := DecodeTinyHeapFreeBlockSize(p^.Size);
  439. p := p^.Next;
  440. end;
  441. if MaxAvail > 0 then
  442. Dec(MaxAvail, SizeOf(TTinyHeapMemBlockSize));
  443. end;
  444. procedure Mark(var p: Pointer);
  445. begin
  446. p := HeapPtr;
  447. end;
  448. procedure Release(var p: Pointer);
  449. begin
  450. HeapPtr := p;
  451. FreeList := p;
  452. end;
  453. procedure InternalTinyAlign(var AAddress: Pointer; ASize: PtrUInt);
  454. var
  455. alignment_inc: smallint;
  456. begin
  457. alignment_inc := TTinyHeapPointerArithmeticType(align(AAddress,TinyHeapAllocGranularity))-TTinyHeapPointerArithmeticType(AAddress);
  458. Inc(AAddress,alignment_inc);
  459. Dec(ASize,alignment_inc);
  460. Dec(ASize,ASize mod TinyHeapAllocGranularity);
  461. end;
  462. { Strongly simplified version of RegisterTinyHeapBlock, which can be used when
  463. the heap is only a single contiguous memory block. If you want to add
  464. multiple blocks to the heap, you should use RegisterTinyHeapBlock instead. }
  465. procedure RegisterTinyHeapBlock_Simple(AAddress: Pointer; ASize: PtrUInt);
  466. begin
  467. {$ifdef DEBUG_TINY_HEAP}
  468. Writeln('RegisterTinyHeapBlock_Simple(', HexStr(AAddress), ',', ASize, ')');
  469. {$endif DEBUG_TINY_HEAP}
  470. InternalTinyAlign(AAddress, ASize);
  471. HeapSize:=HeapSize + ASize;
  472. HeapOrg:=AAddress;
  473. HeapPtr:=AAddress;
  474. FreeList:=AAddress;
  475. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  476. end;
  477. { Strongly simplified version of RegisterTinyHeapBlock, which can be used when
  478. the heap is only a single contiguous memory block and the address and size
  479. are already aligned on a TinyHeapAllocGranularity boundary. }
  480. procedure RegisterTinyHeapBlock_Simple_Prealigned(AAddress: Pointer; ASize: PtrUInt);
  481. begin
  482. {$ifdef DEBUG_TINY_HEAP}
  483. Writeln('RegisterTinyHeapBlock_Simple_Prealigned(', HexStr(AAddress), ',', ASize, ')');
  484. {$endif DEBUG_TINY_HEAP}
  485. HeapOrg:=AAddress;
  486. HeapPtr:=AAddress;
  487. FreeList:=AAddress;
  488. HeapSize:=HeapSize + ASize;
  489. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  490. end;
  491. procedure RegisterTinyHeapBlock(AAddress: pointer; ASize: ptruint);
  492. var
  493. alignment_inc: smallint;
  494. p: PTinyHeapBlock;
  495. begin
  496. {$ifdef DEBUG_TINY_HEAP}
  497. Writeln('RegisterTinyHeapBlock(', HexStr(AAddress), ',', ASize, ')');
  498. {$endif DEBUG_TINY_HEAP}
  499. InternalTinyAlign(AAddress, ASize);
  500. HeapSize:=HeapSize + ASize;
  501. if HeapOrg=nil then
  502. begin
  503. HeapOrg:=AAddress;
  504. HeapPtr:=AAddress;
  505. FreeList:=AAddress;
  506. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  507. end
  508. else
  509. begin
  510. if (TTinyHeapPointerArithmeticType(HeapOrg) > TTinyHeapPointerArithmeticType(AAddress)) then
  511. HeapOrg:=AAddress;
  512. if TTinyHeapPointerArithmeticType(AAddress) > TTinyHeapPointerArithmeticType(HeapEnd) then
  513. begin
  514. if TTinyHeapPointerArithmeticType(HeapPtr) = TTinyHeapPointerArithmeticType(HeapEnd) then
  515. begin
  516. if FreeList=HeapPtr then
  517. FreeList:=AAddress
  518. else
  519. begin
  520. p:=FreeList;
  521. while p^.Next<>HeapPtr do
  522. p:=p^.Next;
  523. PTinyHeapBlock(HeapPtr)^.Next:=AAddress;
  524. end;
  525. end
  526. else
  527. begin
  528. PTinyHeapBlock(HeapPtr)^.Size:=EncodeTinyHeapFreeBlockSize(TTinyHeapPointerArithmeticType(HeapEnd)-TTinyHeapPointerArithmeticType(HeapPtr));
  529. PTinyHeapBlock(HeapPtr)^.Next:=AAddress;
  530. end;
  531. HeapPtr:=AAddress;
  532. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize);
  533. end
  534. else if TTinyHeapPointerArithmeticType(AAddress) = TTinyHeapPointerArithmeticType(HeapEnd) then
  535. HeapEnd:=Pointer(TTinyHeapPointerArithmeticType(AAddress)+ASize)
  536. else
  537. InternalTinyFreeMem(AAddress, ASize);
  538. end;
  539. end;
  540. function SysGetFPCHeapStatus : TFPCHeapStatus;
  541. {
  542. TFPCHeapStatus = record
  543. MaxHeapSize,
  544. MaxHeapUsed,
  545. CurrHeapSize,
  546. CurrHeapUsed,
  547. CurrHeapFree : ptruint;
  548. end;
  549. }
  550. begin
  551. SysGetFPCHeapStatus.MaxHeapSize:=MaxAvail;
  552. { How can we compute this? }
  553. SysGetFPCHeapStatus.MaxHeapUsed:=0;
  554. SysGetFPCHeapStatus.CurrHeapFree:=MemAvail;
  555. SysGetFPCHeapStatus.CurrHeapUsed:=HeapSize-SysGetFPCHeapStatus.CurrHeapFree;
  556. SysGetFPCHeapStatus.CurrHeapSize:=HeapSize;
  557. end;
  558. function SysGetHeapStatus : THeapStatus;
  559. begin
  560. SysGetHeapStatus.TotalAddrSpace:= HeapSize;
  561. SysGetHeapStatus.TotalUncommitted:= 0;
  562. SysGetHeapStatus.TotalCommitted:= 0;
  563. SysGetHeapStatus.TotalAllocated:= HeapSize-MemAvail;
  564. SysGetHeapStatus.TotalFree:= MemAvail;
  565. SysGetHeapStatus.FreeSmall:= 0;
  566. SysGetHeapStatus.FreeBig:= 0;
  567. SysGetHeapStatus.Unused:= 0;
  568. SysGetHeapStatus.Overhead:= 0;
  569. SysGetHeapStatus.HeapErrorCode:= 0;
  570. end;
  571. procedure FinalizeHeap;
  572. begin
  573. end;