mem0mem.ic
Upload User: tsgydb
Upload Date: 2007-04-14
Package Size: 10674k
Code Size: 14k
Category:

MySQL

Development Platform:

Visual C++

  1. /************************************************************************
  2. The memory management
  3. (c) 1994, 1995 Innobase Oy
  4. Created 6/8/1994 Heikki Tuuri
  5. *************************************************************************/
  6. #include "mem0dbg.ic"
  7. #include "mem0pool.h"
  8. /*******************************************************************
  9. Creates a memory heap block where data can be allocated. */
  10. mem_block_t*
  11. mem_heap_create_block(
  12. /*==================*/
  13. /* out, own: memory heap block, NULL if did not
  14. succeed */
  15. mem_heap_t* heap,/* in: memory heap or NULL if first block should
  16. be created */
  17. ulint n, /* in: number of bytes needed for user data, or
  18. if init_block is not NULL, its size in bytes */
  19. void* init_block, /* in: init block in fast create, type must be
  20. MEM_HEAP_DYNAMIC */
  21. ulint  type); /* in: type of heap: MEM_HEAP_DYNAMIC or
  22. MEM_HEAP_BUFFER */
  23. /**********************************************************************
  24. Frees a block from a memory heap. */
  25. void
  26. mem_heap_block_free(
  27. /*================*/
  28. mem_heap_t* heap, /* in: heap */
  29. mem_block_t* block); /* in: block to free */
  30. /**********************************************************************
  31. Frees the free_block field from a memory heap. */
  32. void
  33. mem_heap_free_block_free(
  34. /*=====================*/
  35. mem_heap_t* heap); /* in: heap */
  36. /*******************************************************************
  37. Adds a new block to a memory heap. */
  38. mem_block_t*
  39. mem_heap_add_block(
  40. /*===============*/
  41. /* out: created block, NULL if did not
  42. succeed */
  43. mem_heap_t*  heap, /* in: memory heap */
  44. ulint n); /* in: number of bytes user needs */
  45. UNIV_INLINE
  46. void
  47. mem_block_set_len(mem_block_t* block, ulint len)
  48. {
  49. ut_ad(len > 0);
  50. block->len = len;
  51. }
  52. UNIV_INLINE
  53. ulint
  54. mem_block_get_len(mem_block_t* block)
  55. {
  56. return(block->len);
  57. }
  58. UNIV_INLINE
  59. void
  60. mem_block_set_type(mem_block_t* block, ulint type)
  61. {
  62. ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
  63. || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
  64. block->type = type;
  65. }
  66. UNIV_INLINE
  67. ulint
  68. mem_block_get_type(mem_block_t* block)
  69. {
  70. return(block->type);
  71. }
  72. UNIV_INLINE
  73. void
  74. mem_block_set_free(mem_block_t* block, ulint free)
  75. {
  76. ut_ad(free > 0);
  77. ut_ad(free <= mem_block_get_len(block));
  78. block->free = free;
  79. }
  80. UNIV_INLINE
  81. ulint
  82. mem_block_get_free(mem_block_t* block)
  83. {
  84. return(block->free);
  85. }
  86. UNIV_INLINE
  87. void
  88. mem_block_set_start(mem_block_t* block, ulint start)
  89. {
  90. ut_ad(start > 0);
  91. block->start = start;
  92. }
  93. UNIV_INLINE
  94. ulint
  95. mem_block_get_start(mem_block_t* block)
  96. {
  97. return(block->start);
  98. }
  99. /*******************************************************************
  100. Allocates n bytes of memory from a memory heap. */
  101. UNIV_INLINE
  102. void*
  103. mem_heap_alloc(
  104. /*===========*/
  105. /* out: allocated storage */
  106. mem_heap_t* heap,  /* in: memory heap */
  107. ulint           n)      /* in: number of bytes; if the heap is allowed
  108. to grow into the buffer pool, this must be
  109. <= MEM_MAX_ALLOC_IN_BUF */
  110. {
  111. mem_block_t* block;
  112. void* buf;
  113. ulint free;
  114. ut_ad(mem_heap_check(heap));
  115. block = UT_LIST_GET_LAST(heap->base);
  116. ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF));
  117. /* Check if there is enough space in block. If not, create a new
  118. block to the heap */
  119. if (mem_block_get_len(block) 
  120. < mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) {
  121. block = mem_heap_add_block(heap, n);
  122. if (block == NULL) {
  123. return(NULL);
  124. }
  125. }
  126. free = mem_block_get_free(block);
  127. buf = (byte*)block + free;
  128. mem_block_set_free(block, free + MEM_SPACE_NEEDED(n));
  129. #ifdef UNIV_MEM_DEBUG
  130. /* In the debug version write debugging info to the field */
  131. mem_field_init((byte*)buf, n);
  132. /* Advance buf to point at the storage which will be given to the
  133. caller */
  134. buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
  135. #endif
  136. return(buf);
  137. }
  138. /*********************************************************************
  139. Returns a pointer to the heap top. */
  140. UNIV_INLINE
  141. byte*
  142. mem_heap_get_heap_top(
  143. /*==================*/     
  144. /* out: pointer to the heap top */
  145. mem_heap_t*    heap)  /* in: memory heap */
  146. {
  147. mem_block_t* block;
  148. byte* buf;
  149. ut_ad(mem_heap_check(heap));
  150. block = UT_LIST_GET_LAST(heap->base);
  151. buf = (byte*)block + mem_block_get_free(block);
  152. return(buf);
  153. /*********************************************************************
  154. Frees the space in a memory heap exceeding the pointer given. The
  155. pointer must have been acquired from mem_heap_get_heap_top. The first
  156. memory block of the heap is not freed. */
  157. UNIV_INLINE
  158. void
  159. mem_heap_free_heap_top(
  160. /*===================*/
  161. mem_heap_t*    heap, /* in: heap from which to free */
  162. byte* old_top)/* in: pointer to old top of heap */
  163. {
  164. mem_block_t* block;
  165. mem_block_t* prev_block;
  166. #ifdef UNIV_MEM_DEBUG
  167. ibool error;
  168. ulint total_size;
  169. ulint size;
  170. #endif
  171. ut_ad(mem_heap_check(heap));
  172. #ifdef UNIV_MEM_DEBUG
  173. /* Validate the heap and get its total allocated size */
  174. mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
  175. NULL, NULL);
  176. ut_a(!error);
  177. /* Get the size below top pointer */
  178. mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
  179. NULL);
  180. ut_a(!error);
  181. #endif
  182. block = UT_LIST_GET_LAST(heap->base);
  183. while (block != NULL) {
  184. if (((byte*)block + mem_block_get_free(block) >= old_top)
  185. && ((byte*)block <= old_top)) {
  186. /* Found the right block */
  187. break;
  188. }
  189.  
  190. /* Store prev_block value before freeing the current block
  191. (the current block will be erased in freeing) */
  192. prev_block = UT_LIST_GET_PREV(list, block);
  193. mem_heap_block_free(heap, block);
  194. block = prev_block;
  195. }
  196. ut_ad(block);
  197. /* Set the free field of block */
  198. mem_block_set_free(block, old_top - (byte*)block); 
  199. #ifdef UNIV_MEM_DEBUG
  200. ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
  201. /* In the debug version erase block from top up */
  202. mem_erase_buf(old_top, (byte*)block + block->len - old_top);
  203. /* Update allocated memory count */
  204. mutex_enter(&mem_hash_mutex);
  205. mem_current_allocated_memory -= (total_size - size);
  206. mutex_exit(&mem_hash_mutex);
  207. #endif
  208. /* If free == start, we may free the block if it is not the first
  209. one */
  210. if ((heap != block) && (mem_block_get_free(block) == 
  211.    mem_block_get_start(block))) {
  212. mem_heap_block_free(heap, block);
  213. }
  214. }
  215. /*********************************************************************
  216. Empties a memory heap. The first memory block of the heap is not freed. */
  217. UNIV_INLINE
  218. void
  219. mem_heap_empty(
  220. /*===========*/
  221. mem_heap_t*    heap) /* in: heap to empty */
  222. {
  223. mem_heap_free_heap_top(heap, (byte*)heap + mem_block_get_start(heap));
  224. if (heap->free_block) {
  225. mem_heap_free_block_free(heap);
  226. }
  227. }
  228. /*********************************************************************
  229. Returns a pointer to the topmost element in a memory heap. The size of the
  230. element must be given. */
  231. UNIV_INLINE
  232. void*
  233. mem_heap_get_top(
  234. /*=============*/     
  235. /* out: pointer to the topmost element */
  236. mem_heap_t*    heap,  /* in: memory heap */
  237. ulint           n)      /* in: size of the topmost element */
  238. {
  239. mem_block_t* block;
  240. void* buf;
  241. ut_ad(mem_heap_check(heap));
  242. block = UT_LIST_GET_LAST(heap->base);
  243. buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
  244. #ifdef UNIV_MEM_DEBUG
  245. ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
  246. /* In the debug version, advance buf to point at the storage which
  247. was given to the caller in the allocation*/
  248. buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
  249. /* Check that the field lengths agree */
  250. ut_ad(n == (ulint)mem_field_header_get_len(buf));
  251. #endif
  252. return(buf);
  253. /*********************************************************************
  254. Frees the topmost element in a memory heap. The size of the element must be
  255. given. */
  256. UNIV_INLINE
  257. void
  258. mem_heap_free_top(
  259. /*==============*/    
  260. mem_heap_t*    heap,  /* in: memory heap */
  261. ulint           n)      /* in: size of the topmost element */
  262. {
  263. mem_block_t* block;
  264. ut_ad(mem_heap_check(heap));
  265. block = UT_LIST_GET_LAST(heap->base);
  266. /* Subtract the free field of block */
  267. mem_block_set_free(block, mem_block_get_free(block)
  268. - MEM_SPACE_NEEDED(n));
  269. #ifdef UNIV_MEM_DEBUG
  270. ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
  271. /* In the debug version check the consistency, and erase field */
  272. mem_field_erase((byte*)block + mem_block_get_free(block), n);
  273. #endif
  274. /* If free == start, we may free the block if it is not the first
  275. one */
  276. if ((heap != block) && (mem_block_get_free(block) == 
  277.    mem_block_get_start(block))) {
  278. mem_heap_block_free(heap, block);
  279. }
  280. }
  281. /*********************************************************************
  282. NOTE: Use the corresponding macros instead of this function. Creates a
  283. memory heap which allocates memory from dynamic space. For debugging
  284. purposes, takes also the file name and line as argument in the debug
  285. version. */
  286. UNIV_INLINE
  287. mem_heap_t*
  288. mem_heap_create_func(
  289. /*=================*/
  290. /* out, own: memory heap */
  291. ulint n, /* in: desired start block size,
  292. this means that a single user buffer
  293. of size n will fit in the block, 
  294. 0 creates a default size block;
  295. if init_block is not NULL, n tells
  296. its size in bytes */
  297. void* init_block, /* in: if very fast creation is
  298. wanted, the caller can reserve some
  299. memory from its stack, for example,
  300. and pass it as the the initial block
  301. to the heap: then no OS call of malloc
  302. is needed at the creation. CAUTION:
  303. the caller must make sure the initial
  304. block is not unintentionally erased
  305. (if allocated in the stack), before
  306. the memory heap is explicitly freed. */
  307. ulint type /* in: MEM_HEAP_DYNAMIC, or MEM_HEAP_BUFFER
  308. possibly ORed to MEM_HEAP_BTR_SEARCH */
  309. #ifdef UNIV_MEM_DEBUG
  310. ,char*  file_name, /* in: file name where created */
  311. ulint line /* in: line where created */
  312. #endif
  313. )
  314. {
  315. mem_block_t*   block; 
  316. if (n > 0) {
  317. block = mem_heap_create_block(NULL, n, init_block, type);
  318. } else {
  319. block = mem_heap_create_block(NULL, MEM_BLOCK_START_SIZE, 
  320. init_block, type);
  321. }
  322. ut_ad(block);
  323. UT_LIST_INIT(block->base);
  324. /* Add the created block itself as the first block in the list */
  325. UT_LIST_ADD_FIRST(list, block->base, block);
  326. #ifdef UNIV_MEM_DEBUG
  327. if (block == NULL) {
  328. return(block);
  329. }
  330. mem_hash_insert(block, file_name, line);
  331. #endif
  332. return(block);
  333. }
  334. /*********************************************************************
  335. NOTE: Use the corresponding macro instead of this function. Frees the space
  336. occupied by a memory heap. In the debug version erases the heap memory
  337. blocks. */
  338. UNIV_INLINE
  339. void
  340. mem_heap_free_func(
  341. /*===============*/
  342. mem_heap_t*    heap   /* in, own: heap to be freed */
  343. #ifdef UNIV_MEM_DEBUG
  344. ,char*   file_name, /* in: file name where freed */
  345. ulint     line /* in: line where freed */
  346. #endif
  347. )
  348. {
  349. mem_block_t* block;
  350. mem_block_t* prev_block;
  351. ut_ad(mem_heap_check(heap));
  352. block = UT_LIST_GET_LAST(heap->base);
  353. #ifdef UNIV_MEM_DEBUG
  354. /* In the debug version remove the heap from the hash table of heaps
  355. and check its consistency */
  356. mem_hash_remove(heap, file_name, line); 
  357. #endif
  358. if (heap->free_block) {
  359. mem_heap_free_block_free(heap);
  360. }
  361. while (block != NULL) { 
  362. /* Store the contents of info before freeing current block
  363. (it is erased in freeing) */
  364. prev_block = UT_LIST_GET_PREV(list, block);
  365. mem_heap_block_free(heap, block);
  366. block = prev_block;
  367. }
  368. }
  369. /*******************************************************************
  370. NOTE: Use the corresponding macro instead of this function.
  371. Allocates a single buffer of memory from the dynamic memory of
  372. the C compiler. Is like malloc of C. The buffer must be freed 
  373. with mem_free. */
  374. UNIV_INLINE
  375. void*
  376. mem_alloc_func(
  377. /*===========*/
  378. /* out, own: free storage, NULL if did not
  379. succeed */
  380. ulint   n               /* in: desired number of bytes */
  381. #ifdef UNIV_MEM_DEBUG
  382. ,char*  file_name, /* in: file name where created */
  383. ulint   line /* in: line where created */
  384. #endif
  385. )
  386. {
  387. #ifndef UNIV_MEM_DEBUG
  388. return(mem_area_alloc(n, mem_comm_pool));
  389. #else
  390. mem_heap_t*    heap; 
  391. void*           buf;
  392. heap = mem_heap_create_func(n, NULL, MEM_HEAP_DYNAMIC, file_name,
  393. line);
  394. if (heap == NULL) {
  395. return(NULL);
  396. }
  397. /* Note that as we created the first block in the heap big enough
  398. for the buffer requested by the caller, the buffer will be in the
  399. first block and thus we can calculate the pointer to the heap from
  400. the pointer to the buffer when we free the memory buffer. */
  401. buf = mem_heap_alloc(heap, n);
  402. ut_ad((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
  403. - MEM_FIELD_HEADER_SIZE);
  404. return(buf);
  405. #endif
  406. }
  407. /*******************************************************************
  408. NOTE: Use the corresponding macro instead of this function. Frees a single
  409. buffer of storage from the dynamic memory of the C compiler. Similar to the
  410. free of C. */
  411. UNIV_INLINE
  412. void
  413. mem_free_func(
  414. /*==========*/
  415. void*   ptr             /* in, own: buffer to be freed */
  416. #ifdef UNIV_MEM_DEBUG
  417. ,char*  file_name,      /* in: file name where created */
  418. ulint   line            /* in: line where created */
  419. #endif
  420. )
  421. {
  422. #ifndef UNIV_MEM_DEBUG
  423. mem_area_free(ptr, mem_comm_pool);
  424.        
  425. #else
  426. mem_heap_t*   heap; 
  427. heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
  428.   - MEM_FIELD_HEADER_SIZE);
  429. mem_heap_free_func(heap, file_name, line);
  430. #endif
  431. }
  432. /*********************************************************************
  433. Returns the space in bytes occupied by a memory heap. */
  434. UNIV_INLINE
  435. ulint
  436. mem_heap_get_size(
  437. /*==============*/
  438. mem_heap_t*   heap)   /* in: heap */
  439. {
  440. mem_block_t*   block;
  441. ulint           size = 0;
  442. ut_ad(mem_heap_check(heap));
  443. block = heap;
  444. while (block != NULL) { 
  445. size += mem_block_get_len(block);
  446. block = UT_LIST_GET_NEXT(list, block);
  447. }
  448. if (heap->free_block) {
  449. size += UNIV_PAGE_SIZE;
  450. }
  451. return(size);
  452. }
  453. /*******************************************************************
  454. Implements realloc. */
  455. UNIV_INLINE
  456. void*
  457. mem_realloc(
  458. /*========*/
  459. /* out, own: free storage, NULL if did not succeed */
  460. void* buf, /* in: pointer to an old buffer */
  461. ulint   n) /* in: desired number of bytes */
  462. {
  463. mem_free(buf);
  464. return(mem_alloc(n));
  465. }