heap.inc 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2000 by the Free Pascal development team.
  4. functions for heap management in the data segment
  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. {****************************************************************************}
  12. { Try to find the best matching block in general freelist }
  13. { define BESTMATCH}
  14. { DEBUG: Dump info when the heap needs to grow }
  15. { define DUMPGROW}
  16. { DEBUG: Test the FreeList on correctness }
  17. {$ifdef SYSTEMDEBUG}
  18. {$define TestFreeLists}
  19. {$endif SYSTEMDEBUG}
  20. const
  21. {$ifdef CPU64}
  22. blocksize = 32; { at least size of freerecord }
  23. blockshr = 5; { shr value for blocksize=2^blockshr}
  24. maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
  25. {$else}
  26. blocksize = 16; { at least size of freerecord }
  27. blockshr = 4; { shr value for blocksize=2^blockshr}
  28. maxblocksize = 512+blocksize; { 1024+8 needed for heaprecord }
  29. {$endif}
  30. maxblockindex = maxblocksize div blocksize; { highest index in array of lists of memchunks }
  31. maxreusebigger = 8; { max reuse bigger tries }
  32. usedflag = 1; { flag if the block is used or not }
  33. lastblockflag = 2; { flag if the block is the last in os chunk }
  34. firstblockflag = 4; { flag if the block is the first in os chunk }
  35. fixedsizeflag = 8; { flag if the block is of fixed size }
  36. sizemask = not(blocksize-1);
  37. fixedsizemask = sizemask and $ffff;
  38. {****************************************************************************}
  39. {$ifdef DUMPGROW}
  40. {$define DUMPBLOCKS}
  41. {$endif}
  42. { Forward defines }
  43. procedure SysHeapMutexInit;forward;
  44. procedure SysHeapMutexDone;forward;
  45. procedure SysHeapMutexLock;forward;
  46. procedure SysHeapMutexUnlock;forward;
  47. { Memory manager }
  48. const
  49. MemoryManager: TMemoryManager = (
  50. NeedLock: true;
  51. GetMem: @SysGetMem;
  52. FreeMem: @SysFreeMem;
  53. FreeMemSize: @SysFreeMemSize;
  54. AllocMem: @SysAllocMem;
  55. ReAllocMem: @SysReAllocMem;
  56. MemSize: @SysMemSize;
  57. GetHeapStatus: @SysGetHeapStatus;
  58. {$ifdef HASGETFPCHEAPSTATUS}
  59. GetFPCHeapStatus: @SysGetFPCHeapStatus;
  60. {$endif HASGETFPCHEAPSTATUS}
  61. );
  62. MemoryMutexManager: TMemoryMutexManager = (
  63. MutexInit: @SysHeapMutexInit;
  64. MutexDone: @SysHeapMutexDone;
  65. MutexLock: @SysHeapMutexLock;
  66. MutexUnlock: @SysHeapMutexUnlock;
  67. );
  68. type
  69. pmemchunk_fixed = ^tmemchunk_fixed;
  70. tmemchunk_fixed = record
  71. {$ifdef cpusparc}
  72. { Sparc needs to alloc aligned on 8 bytes, to allow doubles }
  73. _dummy : ptrint;
  74. {$endif cpusparc}
  75. size : ptrint;
  76. next_fixed,
  77. prev_fixed : pmemchunk_fixed;
  78. end;
  79. pmemchunk_var = ^tmemchunk_var;
  80. tmemchunk_var = record
  81. prevsize : ptrint;
  82. size : ptrint;
  83. next_var,
  84. prev_var : pmemchunk_var;
  85. end;
  86. { ``header'', ie. size of structure valid when chunk is in use }
  87. { should correspond to tmemchunk_var_hdr structure starting with the
  88. last field. Reason is that the overlap is starting from the end of the
  89. record. }
  90. tmemchunk_fixed_hdr = record
  91. {$ifdef cpusparc}
  92. { Sparc needs to alloc aligned on 8 bytes, to allow doubles }
  93. _dummy : ptrint;
  94. {$endif cpusparc}
  95. size : ptrint;
  96. end;
  97. tmemchunk_var_hdr = record
  98. prevsize : ptrint;
  99. size : ptrint;
  100. end;
  101. poschunk = ^toschunk;
  102. toschunk = record
  103. size : ptrint;
  104. next,
  105. prev : poschunk;
  106. used : ptrint;
  107. end;
  108. tfreelists = array[1..maxblockindex] of pmemchunk_fixed;
  109. pfreelists = ^tfreelists;
  110. var
  111. {$ifdef HASGETFPCHEAPSTATUS}
  112. internal_status : TFPCHeapStatus;
  113. {$else HASGETFPCHEAPSTATUS}
  114. internal_status : THeapStatus;
  115. {$endif HASGETFPCHEAPSTATUS}
  116. freelists_fixed : tfreelists;
  117. freelist_var : pmemchunk_var;
  118. freeoslist : poschunk;
  119. freeoslistcount : dword;
  120. {$ifdef TestFreeLists}
  121. { this can be turned on by debugger }
  122. const
  123. test_each : boolean = false;
  124. {$endif TestFreeLists}
  125. {*****************************************************************************
  126. Memory Manager
  127. *****************************************************************************}
  128. procedure SetMemoryMutexManager(var MutexMgr: TMemoryMutexManager);
  129. begin
  130. { Release old mutexmanager, the default manager does nothing so
  131. calling this without initializing is safe }
  132. MemoryMutexManager.MutexDone;
  133. { Copy new mutexmanager }
  134. MemoryMutexManager := MutexMgr;
  135. { Init new mutexmanager }
  136. MemoryMutexManager.MutexInit;
  137. end;
  138. procedure GetMemoryManager(var MemMgr:TMemoryManager);
  139. begin
  140. if IsMultiThread and MemoryManager.NeedLock then
  141. begin
  142. try
  143. MemoryMutexManager.MutexLock;
  144. MemMgr := MemoryManager;
  145. finally
  146. MemoryMutexManager.MutexUnlock;
  147. end;
  148. end
  149. else
  150. begin
  151. MemMgr := MemoryManager;
  152. end;
  153. end;
  154. procedure SetMemoryManager(const MemMgr:TMemoryManager);
  155. begin
  156. if IsMultiThread and MemoryManager.NeedLock then
  157. begin
  158. try
  159. MemoryMutexManager.MutexLock;
  160. MemoryManager := MemMgr;
  161. finally
  162. MemoryMutexManager.MutexUnlock;
  163. end;
  164. end
  165. else
  166. begin
  167. MemoryManager := MemMgr;
  168. end;
  169. end;
  170. function IsMemoryManagerSet:Boolean;
  171. begin
  172. if IsMultiThread and MemoryManager.NeedLock then
  173. begin
  174. try
  175. MemoryMutexManager.MutexLock;
  176. IsMemoryManagerSet := (MemoryManager.GetMem<>@SysGetMem) or
  177. (MemoryManager.FreeMem<>@SysFreeMem);
  178. finally
  179. MemoryMutexManager.MutexUnlock;
  180. end;
  181. end
  182. else
  183. begin
  184. IsMemoryManagerSet := (MemoryManager.GetMem<>@SysGetMem) or
  185. (MemoryManager.FreeMem<>@SysFreeMem);
  186. end;
  187. end;
  188. procedure GetMem(Var p:pointer;Size:ptrint);
  189. begin
  190. if IsMultiThread and MemoryManager.NeedLock then
  191. begin
  192. try
  193. MemoryMutexManager.MutexLock;
  194. p := MemoryManager.GetMem(Size);
  195. finally
  196. MemoryMutexManager.MutexUnlock;
  197. end;
  198. end
  199. else
  200. begin
  201. p := MemoryManager.GetMem(Size);
  202. end;
  203. end;
  204. procedure GetMemory(Var p:pointer;Size:ptrint);
  205. begin
  206. GetMem(p,size);
  207. end;
  208. procedure FreeMem(p:pointer;Size:ptrint);
  209. begin
  210. if IsMultiThread and MemoryManager.NeedLock then
  211. begin
  212. try
  213. MemoryMutexManager.MutexLock;
  214. MemoryManager.FreeMemSize(p,Size);
  215. finally
  216. MemoryMutexManager.MutexUnlock;
  217. end;
  218. end
  219. else
  220. begin
  221. MemoryManager.FreeMemSize(p,Size);
  222. end;
  223. end;
  224. procedure FreeMemory(p:pointer;Size:ptrint);
  225. begin
  226. FreeMem(p,size);
  227. end;
  228. {$ifdef HASGETFPCHEAPSTATUS}
  229. function GetHeapStatus:THeapStatus;
  230. begin
  231. if IsMultiThread and MemoryManager.NeedLock then
  232. begin
  233. try
  234. MemoryMutexManager.MutexLock;
  235. result:=MemoryManager.GetHeapStatus();
  236. finally
  237. MemoryMutexManager.MutexUnlock;
  238. end;
  239. end
  240. else
  241. begin
  242. result:=MemoryManager.GetHeapStatus();
  243. end;
  244. end;
  245. function GetFPCHeapStatus:TFPCHeapStatus;
  246. begin
  247. if IsMultiThread and MemoryManager.NeedLock then
  248. begin
  249. try
  250. MemoryMutexManager.MutexLock;
  251. result:=MemoryManager.GetFPCHeapStatus();
  252. finally
  253. MemoryMutexManager.MutexUnlock;
  254. end;
  255. end
  256. else
  257. begin
  258. Result:=MemoryManager.GetFPCHeapStatus();
  259. end;
  260. end;
  261. {$else HASGETFPCHEAPSTATUS}
  262. procedure GetHeapStatus(var status:THeapStatus);
  263. begin
  264. if IsMultiThread and MemoryManager.NeedLock then
  265. begin
  266. try
  267. MemoryMutexManager.MutexLock;
  268. MemoryManager.GetHeapStatus(status);
  269. finally
  270. MemoryMutexManager.MutexUnlock;
  271. end;
  272. end
  273. else
  274. begin
  275. MemoryManager.GetHeapStatus(status);
  276. end;
  277. end;
  278. {$endif HASGETFPCHEAPSTATUS}
  279. function MemSize(p:pointer):ptrint;
  280. begin
  281. if IsMultiThread and MemoryManager.NeedLock then
  282. begin
  283. try
  284. MemoryMutexManager.MutexLock;
  285. MemSize := MemoryManager.MemSize(p);
  286. finally
  287. MemoryMutexManager.MutexUnlock;
  288. end;
  289. end
  290. else
  291. begin
  292. MemSize := MemoryManager.MemSize(p);
  293. end;
  294. end;
  295. { Delphi style }
  296. function FreeMem(p:pointer):ptrint;
  297. begin
  298. if IsMultiThread and MemoryManager.NeedLock then
  299. begin
  300. try
  301. MemoryMutexManager.MutexLock;
  302. Freemem := MemoryManager.FreeMem(p);
  303. finally
  304. MemoryMutexManager.MutexUnlock;
  305. end;
  306. end
  307. else
  308. begin
  309. Freemem := MemoryManager.FreeMem(p);
  310. end;
  311. end;
  312. function FreeMemory(p:pointer):ptrint;
  313. begin
  314. FreeMemory := FreeMem(p);
  315. end;
  316. function GetMem(size:ptrint):pointer;
  317. begin
  318. if IsMultiThread and MemoryManager.NeedLock then
  319. begin
  320. try
  321. MemoryMutexManager.MutexLock;
  322. GetMem := MemoryManager.GetMem(Size);
  323. finally
  324. MemoryMutexManager.MutexUnlock;
  325. end;
  326. end
  327. else
  328. begin
  329. GetMem := MemoryManager.GetMem(Size);
  330. end;
  331. end;
  332. function GetMemory(size:ptrint):pointer;
  333. begin
  334. GetMemory := Getmem(size);
  335. end;
  336. function AllocMem(Size:ptrint):pointer;
  337. begin
  338. if IsMultiThread and MemoryManager.NeedLock then
  339. begin
  340. try
  341. MemoryMutexManager.MutexLock;
  342. AllocMem := MemoryManager.AllocMem(size);
  343. finally
  344. MemoryMutexManager.MutexUnlock;
  345. end;
  346. end
  347. else
  348. begin
  349. AllocMem := MemoryManager.AllocMem(size);
  350. end;
  351. end;
  352. function ReAllocMem(var p:pointer;Size:ptrint):pointer;
  353. begin
  354. if IsMultiThread and MemoryManager.NeedLock then
  355. begin
  356. try
  357. MemoryMutexManager.MutexLock;
  358. ReAllocMem := MemoryManager.ReAllocMem(p,size);
  359. finally
  360. MemoryMutexManager.MutexUnlock;
  361. end;
  362. end
  363. else
  364. begin
  365. ReAllocMem := MemoryManager.ReAllocMem(p,size);
  366. end;
  367. end;
  368. function ReAllocMemory(var p:pointer;Size:ptrint):pointer;
  369. begin
  370. ReAllocMemory := ReAllocMem(p,size);
  371. end;
  372. {$ifdef ValueGetmem}
  373. { Needed for calls from Assembler }
  374. function fpc_getmem(size:ptrint):pointer;compilerproc;[public,alias:'FPC_GETMEM'];
  375. begin
  376. if IsMultiThread and MemoryManager.NeedLock then
  377. begin
  378. try
  379. MemoryMutexManager.MutexLock;
  380. fpc_GetMem := MemoryManager.GetMem(size);
  381. finally
  382. MemoryMutexManager.MutexUnlock;
  383. end;
  384. end
  385. else
  386. begin
  387. fpc_GetMem := MemoryManager.GetMem(size);
  388. end;
  389. end;
  390. {$else ValueGetmem}
  391. { Needed for calls from Assembler }
  392. procedure AsmGetMem(var p:pointer;size:ptrint);[public,alias:'FPC_GETMEM'];
  393. begin
  394. p := MemoryManager.GetMem(size);
  395. end;
  396. {$endif ValueGetmem}
  397. {$ifdef ValueFreemem}
  398. procedure fpc_freemem(p:pointer);compilerproc;[public,alias:'FPC_FREEMEM'];
  399. begin
  400. if IsMultiThread and MemoryManager.NeedLock then
  401. begin
  402. try
  403. MemoryMutexManager.MutexLock;
  404. if p <> nil then
  405. MemoryManager.FreeMem(p);
  406. finally
  407. MemoryMutexManager.MutexUnlock;
  408. end;
  409. end
  410. else
  411. begin
  412. if p <> nil then
  413. MemoryManager.FreeMem(p);
  414. end;
  415. end;
  416. {$else ValueFreemem}
  417. procedure AsmFreeMem(var p:pointer);[public,alias:'FPC_FREEMEM'];
  418. begin
  419. if p <> nil then
  420. MemoryManager.FreeMem(p);
  421. end;
  422. {$endif ValueFreemem}
  423. { Bootstrapping }
  424. {$ifndef HASGETHEAPSTATUS}
  425. Function Memavail:ptrint;
  426. begin
  427. result:=0;
  428. end;
  429. Function Maxavail:ptrint;
  430. begin
  431. result:=0;
  432. end;
  433. Function Heapsize:ptrint;
  434. begin
  435. result:=0;
  436. end;
  437. {$endif HASGETHEAPSTATUS}
  438. {*****************************************************************************
  439. GetHeapStatus
  440. *****************************************************************************}
  441. {$ifdef HASGETFPCHEAPSTATUS}
  442. function SysGetFPCHeapStatus:TFPCHeapStatus;
  443. begin
  444. internal_status.CurrHeapFree:=internal_status.CurrHeapSize-internal_status.CurrHeapUsed;
  445. result:=internal_status;
  446. end;
  447. function SysGetHeapStatus :THeapStatus;
  448. begin
  449. internal_status.CurrHeapFree:=internal_status.CurrHeapSize-internal_status.CurrHeapUsed;
  450. result.TotalAllocated :=internal_status.CurrHeapUsed;
  451. result.TotalFree :=internal_status.CurrHeapFree;
  452. result.TotalAddrSpace :=0;
  453. result.TotalUncommitted :=0;
  454. result.TotalCommitted :=0;
  455. result.FreeSmall :=0;
  456. result.FreeBig :=0;
  457. result.Unused :=0;
  458. result.Overhead :=0;
  459. result.HeapErrorCode :=0;
  460. end;
  461. {$else}
  462. procedure SysGetHeapStatus(var status:THeapStatus);
  463. begin
  464. internal_status.CurrHeapFree:=internal_status.CurrHeapSize-internal_status.CurrHeapUsed;
  465. status:=internal_status;
  466. end;
  467. {$endif HASGETFPCHEAPSTATUS}
  468. {$ifdef DUMPBLOCKS} // TODO
  469. procedure DumpBlocks;
  470. var
  471. s,i,j : ptrint;
  472. hp : pfreerecord;
  473. begin
  474. for i := 1 to maxblock do
  475. begin
  476. hp := freelists[i];
  477. j := 0;
  478. while assigned(hp) do
  479. begin
  480. inc(j);
  481. hp := hp^.next;
  482. end;
  483. writeln('Block ',i*blocksize,': ',j);
  484. end;
  485. { freelist 0 }
  486. hp := freelists[0];
  487. j := 0;
  488. s := 0;
  489. while assigned(hp) do
  490. begin
  491. inc(j);
  492. if hp^.size>s then
  493. s := hp^.size;
  494. hp := hp^.next;
  495. end;
  496. writeln('Main: ',j,' maxsize: ',s);
  497. end;
  498. {$endif}
  499. {$ifdef TestFreeLists}
  500. procedure TestFreeLists;
  501. var
  502. i,j : ptrint;
  503. mc : pmemchunk_fixed;
  504. begin
  505. for i := 1 to maxblockindex do
  506. begin
  507. j := 0;
  508. mc := freelists_fixed[i];
  509. while assigned(mc) do
  510. begin
  511. inc(j);
  512. if ((mc^.size and fixedsizemask) <> i * blocksize) then
  513. RunError(204);
  514. mc := mc^.next_fixed;
  515. end;
  516. end;
  517. end;
  518. {$endif TestFreeLists}
  519. {*****************************************************************************
  520. List adding/removal
  521. *****************************************************************************}
  522. procedure append_to_list_fixed(blockindex: ptrint; pmc: pmemchunk_fixed);
  523. begin
  524. pmc^.prev_fixed := nil;
  525. pmc^.next_fixed := freelists_fixed[blockindex];
  526. if freelists_fixed[blockindex]<>nil then
  527. freelists_fixed[blockindex]^.prev_fixed := pmc;
  528. freelists_fixed[blockindex] := pmc;
  529. end;
  530. procedure append_to_list_var(pmc: pmemchunk_var);
  531. begin
  532. pmc^.prev_var := nil;
  533. pmc^.next_var := freelist_var;
  534. if freelist_var<>nil then
  535. freelist_var^.prev_var := pmc;
  536. freelist_var := pmc;
  537. end;
  538. procedure remove_from_list_fixed(blockindex: ptrint; pmc: pmemchunk_fixed);
  539. begin
  540. if assigned(pmc^.next_fixed) then
  541. pmc^.next_fixed^.prev_fixed := pmc^.prev_fixed;
  542. if assigned(pmc^.prev_fixed) then
  543. pmc^.prev_fixed^.next_fixed := pmc^.next_fixed
  544. else
  545. freelists_fixed[blockindex] := pmc^.next_fixed;
  546. end;
  547. procedure remove_from_list_var(pmc: pmemchunk_var);
  548. begin
  549. if assigned(pmc^.next_var) then
  550. pmc^.next_var^.prev_var := pmc^.prev_var;
  551. if assigned(pmc^.prev_var) then
  552. pmc^.prev_var^.next_var := pmc^.next_var
  553. else
  554. freelist_var := pmc^.next_var;
  555. end;
  556. procedure append_to_oslist(poc: poschunk);
  557. begin
  558. { decide whether to free block or add to list }
  559. {$ifdef HAS_SYSOSFREE}
  560. if freeoslistcount >= 3 then
  561. begin
  562. dec(internal_status.currheapsize, poc^.size);
  563. SysOSFree(poc, poc^.size);
  564. end
  565. else
  566. begin
  567. {$endif}
  568. poc^.prev := nil;
  569. poc^.next := freeoslist;
  570. if freeoslist <> nil then
  571. freeoslist^.prev := poc;
  572. freeoslist := poc;
  573. inc(freeoslistcount);
  574. {$ifdef HAS_SYSOSFREE}
  575. end;
  576. {$endif}
  577. end;
  578. procedure remove_from_oslist(poc: poschunk);
  579. begin
  580. if assigned(poc^.next) then
  581. poc^.next^.prev := poc^.prev;
  582. if assigned(poc^.prev) then
  583. poc^.prev^.next := poc^.next
  584. else
  585. freeoslist := poc^.next;
  586. dec(freeoslistcount);
  587. end;
  588. procedure append_to_oslist_var(pmc: pmemchunk_var);
  589. var
  590. poc: poschunk;
  591. begin
  592. // block eligable for freeing
  593. poc := pointer(pmc)-sizeof(toschunk);
  594. remove_from_list_var(pmc);
  595. append_to_oslist(poc);
  596. end;
  597. procedure append_to_oslist_fixed(blockindex, chunksize: ptrint; poc: poschunk);
  598. var
  599. pmc: pmemchunk_fixed;
  600. i, count: ptrint;
  601. begin
  602. count := (poc^.size - sizeof(toschunk)) div chunksize;
  603. pmc := pmemchunk_fixed(pointer(poc)+sizeof(toschunk));
  604. for i := 0 to count - 1 do
  605. begin
  606. remove_from_list_fixed(blockindex, pmc);
  607. pmc := pointer(pmc)+chunksize;
  608. end;
  609. append_to_oslist(poc);
  610. end;
  611. {*****************************************************************************
  612. Split block
  613. *****************************************************************************}
  614. procedure split_block(pcurr: pmemchunk_var; size: ptrint);
  615. var
  616. pcurr_tmp : pmemchunk_var;
  617. sizeleft: ptrint;
  618. begin
  619. sizeleft := (pcurr^.size and sizemask)-size;
  620. if sizeleft>=blocksize then
  621. begin
  622. pcurr_tmp := pmemchunk_var(pointer(pcurr)+size);
  623. { update prevsize of block to the right }
  624. if (pcurr^.size and lastblockflag) = 0 then
  625. pmemchunk_var(pointer(pcurr)+(pcurr^.size and sizemask))^.prevsize := sizeleft;
  626. { inherit the lastblockflag }
  627. pcurr_tmp^.size := sizeleft or (pcurr^.size and lastblockflag);
  628. pcurr_tmp^.prevsize := size;
  629. { the block we return is not the last one anymore (there's now a block after it) }
  630. { decrease size of block to new size }
  631. pcurr^.size := size or (pcurr^.size and (not sizemask and not lastblockflag));
  632. { insert the block in the freelist }
  633. append_to_list_var(pcurr_tmp);
  634. end;
  635. end;
  636. {*****************************************************************************
  637. Try concat freerecords
  638. *****************************************************************************}
  639. procedure concat_two_blocks(mc_left, mc_right: pmemchunk_var);
  640. var
  641. mc_tmp : pmemchunk_var;
  642. size_right : ptrint;
  643. begin
  644. // mc_right can't be a fixed size block
  645. if mc_right^.size and fixedsizeflag<>0 then
  646. HandleError(204);
  647. // left block free, concat with right-block
  648. size_right := mc_right^.size and sizemask;
  649. inc(mc_left^.size, size_right);
  650. // if right-block was last block, copy flag
  651. if (mc_right^.size and lastblockflag) <> 0 then
  652. begin
  653. mc_left^.size := mc_left^.size or lastblockflag;
  654. end
  655. else
  656. begin
  657. // there is a block to the right of the right-block, adjust it's prevsize
  658. mc_tmp := pmemchunk_var(pointer(mc_right)+size_right);
  659. mc_tmp^.prevsize := mc_left^.size and sizemask;
  660. end;
  661. // remove right-block from doubly linked list
  662. remove_from_list_var(mc_right);
  663. end;
  664. procedure try_concat_free_chunk_forward(mc: pmemchunk_var);
  665. var
  666. mc_tmp : pmemchunk_var;
  667. begin
  668. { try concat forward }
  669. if (mc^.size and lastblockflag) = 0 then
  670. begin
  671. mc_tmp := pmemchunk_var(pointer(mc)+(mc^.size and sizemask));
  672. if (mc_tmp^.size and usedflag) = 0 then
  673. begin
  674. // next block free: concat
  675. concat_two_blocks(mc, mc_tmp);
  676. end;
  677. end;
  678. end;
  679. function try_concat_free_chunk(mc: pmemchunk_var): pmemchunk_var;
  680. var
  681. mc_tmp : pmemchunk_var;
  682. begin
  683. try_concat_free_chunk_forward(mc);
  684. { try concat backward }
  685. if (mc^.size and firstblockflag) = 0 then
  686. begin
  687. mc_tmp := pmemchunk_var(pointer(mc)-mc^.prevsize);
  688. if (mc_tmp^.size and usedflag) = 0 then
  689. begin
  690. // prior block free: concat
  691. concat_two_blocks(mc_tmp, mc);
  692. mc := mc_tmp;
  693. end;
  694. end;
  695. result := mc;
  696. end;
  697. function check_concat_free_chunk_forward(mc: pmemchunk_var;reqsize:ptrint):boolean;
  698. var
  699. mc_tmp : pmemchunk_var;
  700. freesize : ptrint;
  701. begin
  702. check_concat_free_chunk_forward:=false;
  703. freesize:=0;
  704. mc_tmp:=mc;
  705. repeat
  706. inc(freesize,mc_tmp^.size and sizemask);
  707. if freesize>=reqsize then
  708. begin
  709. check_concat_free_chunk_forward:=true;
  710. exit;
  711. end;
  712. if (mc_tmp^.size and lastblockflag) <> 0 then
  713. break;
  714. mc_tmp := pmemchunk_var(pointer(mc_tmp)+(mc_tmp^.size and sizemask));
  715. if (mc_tmp^.size and usedflag) <> 0 then
  716. break;
  717. until false;
  718. end;
  719. {*****************************************************************************
  720. Grow Heap
  721. *****************************************************************************}
  722. function alloc_oschunk(blockindex, size: ptrint): pointer;
  723. var
  724. pmc : pmemchunk_fixed;
  725. pmcv : pmemchunk_var;
  726. minsize,
  727. maxsize,
  728. i, count : ptrint;
  729. chunksize : ptrint;
  730. begin
  731. { increase size by size needed for os block header }
  732. minsize := size + sizeof(toschunk);
  733. if blockindex<>0 then
  734. maxsize := (size * $ffff) + sizeof(toschunk)
  735. else
  736. maxsize := high(ptrint);
  737. { blocks available in freelist? }
  738. result := freeoslist;
  739. while result <> nil do
  740. begin
  741. if (poschunk(result)^.size >= minsize) and
  742. (poschunk(result)^.size <= maxsize) then
  743. begin
  744. size := poschunk(result)^.size;
  745. remove_from_oslist(poschunk(result));
  746. break;
  747. end;
  748. result := poschunk(result)^.next;
  749. end;
  750. if result = nil then
  751. begin
  752. {$ifdef DUMPGROW}
  753. writeln('growheap(',size,') allocating ',(size+sizeof(toschunk)+$ffff) and $ffff0000);
  754. DumpBlocks;
  755. {$endif}
  756. { allocate by 64K size }
  757. size := (size+sizeof(toschunk)+$ffff) and not $ffff;
  758. { allocate smaller blocks for fixed-size chunks }
  759. if blockindex<>0 then
  760. begin
  761. result := SysOSAlloc(GrowHeapSizeSmall);
  762. if result<>nil then
  763. size := GrowHeapSizeSmall;
  764. end
  765. { first try 256K (default) }
  766. else if size<=GrowHeapSize1 then
  767. begin
  768. result := SysOSAlloc(GrowHeapSize1);
  769. if result<>nil then
  770. size := GrowHeapSize1;
  771. end
  772. { second try 1024K (default) }
  773. else if size<=GrowHeapSize2 then
  774. begin
  775. result := SysOSAlloc(GrowHeapSize2);
  776. if result<>nil then
  777. size := GrowHeapSize2;
  778. end
  779. { else allocate the needed bytes }
  780. else
  781. result := SysOSAlloc(size);
  782. { try again }
  783. if result=nil then
  784. begin
  785. result := SysOSAlloc(size);
  786. if (result=nil) then
  787. begin
  788. if ReturnNilIfGrowHeapFails then
  789. exit
  790. else
  791. HandleError(203);
  792. end;
  793. end;
  794. { set the total new heap size }
  795. inc(internal_status.currheapsize,size);
  796. if internal_status.currheapsize>internal_status.maxheapsize then
  797. internal_status.maxheapsize:=internal_status.currheapsize;
  798. end;
  799. { initialize os-block }
  800. poschunk(result)^.used := 0;
  801. poschunk(result)^.size := size;
  802. inc(result, sizeof(toschunk));
  803. if blockindex<>0 then
  804. begin
  805. { chop os chunk in fixedsize parts,
  806. maximum of $ffff elements are allowed, otherwise
  807. there will be an overflow }
  808. chunksize := blockindex shl blockshr;
  809. count := (size-sizeof(toschunk)) div chunksize;
  810. if count>$ffff then
  811. HandleError(204);
  812. pmc := pmemchunk_fixed(result);
  813. pmc^.prev_fixed := nil;
  814. i := 0;
  815. repeat
  816. pmc^.size := fixedsizeflag or chunksize or (i shl 16);
  817. pmc^.next_fixed := pointer(pmc)+chunksize;
  818. inc(i);
  819. if i < count then
  820. begin
  821. pmc := pmemchunk_fixed(pointer(pmc)+chunksize);
  822. pmc^.prev_fixed := pointer(pmc)-chunksize;
  823. end
  824. else
  825. begin
  826. break;
  827. end;
  828. until false;
  829. append_to_list_fixed(blockindex, pmc);
  830. pmc^.prev_fixed := pointer(pmc)-chunksize;
  831. freelists_fixed[blockindex] := pmemchunk_fixed(result);
  832. end
  833. else
  834. begin
  835. pmcv := pmemchunk_var(result);
  836. append_to_list_var(pmcv);
  837. pmcv^.size := ((size-sizeof(toschunk)) and sizemask) or (firstblockflag or lastblockflag);
  838. pmcv^.prevsize := 0;
  839. end;
  840. {$ifdef TestFreeLists}
  841. TestFreeLists;
  842. {$endif TestFreeLists}
  843. end;
  844. {*****************************************************************************
  845. SysGetMem
  846. *****************************************************************************}
  847. function SysGetMem_Fixed(size: ptrint): pointer;
  848. var
  849. pcurr: pmemchunk_fixed;
  850. poc: poschunk;
  851. s: ptrint;
  852. begin
  853. result:=nil;
  854. { try to find a block in one of the freelists per size }
  855. s := size shr blockshr;
  856. pcurr := freelists_fixed[s];
  857. { no free blocks ? }
  858. if not assigned(pcurr) then
  859. begin
  860. pcurr := alloc_oschunk(s, size);
  861. if not assigned(pcurr) then
  862. exit;
  863. end;
  864. { get a pointer to the block we should return }
  865. result := pointer(pcurr)+sizeof(tmemchunk_fixed_hdr);
  866. { flag as in-use }
  867. pcurr^.size := pcurr^.size or usedflag;
  868. { update freelist }
  869. freelists_fixed[s] := pcurr^.next_fixed;
  870. if assigned(freelists_fixed[s]) then
  871. freelists_fixed[s]^.prev_fixed := nil;
  872. poc := poschunk(pointer(pcurr)-((pcurr^.size shr 16)*(pcurr^.size and fixedsizemask)+sizeof(toschunk)));
  873. inc(poc^.used);
  874. { statistics }
  875. inc(internal_status.currheapused,size);
  876. if internal_status.currheapused>internal_status.maxheapused then
  877. internal_status.maxheapused:=internal_status.currheapused;
  878. {$ifdef TestFreeLists}
  879. if test_each then
  880. TestFreeLists;
  881. {$endif TestFreeLists}
  882. end;
  883. function SysGetMem_Var(size: ptrint): pointer;
  884. var
  885. pcurr : pmemchunk_var;
  886. {$ifdef BESTMATCH}
  887. pbest : pmemchunk_var;
  888. {$endif}
  889. begin
  890. result:=nil;
  891. {$ifdef BESTMATCH}
  892. pbest := nil;
  893. {$endif}
  894. pcurr := freelist_var;
  895. while assigned(pcurr) do
  896. begin
  897. {$ifdef BESTMATCH}
  898. if pcurr^.size=size then
  899. begin
  900. break;
  901. end
  902. else
  903. begin
  904. if (pcurr^.size>size) then
  905. begin
  906. if (not assigned(pbest)) or
  907. (pcurr^.size<pbest^.size) then
  908. pbest := pcurr;
  909. end;
  910. end;
  911. {$else BESTMATCH}
  912. if pcurr^.size>=size then
  913. break;
  914. {$endif BESTMATCH}
  915. pcurr := pcurr^.next_var;
  916. end;
  917. {$ifdef BESTMATCH}
  918. if not assigned(pcurr) then
  919. pcurr := pbest;
  920. {$endif}
  921. if not assigned(pcurr) then
  922. begin
  923. // all os-chunks full, allocate a new one
  924. pcurr := alloc_oschunk(0, size);
  925. if not assigned(pcurr) then
  926. exit;
  927. end;
  928. { get pointer of the block we should return }
  929. result := pointer(pcurr)+sizeof(tmemchunk_var_hdr);
  930. { remove the current block from the freelist }
  931. remove_from_list_var(pcurr);
  932. { create the left over freelist block, if at least 16 bytes are free }
  933. split_block(pcurr, size);
  934. { flag block as used }
  935. pcurr^.size := pcurr^.size or usedflag;
  936. { statistics }
  937. inc(internal_status.currheapused,size);
  938. if internal_status.currheapused>internal_status.maxheapused then
  939. internal_status.maxheapused:=internal_status.currheapused;
  940. {$ifdef TestFreeLists}
  941. if test_each then
  942. TestFreeLists;
  943. {$endif TestFreeLists}
  944. end;
  945. function SysGetMem(size : ptrint):pointer;
  946. begin
  947. { Something to allocate ? }
  948. if size<=0 then
  949. begin
  950. { give an error for < 0 }
  951. if size<0 then
  952. HandleError(204);
  953. { we always need to allocate something, using heapend is not possible,
  954. because heappend can be changed by growheap (PFV) }
  955. size := 1;
  956. end;
  957. { calc to multiple of 16 after adding the needed bytes for memchunk header }
  958. if size <= (maxblocksize - sizeof(tmemchunk_fixed_hdr)) then
  959. begin
  960. size := (size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and fixedsizemask;
  961. sysgetmem := sysgetmem_fixed(size);
  962. end
  963. else
  964. begin
  965. size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
  966. sysgetmem := sysgetmem_var(size);
  967. end;
  968. end;
  969. {*****************************************************************************
  970. SysFreeMem
  971. *****************************************************************************}
  972. function SysFreeMem_Fixed(pcurr: pmemchunk_fixed; size: ptrint): ptrint;
  973. var
  974. pcurrsize: ptrint;
  975. blockindex: ptrint;
  976. poc: poschunk;
  977. begin
  978. pcurrsize := pcurr^.size and fixedsizemask;
  979. if size<>pcurrsize then
  980. HandleError(204);
  981. dec(internal_status.currheapused,pcurrsize);
  982. { insert the block in it's freelist }
  983. pcurr^.size := pcurr^.size and (not usedflag);
  984. blockindex := pcurrsize shr blockshr;
  985. append_to_list_fixed(blockindex, pcurr);
  986. { decrease used blocks count }
  987. poc := poschunk(pointer(pcurr)-(pcurr^.size shr 16)*pcurrsize-sizeof(toschunk));
  988. if poc^.used = 0 then
  989. HandleError(204);
  990. dec(poc^.used);
  991. if poc^.used = 0 then
  992. begin
  993. // block eligable for freeing
  994. append_to_oslist_fixed(blockindex, pcurrsize, poc);
  995. end;
  996. SysFreeMem_Fixed := pcurrsize;
  997. {$ifdef TestFreeLists}
  998. if test_each then
  999. TestFreeLists;
  1000. {$endif TestFreeLists}
  1001. end;
  1002. function SysFreeMem_Var(pcurr: pmemchunk_var; size: ptrint): ptrint;
  1003. var
  1004. pcurrsize: ptrint;
  1005. begin
  1006. pcurrsize := pcurr^.size and sizemask;
  1007. if size<>pcurrsize then
  1008. HandleError(204);
  1009. dec(internal_status.currheapused,pcurrsize);
  1010. { insert the block in it's freelist }
  1011. pcurr^.size := pcurr^.size and (not usedflag);
  1012. append_to_list_var(pcurr);
  1013. SysFreeMem_Var := pcurrsize;
  1014. pcurr := try_concat_free_chunk(pcurr);
  1015. if (pcurr^.size and (firstblockflag or lastblockflag)) = (firstblockflag or lastblockflag) then
  1016. begin
  1017. append_to_oslist_var(pcurr);
  1018. end;
  1019. {$ifdef TestFreeLists}
  1020. if test_each then
  1021. TestFreeLists;
  1022. {$endif TestFreeLists}
  1023. end;
  1024. function SysFreeMem(p: pointer): ptrint;
  1025. var
  1026. pcurrsize: ptrint;
  1027. begin
  1028. if p=nil then
  1029. exit;
  1030. pcurrsize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
  1031. { check if this is a fixed- or var-sized chunk }
  1032. if (pcurrsize and fixedsizeflag) = 0 then
  1033. begin
  1034. result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)), pcurrsize and sizemask);
  1035. end
  1036. else
  1037. begin
  1038. result := sysfreemem_fixed(pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr)), pcurrsize and fixedsizemask);
  1039. end;
  1040. end;
  1041. {*****************************************************************************
  1042. SysFreeMemSize
  1043. *****************************************************************************}
  1044. Function SysFreeMemSize(p: pointer; size: ptrint):ptrint;
  1045. var
  1046. pcurrsize: ptrint;
  1047. begin
  1048. SysFreeMemSize := 0;
  1049. if size<=0 then
  1050. begin
  1051. if size<0 then
  1052. HandleError(204);
  1053. exit;
  1054. end;
  1055. if p=nil then
  1056. HandleError(204);
  1057. pcurrsize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
  1058. { check if this is a fixed- or var-sized chunk }
  1059. if (pcurrsize and fixedsizeflag) = 0 then
  1060. begin
  1061. size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
  1062. result := sysfreemem_var(pmemchunk_var(p-sizeof(tmemchunk_var_hdr)), size);
  1063. end
  1064. else
  1065. begin
  1066. size := (size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and fixedsizemask;
  1067. result := sysfreemem_fixed(pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr)), size);
  1068. end;
  1069. end;
  1070. {*****************************************************************************
  1071. SysMemSize
  1072. *****************************************************************************}
  1073. function SysMemSize(p: pointer): ptrint;
  1074. begin
  1075. SysMemSize := pmemchunk_fixed(pointer(p)-sizeof(tmemchunk_fixed_hdr))^.size;
  1076. if (SysMemSize and fixedsizeflag) = 0 then
  1077. begin
  1078. SysMemSize := SysMemSize and sizemask;
  1079. dec(SysMemSize, sizeof(tmemchunk_var_hdr));
  1080. end
  1081. else
  1082. begin
  1083. SysMemSize := SysMemSize and fixedsizemask;
  1084. dec(SysMemSize, sizeof(tmemchunk_fixed_hdr));
  1085. end;
  1086. end;
  1087. {*****************************************************************************
  1088. SysAllocMem
  1089. *****************************************************************************}
  1090. function SysAllocMem(size: ptrint): pointer;
  1091. begin
  1092. sysallocmem := MemoryManager.GetMem(size);
  1093. if sysallocmem<>nil then
  1094. FillChar(sysallocmem^,MemoryManager.MemSize(sysallocmem),0);
  1095. end;
  1096. {*****************************************************************************
  1097. SysResizeMem
  1098. *****************************************************************************}
  1099. function SysTryResizeMem(var p: pointer; size: ptrint): boolean;
  1100. var
  1101. pcurrsize,
  1102. oldsize,
  1103. currsize : ptrint;
  1104. pcurr : pmemchunk_var;
  1105. begin
  1106. SysTryResizeMem := false;
  1107. { fix p to point to the heaprecord }
  1108. pcurrsize := pmemchunk_fixed(p-sizeof(tmemchunk_fixed_hdr))^.size;
  1109. if (pcurrsize and fixedsizeflag) = 0 then
  1110. begin
  1111. currsize := pcurrsize and sizemask;
  1112. size := (size+sizeof(tmemchunk_var_hdr)+(blocksize-1)) and sizemask;
  1113. end
  1114. else
  1115. begin
  1116. currsize := pcurrsize and fixedsizemask;
  1117. size := (size+sizeof(tmemchunk_fixed_hdr)+(blocksize-1)) and fixedsizemask;
  1118. end;
  1119. { is the allocated block still correct? }
  1120. if (currsize>=size) and (size>(currsize-blocksize)) then
  1121. begin
  1122. SysTryResizeMem := true;
  1123. {$ifdef TestFreeLists}
  1124. if test_each then
  1125. TestFreeLists;
  1126. {$endif TestFreeLists}
  1127. exit;
  1128. end;
  1129. { don't do resizes on fixed-size blocks }
  1130. if (pcurrsize and fixedsizeflag) <> 0 then
  1131. exit;
  1132. { get pointer to block }
  1133. pcurr := pmemchunk_var(pointer(p)-sizeof(tmemchunk_var_hdr));
  1134. oldsize := currsize;
  1135. { do we need to allocate more memory ? }
  1136. if size>currsize then
  1137. begin
  1138. { the size is bigger than the previous size, we need to allocated more mem.
  1139. We first check if the blocks after the current block are free. If not we
  1140. simply call getmem/freemem to get the new block }
  1141. if check_concat_free_chunk_forward(pcurr,size) then
  1142. begin
  1143. try_concat_free_chunk_forward(pcurr);
  1144. currsize := (pcurr^.size and sizemask);
  1145. end;
  1146. end;
  1147. { not enough space? }
  1148. if size>currsize then
  1149. exit;
  1150. { is the size smaller then we can adjust the block to that size and insert
  1151. the other part into the freelist }
  1152. if currsize>size then
  1153. split_block(pcurr, size);
  1154. inc(internal_status.currheapused,size-oldsize);
  1155. SysTryResizeMem := true;
  1156. {$ifdef TestFreeLists}
  1157. if test_each then
  1158. TestFreeLists;
  1159. {$endif TestFreeLists}
  1160. end;
  1161. {*****************************************************************************
  1162. SysResizeMem
  1163. *****************************************************************************}
  1164. function SysReAllocMem(var p: pointer; size: ptrint):pointer;
  1165. var
  1166. minsize : ptrint;
  1167. p2 : pointer;
  1168. begin
  1169. { Free block? }
  1170. if size=0 then
  1171. begin
  1172. if p<>nil then
  1173. begin
  1174. MemoryManager.FreeMem(p);
  1175. p := nil;
  1176. end;
  1177. end
  1178. else
  1179. { Allocate a new block? }
  1180. if p=nil then
  1181. begin
  1182. p := MemoryManager.GetMem(size);
  1183. end
  1184. else
  1185. { Resize block }
  1186. if not SysTryResizeMem(p,size) then
  1187. begin
  1188. minsize := MemoryManager.MemSize(p);
  1189. if size < minsize then
  1190. minsize := size;
  1191. p2 := MemoryManager.GetMem(size);
  1192. if p2<>nil then
  1193. Move(p^,p2^,minsize);
  1194. MemoryManager.FreeMem(p);
  1195. p := p2;
  1196. end;
  1197. SysReAllocMem := p;
  1198. end;
  1199. {*****************************************************************************
  1200. MemoryMutexManager default hooks
  1201. *****************************************************************************}
  1202. procedure SysHeapMutexInit;
  1203. begin
  1204. { nothing todo }
  1205. end;
  1206. procedure SysHeapMutexDone;
  1207. begin
  1208. { nothing todo }
  1209. end;
  1210. procedure SysHeapMutexLock;
  1211. begin
  1212. { give an runtime error. the program is running multithreaded without
  1213. any heap protection. this will result in unpredictable errors so
  1214. stopping here with an error is more safe (PFV) }
  1215. runerror(244);
  1216. end;
  1217. procedure SysHeapMutexUnLock;
  1218. begin
  1219. { see SysHeapMutexLock for comment }
  1220. runerror(244);
  1221. end;
  1222. {*****************************************************************************
  1223. InitHeap
  1224. *****************************************************************************}
  1225. { This function will initialize the Heap manager and need to be called from
  1226. the initialization of the system unit }
  1227. procedure InitHeap;
  1228. begin
  1229. FillChar(freelists_fixed,sizeof(tfreelists),0);
  1230. freelist_var := nil;
  1231. freeoslist := nil;
  1232. freeoslistcount := 0;
  1233. fillchar(internal_status,sizeof(internal_status),0);
  1234. end;
  1235. {
  1236. $Log: heap.inc,v $
  1237. Revision 1.51 2005/04/04 15:40:30 peter
  1238. * check if there is enough room before concatting blocks in
  1239. systryresizemem()
  1240. Revision 1.50 2005/03/25 22:53:39 jonas
  1241. * fixed several warnings and notes about unused variables (mainly) or
  1242. uninitialised use of variables/function results (a few)
  1243. Revision 1.49 2005/03/21 16:31:33 peter
  1244. * fix crash under win32 with previous reallocmem fix
  1245. Revision 1.48 2005/03/20 18:57:29 peter
  1246. * fixed tryresizemem
  1247. Revision 1.47 2005/03/04 16:49:34 peter
  1248. * fix getheapstatus bootstrapping
  1249. Revision 1.46 2005/03/02 14:25:19 marco
  1250. * small typo fix on last commit
  1251. Revision 1.45 2005/03/02 10:46:10 marco
  1252. * getfpcheapstatus now also on memmgr
  1253. Revision 1.44 2005/02/28 15:38:38 marco
  1254. * getFPCheapstatus (no, FPC HEAP, not FP CHEAP!)
  1255. Revision 1.43 2005/02/14 17:13:22 peter
  1256. * truncate log
  1257. Revision 1.42 2005/01/30 11:56:29 peter
  1258. * allow Freemem(nil)
  1259. }