memory.cpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013
  1. #include "memory.h"
  2. #include <SDL/SDL.h>
  3. #ifdef _USE_MEM_MANAGER_
  4. namespace mem {
  5. #ifdef malloc
  6. #undef malloc
  7. #endif
  8. #ifdef realloc
  9. #undef realloc
  10. #endif
  11. #ifdef calloc
  12. #undef calloc
  13. #endif
  14. #ifdef free
  15. #undef free
  16. #endif
  17. #ifdef new
  18. #undef new
  19. #endif
  20. #ifdef delete
  21. #undef delete
  22. #endif
  23. #ifdef _DEBUG_
  24. #define SANITY_CHECKS SanityChecks();
  25. #define PRINT_CALL_INFO(x) { if(mem::print_call_info) INFO(x) }
  26. #else
  27. #define SANITY_CHECKS
  28. #define PRINT_CALL_INFO(x)
  29. #endif
  30. #define MERROR(x) {++errors_num; if(print_errors) ERROR(x)}
  31. /*
  32. =======================================================================================================================================
  33. variables and types =
  34. =======================================================================================================================================
  35. */
  36. // owner info for the block
  37. struct mblock_owner_t
  38. {
  39. const char* file;
  40. int line;
  41. const char* func;
  42. };
  43. // used as a list node
  44. struct mem_block_t
  45. {
  46. void* addr;
  47. size_t size; // aka offset
  48. bool free_space;
  49. bool active; // if true then the block/node is an active node of the list
  50. uint id; // the id in the mem_blocks array
  51. mem_block_t* prev;
  52. mem_block_t* next;
  53. mblock_owner_t owner; // for leak tracking
  54. };
  55. // the buffer
  56. const size_t buffer_size = 30*MEGABYTE;
  57. char prealloced_buff [buffer_size];
  58. void* buffer = prealloced_buff;
  59. size_t free_size = buffer_size;
  60. // block stuff
  61. const int MAX_MEM_BLOCKS = 20*KILOBYTE;
  62. mem_block_t mem_blocks[ MAX_MEM_BLOCKS ]; // this is actualy a list
  63. uint active_mem_blocks_num = 3;
  64. mem_block_t& head_node = mem_blocks[0];
  65. mem_block_t& tail_node = mem_blocks[1];
  66. // dummy
  67. static void DummyFunc() {}
  68. // Used so we can save a check in NewBlock
  69. static void init();
  70. void (*p_Init)(void) = init;
  71. // threads
  72. void (*p_Lock)(void) = DummyFunc;
  73. void (*p_Unlock)(void) = DummyFunc;
  74. SDL_sem* semaphore = NULL;
  75. // unknown owner
  76. mblock_owner_t unknown_owner = {"??", 0, "??"};
  77. // times we called each
  78. uint malloc_called_num = 0;
  79. uint calloc_called_num = 0;
  80. uint realloc_called_num = 0;
  81. uint free_called_num = 0;
  82. uint new_called_num = 0;
  83. uint delete_called_num = 0;
  84. // errors & other
  85. bool print_errors = false;
  86. uint errors_num = 0;
  87. bool print_call_info = false; // works only in debug
  88. /*
  89. =======================================================================================================================================
  90. FreeBlocksNum =
  91. =======================================================================================================================================
  92. */
  93. static int FreeBlocksNum()
  94. {
  95. mem_block_t* mb = head_node.next;
  96. int num = 0;
  97. do
  98. {
  99. if( mb->free_space )
  100. ++num;
  101. mb = mb->next;
  102. } while( mb != &tail_node );
  103. return num;
  104. }
  105. /*
  106. =======================================================================================================================================
  107. SetOwner =
  108. set the file,func,line to the given block =
  109. =======================================================================================================================================
  110. */
  111. static inline void SetOwner( mem_block_t* mb, mblock_owner_t* owner )
  112. {
  113. DEBUG_ERR( mb == &head_node || mb == &tail_node ); // shouldn't change the head_node or tail node
  114. mb->owner.file = owner->file;
  115. mb->owner.line = owner->line;
  116. mb->owner.func = owner->func;
  117. }
  118. /*
  119. =======================================================================================================================================
  120. SanityChecks =
  121. =======================================================================================================================================
  122. */
  123. static bool SanityChecks()
  124. {
  125. // the head_node
  126. if( !(head_node.addr == NULL || head_node.size == 0 || head_node.prev == NULL || head_node.id == 0 ||
  127. head_node.active == true || head_node.free_space == false) )
  128. MERROR( "In head_node" );
  129. // check the list
  130. uint num = 0;
  131. for( int i=0; i<MAX_MEM_BLOCKS; i++ )
  132. if( mem_blocks[i].active ) ++num;
  133. if( active_mem_blocks_num != num ) MERROR( "In mem_blocks list" );
  134. // check the size
  135. size_t size = 0;
  136. mem_block_t* mb = head_node.next;
  137. do
  138. {
  139. if( !mb->free_space )
  140. size += mb->size;
  141. // the prev's next has to be ME and the next's prev has to show me also
  142. if( mb->prev->next!=mb || mb->next->prev!=mb )
  143. MERROR( "Chain is broken" );
  144. if( mb->next!=&tail_node && ((char*)mb->addr)+mb->size!=mb->next->addr )
  145. MERROR( "In crnt and next sizes cohisency" );
  146. if( mb->next == NULL || mb->prev==NULL )
  147. MERROR( "Prev or next are NULL" );
  148. mb = mb->next;
  149. } while( mb!=&tail_node );
  150. if( size != buffer_size-free_size ) MERROR( "In size" );
  151. return true;
  152. }
  153. /*
  154. =======================================================================================================================================
  155. BytesStr =
  156. =======================================================================================================================================
  157. */
  158. static char* BytesStr( size_t size )
  159. {
  160. static char str[10];
  161. if( size > MEGABYTE )
  162. sprintf( str, "%dMB", (uint)(size/MEGABYTE) );
  163. else if( size > KILOBYTE )
  164. sprintf( str, "%dKB", (uint)(size/KILOBYTE) );
  165. else
  166. sprintf( str, "%dB ", (uint)(size) );
  167. return str;
  168. }
  169. /*
  170. =======================================================================================================================================
  171. printBlockInfo =
  172. =======================================================================================================================================
  173. */
  174. static void printBlockInfo( const mem_block_t* mb )
  175. {
  176. const char cond = (mb->free_space) ? 'F' : 'U';
  177. cout << setw(4) << setfill(' ') << mb->id << setw(0) << ' ' << cond << ' ' << setw(6) << BytesStr( mb->size ) << setw(0) << hex <<
  178. " 0x" << mb->addr << dec;
  179. if( cond=='U' ) cout << " " << mb->owner.file << ' ' << mb->owner.line << ' ' << mb->owner.func;
  180. cout << endl;
  181. }
  182. /*
  183. =======================================================================================================================================
  184. printInfo =
  185. =======================================================================================================================================
  186. */
  187. void printInfo( uint flags )
  188. {
  189. cout << "\n=========================== MEM REPORT =========================" << endl;
  190. // header
  191. if( (flags & PRINT_ALL)==PRINT_ALL || (flags & PRINT_HEADER)==PRINT_HEADER )
  192. {
  193. cout << "Used space: " << BytesStr(buffer_size-free_size) << "(" << buffer_size-free_size << ")";
  194. cout << ", free: " << BytesStr(free_size) << " (" << free_size << ")";
  195. cout << ", total: " << BytesStr(buffer_size) << " (" << buffer_size << ")" << endl;
  196. int num = FreeBlocksNum();
  197. cout << "Active blocks: " << active_mem_blocks_num << "(free space: " << num << ", used space: " << active_mem_blocks_num-num <<
  198. "), total: " << MAX_MEM_BLOCKS << endl;
  199. // get the block with the max free space
  200. mem_block_t* tmp = head_node.next;
  201. mem_block_t* mb = &head_node;
  202. do
  203. {
  204. if( tmp->free_space && tmp->size > mb->size )
  205. mb = tmp;
  206. tmp = tmp->next;
  207. } while( tmp!=&tail_node );
  208. cout << "Block with max free space: " << mb->id << ", size: " << BytesStr( mb->size ) << " (" << mb->size << ")" << endl;
  209. // print how many times malloc,realloc etc have been called
  210. cout << "Func calls: malloc:" << malloc_called_num << ", calloc:" << calloc_called_num << ", realloc:" << realloc_called_num <<
  211. ", free:" << free_called_num << ", new:" << new_called_num << ", delete:" << delete_called_num << endl;
  212. cout << "Errors count:" << errors_num << endl;
  213. }
  214. // blocks
  215. if( (flags & PRINT_ALL)==PRINT_ALL || (flags & PRINT_BLOCKS)==PRINT_BLOCKS )
  216. {
  217. cout << "Block table (id, type, size [, file, line, func]):" << endl;
  218. mem_block_t* mb = head_node.next;
  219. do
  220. {
  221. printBlockInfo( mb );
  222. mb = mb->next;
  223. } while( mb!=&tail_node );
  224. }
  225. cout << "================================================================\n" << endl;
  226. }
  227. /*
  228. =======================================================================================================================================
  229. init =
  230. =======================================================================================================================================
  231. */
  232. static void init()
  233. {
  234. #ifdef _DEBUG_
  235. memset( buffer, (char)0xCC, buffer_size );
  236. #endif
  237. // mem block stuff
  238. // set the head block. Its the head of the list
  239. head_node.addr = NULL;
  240. head_node.size = 0;
  241. head_node.prev = NULL;
  242. head_node.next = &mem_blocks[2];
  243. head_node.id = 0;
  244. head_node.active = true;
  245. head_node.free_space = false;
  246. // set the head block. Its the head of the list
  247. tail_node.addr = NULL;
  248. tail_node.size = 0;
  249. tail_node.prev = &mem_blocks[2];
  250. tail_node.next = NULL;
  251. tail_node.id = 1;
  252. tail_node.active = true;
  253. tail_node.free_space = false;
  254. // set the first block
  255. mem_blocks[2].addr = buffer;
  256. mem_blocks[2].size = buffer_size;
  257. mem_blocks[2].prev = &head_node;
  258. mem_blocks[2].next = &tail_node;
  259. mem_blocks[2].id = 2;
  260. mem_blocks[2].active = true;
  261. mem_blocks[2].free_space = true;
  262. // set the rest
  263. memset( &mem_blocks[3], 0, sizeof(mem_block_t)*(MAX_MEM_BLOCKS-3) );
  264. for( int i=3; i<MAX_MEM_BLOCKS; i++ )
  265. {
  266. mem_blocks[i].id = i;
  267. }
  268. p_Init = DummyFunc;
  269. semaphore = SDL_CreateSemaphore(1);
  270. }
  271. /*
  272. =======================================================================================================================================
  273. thread stuff =
  274. =======================================================================================================================================
  275. */
  276. static void Lock()
  277. {
  278. if( SDL_SemWait(semaphore)==-1 )
  279. MERROR( "Cant lock semaphore" );
  280. }
  281. static void Unlock()
  282. {
  283. if( SDL_SemPost(semaphore)==-1 )
  284. MERROR( "Cant unlock semaphore" );
  285. }
  286. /*
  287. =======================================================================================================================================
  288. Enable =
  289. =======================================================================================================================================
  290. */
  291. void Enable( uint flags )
  292. {
  293. if( (flags & THREADS)==THREADS )
  294. {
  295. p_Lock = Lock;
  296. p_Unlock = Unlock;
  297. }
  298. if( (flags & PRINT_ERRORS)==PRINT_ERRORS )
  299. print_errors = true;
  300. if( (flags & PRINT_CALL_INFO)==PRINT_CALL_INFO )
  301. print_call_info = true;
  302. }
  303. /*
  304. =======================================================================================================================================
  305. Disable =
  306. =======================================================================================================================================
  307. */
  308. void Disable( uint flags )
  309. {
  310. if( (flags & THREADS)==THREADS )
  311. {
  312. p_Lock = DummyFunc;
  313. p_Unlock = DummyFunc;
  314. }
  315. if( (flags & PRINT_ERRORS)==PRINT_ERRORS )
  316. print_errors = false;
  317. if( (flags & PRINT_CALL_INFO)==PRINT_CALL_INFO )
  318. print_call_info = false;
  319. }
  320. /*
  321. =======================================================================================================================================
  322. GetBlock =
  323. find the active block who has for addr the given ptr param. Func used by free and realloc =
  324. =======================================================================================================================================
  325. */
  326. static mem_block_t* GetBlock( void* ptr )
  327. {
  328. //if( ptr<buffer || ptr>((char*)buffer+buffer_size) ) return &head_node;
  329. mem_block_t* mb = tail_node.prev;
  330. do
  331. {
  332. if( mb->addr==ptr )
  333. return mb;
  334. mb = mb->prev;
  335. } while( mb!=&head_node );
  336. return NULL;
  337. //
  338. // int a = 1;
  339. // int b = active_mem_blocks_num-2;
  340. // mem_block_t* mb = head_node.next;
  341. // int pos = 1;
  342. //
  343. // for(;;)
  344. // {
  345. // int tmp = (a+b)/2;
  346. //
  347. // // move the mb to crnt_pos
  348. // if( pos < tmp )
  349. // for( int i=0; i<tmp-pos; i++ )
  350. // mb = mb->next;
  351. // else
  352. // for( int i=0; i<pos-tmp; i++ )
  353. // mb = mb->prev;
  354. // pos = tmp;
  355. //
  356. // if( ptr < mb->addr )
  357. // b = pos;
  358. // else if( ptr > mb->addr )
  359. // a = pos;
  360. // else
  361. // return mb;
  362. // if( b-a < 2 ) break;
  363. // }
  364. //
  365. // return NULL;
  366. }
  367. /*
  368. =======================================================================================================================================
  369. GetInactiveBlock =
  370. get an inactive node/block =
  371. =======================================================================================================================================
  372. */
  373. static mem_block_t* GetInactiveBlock()
  374. {
  375. for( int i=2; i<MAX_MEM_BLOCKS; i++ )
  376. {
  377. if( !mem_blocks[i].active )
  378. return &mem_blocks[i];
  379. }
  380. FATAL( "Cannot find an inactive node. Inc the mem_blocks arr" );
  381. return NULL;
  382. }
  383. /*
  384. =======================================================================================================================================
  385. WorstFit =
  386. "worst fit" algorithm. It returns the block with the biger free space =
  387. =======================================================================================================================================
  388. */
  389. static mem_block_t* WorstFit( size_t size )
  390. {
  391. mem_block_t* tmp = tail_node.prev;
  392. mem_block_t* candidate = &head_node;
  393. do
  394. {
  395. if( tmp->size > candidate->size && tmp->free_space )
  396. candidate = tmp;
  397. tmp = tmp->prev;
  398. } while( tmp!=&head_node );
  399. return candidate;
  400. }
  401. /*
  402. =======================================================================================================================================
  403. BestFit =
  404. =======================================================================================================================================
  405. */
  406. static mem_block_t* BestFit( size_t size )
  407. {
  408. mem_block_t* tmp = tail_node.prev;
  409. mem_block_t* candidate = &head_node;
  410. // find a free block firstly
  411. do
  412. {
  413. if( tmp->free_space )
  414. {
  415. candidate = tmp;
  416. break;
  417. }
  418. tmp = tmp->prev;
  419. } while( tmp!=&head_node );
  420. if( candidate == &head_node ) return candidate; // we failed to find free node
  421. // now run the real deal
  422. do
  423. {
  424. if( tmp->free_space )
  425. {
  426. if( (tmp->size < candidate->size) && (tmp->size > size) )
  427. candidate = tmp;
  428. else if( tmp->size == size )
  429. return tmp;
  430. }
  431. tmp = tmp->prev;
  432. } while( tmp!=&head_node );
  433. return candidate;
  434. }
  435. /*
  436. =======================================================================================================================================
  437. BadFit =
  438. =======================================================================================================================================
  439. */
  440. static mem_block_t* BadFit( size_t size )
  441. {
  442. mem_block_t* tmp = tail_node.prev;
  443. do
  444. {
  445. if( tmp->size >= size && tmp->free_space )
  446. return tmp;
  447. tmp = tmp->prev;
  448. } while( tmp!=&head_node );
  449. return &head_node;
  450. }
  451. /*
  452. =======================================================================================================================================
  453. NewBlock =
  454. just free the given block =
  455. =======================================================================================================================================
  456. */
  457. static mem_block_t* NewBlock( size_t size )
  458. {
  459. p_Init();
  460. // a simple check
  461. if( size < 1 )
  462. {
  463. MERROR( "Size is < 1" );
  464. return &head_node;
  465. }
  466. // get an inactive block
  467. mem_block_t* newmb = GetInactiveBlock();
  468. // use an algorithm to find the best candidate
  469. mem_block_t* candidate = BestFit(size);
  470. if( candidate==&head_node )
  471. {
  472. FATAL( "There are no free blocks" );
  473. return &head_node;
  474. }
  475. // case 0: we have found a big enought free block
  476. if( candidate->size > size )
  477. {
  478. // reorganize the prev and the next of the 3 involved blocks
  479. DEBUG_ERR( candidate->prev==NULL );
  480. candidate->prev->next = newmb;
  481. newmb->prev = candidate->prev;
  482. newmb->next = candidate;
  483. candidate->prev = newmb;
  484. // do the rest of the changes
  485. newmb->addr = candidate->addr;
  486. newmb->size = size;
  487. candidate->addr = ((char*)candidate->addr) + size;
  488. candidate->size -= size;
  489. newmb->active = true;
  490. newmb->free_space = false;
  491. ++active_mem_blocks_num;
  492. }
  493. // case 1: we have found a block with the exchact space
  494. else if( candidate->size == size )
  495. {
  496. newmb = candidate;
  497. newmb->free_space = false;
  498. }
  499. // case 2: we cannot find a block!!!
  500. else // if( max_free_bytes < bytes )
  501. {
  502. FATAL( "Cant find block with " << size << " free space. Inc buffer" );
  503. return &head_node;
  504. }
  505. free_size -= size;
  506. return newmb;
  507. }
  508. /*
  509. =======================================================================================================================================
  510. FreeBlock =
  511. =======================================================================================================================================
  512. */
  513. static void FreeBlock( mem_block_t* crnt )
  514. {
  515. DEBUG_ERR( crnt->free_space || !crnt->active || crnt==&head_node || crnt==&tail_node ); // self explanatory
  516. free_size += crnt->size;
  517. #ifdef _DEBUG_
  518. memset( crnt->addr, (char)0xCC, crnt->size );
  519. #endif
  520. // rearange the blocks
  521. mem_block_t* prev = crnt->prev;
  522. mem_block_t* next = crnt->next;
  523. // if we have a prev block with free space we resize the prev and then we remove the current one
  524. if( prev != &head_node && prev->free_space )
  525. {
  526. prev->size += crnt->size;
  527. prev->next = next;
  528. next->prev = prev;
  529. // remove the crnt block from the list
  530. crnt->active = false;
  531. --active_mem_blocks_num;
  532. // rearange the blocks for the next check
  533. crnt = prev;
  534. prev = crnt->prev;
  535. }
  536. // if we have a next block with free space we resize the next and then we remove the crnt one
  537. if( next != &tail_node && next->free_space )
  538. {
  539. next->addr = crnt->addr;
  540. next->size += crnt->size;
  541. next->prev = prev;
  542. prev->next = next;
  543. // remove the next block from the list
  544. crnt->active = false;
  545. --active_mem_blocks_num;
  546. }
  547. crnt->free_space = true;
  548. }
  549. /*
  550. =======================================================================================================================================
  551. ReallocBlock =
  552. it gets the block we want to realloc and returns the reallocated (either the same or a new) =
  553. =======================================================================================================================================
  554. */
  555. static mem_block_t* ReallocBlock( mem_block_t* crnt, size_t size )
  556. {
  557. DEBUG_ERR( crnt->free_space || !crnt->active || crnt==&head_node || crnt==&tail_node ); // self explanatory
  558. // case 0: If size is 0 and p points to an existing block of memory, the memory block pointed by ptr is deallocated and a NULL...
  559. // ...pointer is returned.(ISO behaviour)
  560. if( size==0 )
  561. {
  562. FreeBlock( crnt );
  563. crnt = &head_node;
  564. }
  565. // case 1: we want more space
  566. else if( size > crnt->size )
  567. {
  568. mem_block_t* next = crnt->next;
  569. // case 1.0: the next block has enough space. Then we eat from the next
  570. if( next!=&tail_node && next->free_space && next->size >= size )
  571. {
  572. free_size -= size - crnt->size;
  573. next->addr = ((char*)next->addr) + (size - crnt->size); // shift right the addr
  574. next->size -= size - crnt->size;
  575. crnt->size = size;
  576. }
  577. // case 1.1: We cannot eat from the next. Create new block and move the crnt's data there
  578. else
  579. {
  580. mem_block_t* mb = NewBlock( size );
  581. memcpy( mb->addr, crnt->addr, crnt->size );
  582. FreeBlock( crnt );
  583. crnt = mb;
  584. }
  585. }
  586. // case 2: we want less space
  587. else if( size < crnt->size )
  588. {
  589. mem_block_t* next = crnt->next;
  590. // case 2.0: we have next
  591. if( next!=&tail_node )
  592. {
  593. // case 2.0.0: the next block is free space...
  594. // ...resize next and crnt
  595. if( next->free_space )
  596. {
  597. free_size -= size - crnt->size;
  598. next->addr = ((char*)next->addr) - (crnt->size - size); // shl
  599. next->size += crnt->size - size;
  600. crnt->size = size;
  601. }
  602. // case 2.0.1: the next block is used space. Create new free block
  603. else
  604. {
  605. free_size -= size - crnt->size;
  606. mem_block_t* newmb = GetInactiveBlock();
  607. newmb->active = true;
  608. newmb->free_space = true;
  609. newmb->prev = crnt;
  610. newmb->next = next;
  611. newmb->addr = ((char*)crnt->addr) + size;
  612. newmb->size = crnt->size - size;
  613. next->prev = newmb;
  614. crnt->size = size;
  615. crnt->next = newmb;
  616. }
  617. }
  618. // case 2.1: We DONT have next. Create a new node
  619. else
  620. {
  621. free_size -= size - crnt->size;
  622. mem_block_t* newmb = GetInactiveBlock();
  623. newmb->active = true;
  624. newmb->free_space = true;
  625. newmb->prev = crnt;
  626. newmb->next = next;
  627. newmb->addr = ((char*)crnt->addr) + size;
  628. newmb->size = crnt->size - size;
  629. crnt->size = size;
  630. crnt->next = newmb;
  631. }
  632. }
  633. return crnt;
  634. }
  635. /*
  636. =======================================================================================================================================
  637. Malloc =
  638. =======================================================================================================================================
  639. */
  640. static void* Malloc( size_t size, mblock_owner_t* owner=&unknown_owner )
  641. {
  642. p_Lock();
  643. PRINT_CALL_INFO( "caller: \"" << owner->file << ':' << owner->line << "\", size: " << size );
  644. mem_block_t* mb = NewBlock( size );
  645. SetOwner( mb, owner );
  646. SANITY_CHECKS
  647. p_Unlock();
  648. return mb->addr;
  649. }
  650. /*
  651. =======================================================================================================================================
  652. Calloc =
  653. =======================================================================================================================================
  654. */
  655. static void* Calloc( size_t num, size_t size, mblock_owner_t* owner=&unknown_owner )
  656. {
  657. p_Lock();
  658. PRINT_CALL_INFO( "caller: \"" << owner->file << ':' << owner->line << "size: " << size );
  659. mem_block_t* mb = NewBlock( num*size );
  660. SetOwner( mb, owner);
  661. memset( mb->addr, 0x00000000, num*size );
  662. SANITY_CHECKS
  663. p_Unlock();
  664. return mb->addr;
  665. }
  666. /*
  667. =======================================================================================================================================
  668. Realloc =
  669. =======================================================================================================================================
  670. */
  671. static void* Realloc( void* ptr, size_t size, mblock_owner_t* owner=&unknown_owner )
  672. {
  673. p_Lock();
  674. // ISO beheviur
  675. if( ptr==NULL )
  676. {
  677. p_Unlock();
  678. return Malloc( size, owner );
  679. }
  680. // find the block we want to realloc
  681. mem_block_t* mb = GetBlock( ptr );
  682. PRINT_CALL_INFO( "caller: \"" << owner->file << ':' << owner->line << "\", user: \"" << mb->owner.file << ':' << mb->owner.line <<
  683. "\", new size: " << size );
  684. if( mb==NULL )
  685. {
  686. MERROR( "Addr 0x" << hex << ptr << dec << " not found" );
  687. p_Unlock();
  688. return NULL;
  689. }
  690. if( mb->free_space )
  691. {
  692. MERROR( "Addr 0x" << hex << ptr << dec << " is free space" );
  693. p_Unlock();
  694. return NULL;
  695. }
  696. mem_block_t* crnt = ReallocBlock( mb, size );
  697. SetOwner( crnt, owner );
  698. SANITY_CHECKS
  699. p_Unlock();
  700. return crnt->addr;
  701. }
  702. /*
  703. =======================================================================================================================================
  704. Free =
  705. =======================================================================================================================================
  706. */
  707. static void Free( void* ptr, mblock_owner_t* owner=&unknown_owner )
  708. {
  709. p_Lock();
  710. // find the block we want to delete
  711. mem_block_t* mb = GetBlock( ptr );
  712. if( mb==NULL )
  713. {
  714. MERROR( "Addr 0x" << hex << ptr << dec << " not found" );
  715. p_Unlock();
  716. return;
  717. }
  718. if( mb->free_space )
  719. {
  720. MERROR( "Addr 0x" << hex << ptr << dec << " is free space" );
  721. p_Unlock();
  722. return;
  723. }
  724. PRINT_CALL_INFO( "caller: \"" << owner->file << ':' << owner->line << "\", user: \"" << mb->owner.file << ':' << mb->owner.line
  725. << "\", mb size: " << mb->size );
  726. FreeBlock( mb );
  727. SANITY_CHECKS
  728. p_Unlock();
  729. }
  730. } // end namespace
  731. /**
  732. =======================================================================================================================================
  733. overloaded stuff =
  734. =======================================================================================================================================
  735. */
  736. // malloc
  737. void* malloc( size_t size ) throw()
  738. {
  739. ++mem::malloc_called_num;
  740. return mem::Malloc( size );
  741. }
  742. // realloc
  743. void* realloc( void* p, size_t size ) throw()
  744. {
  745. ++mem::realloc_called_num;
  746. return mem::Realloc( p, size );
  747. }
  748. // calloc
  749. void* calloc( size_t num, size_t size ) throw()
  750. {
  751. ++mem::calloc_called_num;
  752. return mem::Calloc( num, size );
  753. }
  754. // free
  755. void free( void* p ) throw()
  756. {
  757. ++mem::free_called_num;
  758. mem::Free( p );
  759. }
  760. // new
  761. void* operator new( size_t size ) throw(std::bad_alloc)
  762. {
  763. ++mem::new_called_num;
  764. return mem::Malloc( size );
  765. }
  766. // new[]
  767. void* operator new[]( size_t size ) throw(std::bad_alloc)
  768. {
  769. ++mem::new_called_num;
  770. return mem::Malloc( size );
  771. }
  772. // delete
  773. void operator delete( void* p ) throw()
  774. {
  775. ++mem::delete_called_num;
  776. mem::Free(p);
  777. }
  778. // delete []
  779. void operator delete[]( void* p ) throw()
  780. {
  781. ++mem::delete_called_num;
  782. mem::Free(p);
  783. }
  784. /**
  785. =======================================================================================================================================
  786. overloaded stuff with owner =
  787. =======================================================================================================================================
  788. */
  789. // malloc
  790. void* malloc( size_t size, const char* file, int line, const char* func )
  791. {
  792. ++mem::malloc_called_num;
  793. mem::mblock_owner_t owner = {file, line, func};
  794. return mem::Malloc( size, &owner );
  795. }
  796. // realloc
  797. void* realloc( void* p, size_t size, const char* file, int line, const char* func )
  798. {
  799. ++mem::realloc_called_num;
  800. mem::mblock_owner_t owner = {file, line, func};
  801. return mem::Realloc( p, size, &owner );
  802. }
  803. // calloc
  804. void* calloc( size_t num, size_t size, const char* file, int line, const char* func )
  805. {
  806. ++mem::calloc_called_num;
  807. mem::mblock_owner_t owner = {file, line, func};
  808. return mem::Calloc( num, size, &owner );
  809. }
  810. // free
  811. void free( void* p, const char* file, int line, const char* func )
  812. {
  813. ++mem::free_called_num;
  814. mem::mblock_owner_t owner = {file, line, func};
  815. mem::Free( p, &owner );
  816. }
  817. // new
  818. void* operator new( size_t size, const char* file, int line, const char* func )
  819. {
  820. ++mem::new_called_num;
  821. mem::mblock_owner_t owner = {file, line, func};
  822. return mem::Malloc( size, &owner );
  823. }
  824. // new[]
  825. void* operator new[]( size_t size, const char* file, int line, const char* func )
  826. {
  827. ++mem::new_called_num;
  828. mem::mblock_owner_t owner = {file, line, func};
  829. return mem::Malloc( size, &owner );
  830. }
  831. // delete
  832. void operator delete( void* p, const char* file, int line, const char* func )
  833. {
  834. ++mem::delete_called_num;
  835. mem::mblock_owner_t owner = {file, line, func};
  836. mem::Free( p, &owner );
  837. }
  838. // delete []
  839. void operator delete[]( void* p, const char* file, int line, const char* func )
  840. {
  841. ++mem::delete_called_num;
  842. mem::mblock_owner_t owner = {file, line, func};
  843. mem::Free( p, &owner );
  844. }
  845. #endif // _USE_MEM_MANAGER_