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