heap.inc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team.
  5. functions for heap management in the data segment
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {****************************************************************************}
  13. { Reuse bigger blocks instead of allocating a new block at freelist/heapptr.
  14. the tried bigger blocks are always multiple sizes of the current block }
  15. {$define REUSEBIGGER}
  16. { Allocate small blocks at heapptr instead of walking the freelist }
  17. {$define SMALLATHEAPPTR}
  18. { Try to find the best matching block in general freelist }
  19. {$define BESTMATCH}
  20. { DEBUG: Dump info when the heap needs to grow }
  21. { define DUMPGROW}
  22. { Default heap settings }
  23. const
  24. blocksize = 16; { at least size of freerecord }
  25. blockshr = 4; { shr value for blocksize=2^blockshr}
  26. maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
  27. maxblock = maxblocksize div blocksize;
  28. maxreusebigger = 8; { max reuse bigger tries }
  29. usedmask = 1; { flag if the block is used or not }
  30. beforeheapendmask = 2; { flag if the block is just before a heapptr }
  31. sizemask = not(blocksize-1);
  32. {****************************************************************************}
  33. {$ifdef DUMPGROW}
  34. {$define DUMPBLOCKS}
  35. {$endif}
  36. { Memory manager }
  37. const
  38. MemoryManager: TMemoryManager = (
  39. GetMem: SysGetMem;
  40. FreeMem: SysFreeMem;
  41. FreeMemSize: SysFreeMemSize;
  42. AllocMem: SysAllocMem;
  43. ReAllocMem: SysReAllocMem;
  44. MemSize: SysMemSize;
  45. MemAvail: SysMemAvail;
  46. MaxAvail: SysMaxAvail;
  47. HeapSize: SysHeapSize;
  48. );
  49. type
  50. ppfreerecord = ^pfreerecord;
  51. pfreerecord = ^tfreerecord;
  52. tfreerecord = record
  53. size : longint;
  54. next,
  55. prev : pfreerecord;
  56. end; { 12 bytes }
  57. pheaprecord = ^theaprecord;
  58. theaprecord = record
  59. { this should overlap with tfreerecord }
  60. size : longint;
  61. end; { 4 bytes }
  62. tfreelists = array[0..maxblock] of pfreerecord;
  63. pfreelists = ^tfreelists;
  64. var
  65. internal_memavail : longint;
  66. internal_heapsize : longint;
  67. freelists : tfreelists;
  68. {*****************************************************************************
  69. Memory Manager
  70. *****************************************************************************}
  71. procedure GetMemoryManager(var MemMgr:TMemoryManager);
  72. begin
  73. MemMgr:=MemoryManager;
  74. end;
  75. procedure SetMemoryManager(const MemMgr:TMemoryManager);
  76. begin
  77. MemoryManager:=MemMgr;
  78. end;
  79. function IsMemoryManagerSet:Boolean;
  80. begin
  81. IsMemoryManagerSet:=(MemoryManager.GetMem<>@SysGetMem) or
  82. (MemoryManager.FreeMem<>@SysFreeMem);
  83. end;
  84. procedure GetMem(Var p:pointer;Size:Longint);{$ifndef NEWMM}[public,alias:'FPC_GETMEM'];{$endif}
  85. begin
  86. p:=MemoryManager.GetMem(Size);
  87. end;
  88. procedure FreeMem(Var p:pointer;Size:Longint);{$ifndef NEWMM}[public,alias:'FPC_FREEMEM'];{$endif}
  89. begin
  90. MemoryManager.FreeMemSize(p,Size);
  91. p:=nil;
  92. end;
  93. function MaxAvail:Longint;
  94. begin
  95. MaxAvail:=MemoryManager.MaxAvail();
  96. end;
  97. function MemAvail:Longint;
  98. begin
  99. MemAvail:=MemoryManager.MemAvail();
  100. end;
  101. { FPC Additions }
  102. function HeapSize:Longint;
  103. begin
  104. HeapSize:=MemoryManager.HeapSize();
  105. end;
  106. function MemSize(p:pointer):Longint;
  107. begin
  108. MemSize:=MemoryManager.MemSize(p);
  109. end;
  110. { Delphi style }
  111. function FreeMem(var p:pointer):Longint;
  112. begin
  113. Freemem:=MemoryManager.FreeMem(p);
  114. end;
  115. function GetMem(size:longint):pointer;
  116. begin
  117. GetMem:=MemoryManager.GetMem(Size);
  118. end;
  119. function AllocMem(Size:Longint):pointer;
  120. begin
  121. AllocMem:=MemoryManager.AllocMem(size);
  122. end;
  123. function ReAllocMem(var p:pointer;Size:Longint):pointer;
  124. begin
  125. ReAllocMem:=MemoryManager.ReAllocMem(p,size);
  126. end;
  127. { Needed for calls from Assembler }
  128. procedure AsmGetMem(var p:pointer;size:longint);{$ifdef NEWMM}[public,alias:'FPC_GETMEM'];{$endif}
  129. begin
  130. p:=MemoryManager.GetMem(size);
  131. end;
  132. procedure AsmFreeMem(var p:pointer);{$ifdef NEWMM}[public,alias:'FPC_FREEMEM'];{$endif}
  133. begin
  134. if p <> nil then
  135. begin
  136. MemoryManager.FreeMem(p);
  137. p:=nil;
  138. end;
  139. end;
  140. {*****************************************************************************
  141. Heapsize,Memavail,MaxAvail
  142. *****************************************************************************}
  143. function SysHeapsize : longint;
  144. begin
  145. Sysheapsize:=internal_heapsize;
  146. end;
  147. function SysMemavail : longint;
  148. begin
  149. Sysmemavail:=internal_memavail;
  150. end;
  151. function SysMaxavail : longint;
  152. var
  153. hp : pfreerecord;
  154. begin
  155. Sysmaxavail:=heapend-heapptr;
  156. hp:=freelists[0];
  157. while assigned(hp) do
  158. begin
  159. if hp^.size>Sysmaxavail then
  160. Sysmaxavail:=hp^.size;
  161. hp:=hp^.next;
  162. end;
  163. end;
  164. {$ifdef DUMPBLOCKS}
  165. procedure DumpBlocks;
  166. var
  167. s,i,j : longint;
  168. hp : pfreerecord;
  169. begin
  170. for i:=1 to maxblock do
  171. begin
  172. hp:=freelists[i];
  173. j:=0;
  174. while assigned(hp) do
  175. begin
  176. inc(j);
  177. hp:=hp^.next;
  178. end;
  179. writeln('Block ',i*blocksize,': ',j);
  180. end;
  181. { freelist 0 }
  182. hp:=freelists[0];
  183. j:=0;
  184. s:=0;
  185. while assigned(hp) do
  186. begin
  187. inc(j);
  188. if hp^.size>s then
  189. s:=hp^.size;
  190. hp:=hp^.next;
  191. end;
  192. writeln('Main: ',j,' maxsize: ',s);
  193. end;
  194. {$endif}
  195. {*****************************************************************************
  196. SysGetMem
  197. *****************************************************************************}
  198. function SysGetMem(size : longint):pointer;
  199. type
  200. heaperrorproc=function(size:longint):integer;
  201. var
  202. proc : heaperrorproc;
  203. pcurr : pfreerecord;
  204. again : boolean;
  205. s,s1,i,
  206. sizeleft : longint;
  207. {$ifdef BESTMATCH}
  208. pbest : pfreerecord;
  209. {$endif}
  210. begin
  211. { Something to allocate ? }
  212. if size<=0 then
  213. begin
  214. { give an error for < 0 }
  215. if size<0 then
  216. HandleError(204);
  217. { we always need to allocate something, using heapend is not possible,
  218. because heappend can be changed by growheap (PFV) }
  219. size:=1;
  220. end;
  221. { calc to multiply of 16 after adding the needed 8 bytes heaprecord }
  222. size:=(size+sizeof(theaprecord)+(blocksize-1)) and (not (blocksize-1));
  223. dec(internal_memavail,size);
  224. { try to find a block in one of the freelists per size }
  225. s:=size shr blockshr;
  226. if s<=maxblock then
  227. begin
  228. pcurr:=freelists[s];
  229. { correct size match ? }
  230. if assigned(pcurr) then
  231. begin
  232. { create the block we should return }
  233. sysgetmem:=pointer(pcurr)+sizeof(theaprecord);
  234. { fix size }
  235. pcurr^.size:=pcurr^.size or usedmask;
  236. { update freelist }
  237. freelists[s]:=pcurr^.next;
  238. if assigned(freelists[s]) then
  239. freelists[s]^.prev:=nil;
  240. exit;
  241. end;
  242. {$ifdef SMALLATHEAPPTR}
  243. if heapend-heapptr>size then
  244. begin
  245. sysgetmem:=heapptr;
  246. if (heapptr+size=heapend) then
  247. pheaprecord(sysgetmem)^.size:=size or (usedmask or beforeheapendmask)
  248. else
  249. pheaprecord(sysgetmem)^.size:=size or usedmask;
  250. inc(sysgetmem,sizeof(theaprecord));
  251. inc(heapptr,size);
  252. exit;
  253. end;
  254. {$endif}
  255. {$ifdef REUSEBIGGER}
  256. { try a bigger block }
  257. s1:=s+s;
  258. i:=0;
  259. while (s1<=maxblock) and (i<maxreusebigger) do
  260. begin
  261. pcurr:=freelists[s1];
  262. if assigned(pcurr) then
  263. begin
  264. s:=s1;
  265. break;
  266. end;
  267. inc(s1);
  268. inc(i);
  269. end;
  270. {$endif}
  271. end
  272. else
  273. pcurr:=nil;
  274. { not found, then check the main freelist for the first match }
  275. if not(assigned(pcurr)) then
  276. begin
  277. s:=0;
  278. {$ifdef BESTMATCH}
  279. pbest:=nil;
  280. {$endif}
  281. pcurr:=freelists[0];
  282. while assigned(pcurr) do
  283. begin
  284. {$ifdef BESTMATCH}
  285. if pcurr^.size=size then
  286. break
  287. else
  288. begin
  289. if (pcurr^.size>size) then
  290. begin
  291. if (not assigned(pbest)) or
  292. (pcurr^.size<pbest^.size) then
  293. pbest:=pcurr;
  294. end;
  295. end;
  296. {$else}
  297. if pcurr^.size>=size then
  298. break;
  299. {$endif}
  300. pcurr:=pcurr^.next;
  301. end;
  302. {$ifdef BESTMATCH}
  303. if not assigned(pcurr) then
  304. pcurr:=pbest;
  305. {$endif}
  306. end;
  307. { have we found a block, then get it and free up the other left part,
  308. if no blocks are found then allocated at the heapptr or grow the heap }
  309. if assigned(pcurr) then
  310. begin
  311. { get pointer of the block we should return }
  312. sysgetmem:=pointer(pcurr);
  313. { remove the current block from the freelist }
  314. if assigned(pcurr^.next) then
  315. pcurr^.next^.prev:=pcurr^.prev;
  316. if assigned(pcurr^.prev) then
  317. pcurr^.prev^.next:=pcurr^.next
  318. else
  319. freelists[s]:=pcurr^.next;
  320. { create the left over freelist block, if at least 16 bytes are free }
  321. sizeleft:=pcurr^.size-size;
  322. if sizeleft>sizeof(tfreerecord) then
  323. begin
  324. pcurr:=pfreerecord(pointer(pcurr)+size);
  325. { inherit the beforeheapendmask }
  326. pcurr^.size:=sizeleft or (pheaprecord(sysgetmem)^.size and beforeheapendmask);
  327. { insert the block in the freelist }
  328. pcurr^.prev:=nil;
  329. s1:=sizeleft shr blockshr;
  330. if s1>maxblock then
  331. s1:=0;
  332. pcurr^.next:=freelists[s1];
  333. if assigned(freelists[s1]) then
  334. freelists[s1]^.prev:=pcurr;
  335. freelists[s1]:=pcurr;
  336. { create the block we need to return }
  337. pheaprecord(sysgetmem)^.size:=size or usedmask;
  338. end
  339. else
  340. begin
  341. { create the block we need to return }
  342. pheaprecord(sysgetmem)^.size:=size or usedmask or (pheaprecord(sysgetmem)^.size and beforeheapendmask);
  343. end;
  344. inc(sysgetmem,sizeof(theaprecord));
  345. exit;
  346. end;
  347. { Lastly, the top of the heap is checked, to see if there is }
  348. { still memory available. }
  349. repeat
  350. again:=false;
  351. if heapend-heapptr>size then
  352. begin
  353. sysgetmem:=heapptr;
  354. if (heapptr+size=heapend) then
  355. pheaprecord(sysgetmem)^.size:=size or (usedmask or beforeheapendmask)
  356. else
  357. pheaprecord(sysgetmem)^.size:=size or usedmask;
  358. inc(sysgetmem,sizeof(theaprecord));
  359. inc(heapptr,size);
  360. exit;
  361. end;
  362. { Call the heaperror proc }
  363. if assigned(heaperror) then
  364. begin
  365. proc:=heaperrorproc(heaperror);
  366. case proc(size) of
  367. 0 : HandleError(203);
  368. 1 : sysgetmem:=nil;
  369. 2 : again:=true;
  370. end;
  371. end
  372. else
  373. HandleError(203);
  374. until not again;
  375. end;
  376. {*****************************************************************************
  377. SysFreeMem
  378. *****************************************************************************}
  379. Function SysFreeMem(var p : pointer):Longint;
  380. var
  381. pcurrsize,s : longint;
  382. pcurr : pfreerecord;
  383. begin
  384. if p=nil then
  385. HandleError(204);
  386. { fix p to point to the heaprecord }
  387. pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
  388. pcurrsize:=pcurr^.size and sizemask;
  389. inc(internal_memavail,pcurrsize);
  390. { insert the block in it's freelist }
  391. pcurr^.size:=pcurr^.size and (not usedmask);
  392. pcurr^.prev:=nil;
  393. s:=pcurrsize shr blockshr;
  394. if s>maxblock then
  395. s:=0;
  396. pcurr^.next:=freelists[s];
  397. if assigned(pcurr^.next) then
  398. pcurr^.next^.prev:=pcurr;
  399. freelists[s]:=pcurr;
  400. p:=nil;
  401. SysFreeMem:=pcurrsize;
  402. end;
  403. {*****************************************************************************
  404. SysFreeMemSize
  405. *****************************************************************************}
  406. Function SysFreeMemSize(var p : pointer;size : longint):longint;
  407. var
  408. pcurrsize,s : longint;
  409. pcurr : pfreerecord;
  410. begin
  411. SysFreeMemSize:=0;
  412. if size<=0 then
  413. begin
  414. if size<0 then
  415. HandleError(204);
  416. p:=nil;
  417. exit;
  418. end;
  419. if p=nil then
  420. HandleError(204);
  421. { fix p to point to the heaprecord }
  422. pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
  423. pcurrsize:=pcurr^.size and sizemask;
  424. inc(internal_memavail,pcurrsize);
  425. { size check }
  426. size:=(size+sizeof(theaprecord)+(blocksize-1)) and (not (blocksize-1));
  427. if size<>pcurrsize then
  428. HandleError(204);
  429. { insert the block in it's freelist }
  430. pcurr^.size:=pcurr^.size and (not usedmask);
  431. pcurr^.prev:=nil;
  432. s:=pcurrsize shr blockshr;
  433. if s>maxblock then
  434. s:=0;
  435. pcurr^.next:=freelists[s];
  436. if assigned(pcurr^.next) then
  437. pcurr^.next^.prev:=pcurr;
  438. freelists[s]:=pcurr;
  439. p:=nil;
  440. SysFreeMemSize:=pcurrsize;
  441. end;
  442. {*****************************************************************************
  443. SysMemSize
  444. *****************************************************************************}
  445. function SysMemSize(p:pointer):longint;
  446. begin
  447. SysMemSize:=(pheaprecord(pointer(p)-sizeof(theaprecord))^.size and sizemask)-sizeof(theaprecord);
  448. end;
  449. {*****************************************************************************
  450. SysAllocMem
  451. *****************************************************************************}
  452. function SysAllocMem(size : longint):pointer;
  453. begin
  454. sysallocmem:=MemoryManager.GetMem(size);
  455. if sysallocmem<>nil then
  456. FillChar(sysallocmem^,size,0);
  457. end;
  458. {*****************************************************************************
  459. SysReAllocMem
  460. *****************************************************************************}
  461. function internSysReAllocMem(var p:pointer;size : longint; var doMove: boolean):pointer;
  462. { On entry, doMove determines if a new block has to be allocated, whether this is }
  463. { done and the data is moved from the old to the new block }
  464. { If doMove was false on entry, it is set to true on exit if a move has to be done }
  465. { which then has to be carried out by the caller, otherwise it remains false }
  466. { This functionality is required if you install you own heap manager (e.g. heaptrc) }
  467. var
  468. orgsize,
  469. currsize,
  470. foundsize,
  471. sizeleft,
  472. s : longint;
  473. wasbeforeheapend, canDoMove : boolean;
  474. p2 : pointer;
  475. hp,
  476. pnew,
  477. pcurr : pfreerecord;
  478. begin
  479. canDoMove := doMove;
  480. { assume no move is necessary }
  481. doMove := false;
  482. { Allocate a new block? }
  483. if p=nil then
  484. begin
  485. p:=MemoryManager.GetMem(size);
  486. internSysReallocmem:=P;
  487. exit;
  488. end;
  489. { fix needed size }
  490. orgsize:=size;
  491. size:=(size+sizeof(theaprecord)+(blocksize-1)) and (not (blocksize-1));
  492. { fix p to point to the heaprecord }
  493. pcurr:=pfreerecord(pointer(p)-sizeof(theaprecord));
  494. currsize:=pcurr^.size and sizemask;
  495. wasbeforeheapend:=(pcurr^.size and beforeheapendmask)<>0;
  496. { is the allocated block still correct? }
  497. if currsize=size then
  498. begin
  499. internSysReAllocMem:=p;
  500. exit;
  501. end;
  502. { do we need to allocate more memory ? }
  503. if size>currsize then
  504. begin
  505. { the size is bigger than the previous size, we need to allocated more mem.
  506. We first check if the blocks after the current block are free. If not we
  507. simply call getmem/freemem to get the new block }
  508. foundsize:=0;
  509. hp:=pcurr;
  510. repeat
  511. inc(foundsize,hp^.size and sizemask);
  512. { block used or before a heapptr ? }
  513. if (hp^.size and beforeheapendmask)<>0 then
  514. begin
  515. wasbeforeheapend:=true;
  516. break;
  517. end;
  518. { get next block }
  519. hp:=pfreerecord(pointer(hp)+(hp^.size and sizemask));
  520. { when we're at heapptr then we can stop }
  521. if (hp=heapptr) then
  522. begin
  523. inc(foundsize,heapend-heapptr);
  524. break;
  525. end;
  526. if (hp^.size and usedmask)<>0 then
  527. break;
  528. until (foundsize>=size);
  529. { found enough free blocks? }
  530. if foundsize>=size then
  531. begin
  532. { we walk the list again and remove all blocks }
  533. foundsize:=pcurr^.size and sizemask;
  534. hp:=pcurr;
  535. repeat
  536. { get next block }
  537. hp:=pfreerecord(pointer(hp)+(hp^.size and sizemask));
  538. { when we're at heapptr then we can increase it, if there is enough
  539. room is already checked }
  540. if (hp=heapptr) then
  541. begin
  542. inc(heapptr,size-foundsize);
  543. foundsize:=size;
  544. break;
  545. end;
  546. s:=hp^.size and sizemask;
  547. inc(foundsize,s);
  548. { remove block from freelist }
  549. s:=s shr blockshr;
  550. if s>maxblock then
  551. s:=0;
  552. if assigned(hp^.next) then
  553. hp^.next^.prev:=hp^.prev;
  554. if assigned(hp^.prev) then
  555. hp^.prev^.next:=hp^.next
  556. else
  557. freelists[s]:=hp^.next;
  558. until (foundsize>=size);
  559. if wasbeforeheapend then
  560. pcurr^.size:=foundsize or usedmask or beforeheapendmask
  561. else
  562. pcurr^.size:=foundsize or usedmask;
  563. end
  564. else
  565. begin
  566. { we need to call getmem/move/freemem }
  567. If canDoMove then
  568. begin
  569. p2:= MemoryManager.GetMem(orgsize);
  570. if p2<>nil then
  571. Move(p^,p2^,orgsize);
  572. MemoryManager.FreeMem(p);
  573. p:=p2;
  574. end
  575. else
  576. doMove := true;
  577. internSysReAllocMem:=p;
  578. exit;
  579. end;
  580. currsize:=pcurr^.size and sizemask;
  581. end;
  582. { is the size smaller then we can adjust the block to that size and insert
  583. the other part into the freelist }
  584. if size<currsize then
  585. begin
  586. { create the left over freelist block, if at least 16 bytes are free }
  587. sizeleft:=currsize-size;
  588. if sizeleft>sizeof(tfreerecord) then
  589. begin
  590. pnew:=pfreerecord(pointer(pcurr)+size);
  591. pnew^.size:=sizeleft or (pcurr^.size and beforeheapendmask);
  592. { insert the block in the freelist }
  593. pnew^.prev:=nil;
  594. s:=sizeleft shr blockshr;
  595. if s>maxblock then
  596. s:=0;
  597. pnew^.next:=freelists[s];
  598. if assigned(freelists[s]) then
  599. freelists[s]^.prev:=pnew;
  600. freelists[s]:=pnew;
  601. { fix the size of the current block and leave }
  602. pcurr^.size:=size or usedmask;
  603. end
  604. else
  605. begin
  606. { fix the size of the current block and leave }
  607. pcurr^.size:=size or usedmask or (pcurr^.size and beforeheapendmask);
  608. end;
  609. end;
  610. internSysReAllocMem:=p;
  611. end;
  612. function SysReAllocMem(var p:pointer;size : longint):pointer;
  613. var
  614. doMove: boolean;
  615. begin
  616. doMove:=true;
  617. SysReAllocMem := internSysReallocMem(p,size,doMove);
  618. end;
  619. {*****************************************************************************
  620. Mark/Release
  621. *****************************************************************************}
  622. procedure release(var p : pointer);
  623. begin
  624. end;
  625. procedure mark(var p : pointer);
  626. begin
  627. end;
  628. {*****************************************************************************
  629. Grow Heap
  630. *****************************************************************************}
  631. function growheap(size :longint) : integer;
  632. var
  633. sizeleft,
  634. NewPos : longint;
  635. pcurr : pfreerecord;
  636. begin
  637. {$ifdef DUMPGROW}
  638. writeln('grow ',size);
  639. DumpBlocks;
  640. {$endif}
  641. { Allocate by 64K size }
  642. size:=(size+$ffff) and $ffff0000;
  643. { first try 256K (default) }
  644. if size<=GrowHeapSize1 then
  645. begin
  646. NewPos:=Sbrk(GrowHeapSize1);
  647. if NewPos>0 then
  648. size:=GrowHeapSize1;
  649. end
  650. else
  651. { second try 1024K (default) }
  652. if size<=GrowHeapSize2 then
  653. begin
  654. NewPos:=Sbrk(GrowHeapSize2);
  655. if NewPos>0 then
  656. size:=GrowHeapSize2;
  657. end
  658. { else alloate the needed bytes }
  659. else
  660. NewPos:=SBrk(size);
  661. { try again }
  662. if NewPos=-1 then
  663. begin
  664. NewPos:=Sbrk(size);
  665. if NewPos=-1 then
  666. begin
  667. GrowHeap:=0;
  668. Exit;
  669. end;
  670. end;
  671. { increase heapend or add to freelist }
  672. if heapend=pointer(newpos) then
  673. begin
  674. heapend:=pointer(newpos+size);
  675. end
  676. else
  677. begin
  678. { create freelist entry for old heapptr-heapend }
  679. sizeleft:=heapend-heapptr;
  680. if sizeleft>sizeof(tfreerecord) then
  681. begin
  682. pcurr:=pfreerecord(heapptr);
  683. pcurr^.size:=sizeleft or beforeheapendmask;
  684. { insert the block in the freelist }
  685. pcurr^.next:=freelists[0];
  686. pcurr^.prev:=nil;
  687. if assigned(freelists[0]) then
  688. freelists[0]^.prev:=pcurr;
  689. freelists[0]:=pcurr;
  690. end;
  691. { now set the new heapptr,heapend to the new block }
  692. heapptr:=pointer(newpos);
  693. heapend:=pointer(newpos+size);
  694. end;
  695. { set the total new heap size }
  696. inc(internal_memavail,size);
  697. inc(internal_heapsize,size);
  698. { try again }
  699. GrowHeap:=2;
  700. end;
  701. {*****************************************************************************
  702. InitHeap
  703. *****************************************************************************}
  704. { This function will initialize the Heap manager and need to be called from
  705. the initialization of the system unit }
  706. procedure InitHeap;
  707. begin
  708. FillChar(FreeLists,sizeof(TFreeLists),0);
  709. internal_heapsize:=GetHeapSize;
  710. internal_memavail:=internal_heapsize;
  711. HeapOrg:=GetHeapStart;
  712. HeapPtr:=HeapOrg;
  713. HeapEnd:=HeapOrg+internal_memavail;
  714. HeapError:=@GrowHeap;
  715. end;
  716. {
  717. $Log$
  718. Revision 1.31 2000-01-24 23:56:10 peter
  719. * fixed reallocmem which didn't work anymore and thus broke a lot
  720. of objfpc/delphi code
  721. Revision 1.30 2000/01/20 12:35:35 jonas
  722. * fixed problem with reallocmem and heaptrc
  723. Revision 1.29 2000/01/07 16:41:34 daniel
  724. * copyright 2000
  725. Revision 1.28 2000/01/07 16:32:24 daniel
  726. * copyright 2000 added
  727. Revision 1.27 1999/12/16 19:11:49 peter
  728. * fixed sysmemsize which did the and sizemask wrong
  729. Revision 1.26 1999/12/13 21:04:46 peter
  730. * fixed getmem call with wrong size from reallocmem
  731. Revision 1.25 1999/12/01 22:57:31 peter
  732. * cmdline support
  733. Revision 1.24 1999/11/14 21:34:21 peter
  734. * fixed reallocmem with a block at the end of an allocated memoryblock,
  735. had to introduce a flag for such blocks.
  736. * flags are now stored in the first 4 bits instead of the highest bit,
  737. this could be done because the sizes of block are always >= 16
  738. Revision 1.23 1999/11/10 22:29:51 michael
  739. + Fixed sysreallocmem
  740. Revision 1.22 1999/11/01 13:56:50 peter
  741. * freemem,reallocmem now get var argument
  742. Revision 1.21 1999/10/30 17:39:05 peter
  743. * memorymanager expanded with allocmem/reallocmem
  744. Revision 1.20 1999/10/22 22:03:07 sg
  745. * FreeMem(p) is ignored if p is NIL, instead of throwing an
  746. runtime error 204. (Delphi ignores NIL FreeMem's, too)
  747. Revision 1.19 1999/10/01 07:55:54 peter
  748. * fixed memsize which forgot the sizemask
  749. Revision 1.18 1999/09/22 21:59:02 peter
  750. * best match for main freelist
  751. * removed root field, saves 4 bytes per block
  752. * fixed crash in dumpblocks
  753. Revision 1.17 1999/09/20 14:17:37 peter
  754. * fixed growheap freelist addition when heapend-heapptr<blocksize
  755. Revision 1.16 1999/09/17 17:14:12 peter
  756. + new heap manager supporting delphi freemem(pointer)
  757. }