1 /*****************************************************************************
3 Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *****************************************************************************/
19 /********************************************************************//**
20 @file include/mem0mem.ic
23 Created 6/8/1994 Heikki Tuuri
24 *************************************************************************/
27 #ifndef UNIV_HOTBACKUP
28 # include "mem0pool.h"
29 #endif /* !UNIV_HOTBACKUP */
31 /***************************************************************//**
32 Creates a memory heap block where data can be allocated.
33 @return own: memory heap block, NULL if did not succeed (only possible
34 for MEM_HEAP_BTR_SEARCH type heaps) */
37 mem_heap_create_block(
38 /*==================*/
39 mem_heap_t* heap, /*!< in: memory heap or NULL if first block
41 ulint n, /*!< in: number of bytes needed for user data */
42 ulint type, /*!< in: type of heap: MEM_HEAP_DYNAMIC or
44 const char* file_name,/*!< in: file name where created */
45 ulint line); /*!< in: line where created */
46 /******************************************************************//**
47 Frees a block from a memory heap. */
52 mem_heap_t* heap, /*!< in: heap */
53 mem_block_t* block); /*!< in: block to free */
54 #ifndef UNIV_HOTBACKUP
55 /******************************************************************//**
56 Frees the free_block field from a memory heap. */
59 mem_heap_free_block_free(
60 /*=====================*/
61 mem_heap_t* heap); /*!< in: heap */
62 #endif /* !UNIV_HOTBACKUP */
63 /***************************************************************//**
64 Adds a new block to a memory heap.
65 @return created block, NULL if did not succeed (only possible for
66 MEM_HEAP_BTR_SEARCH type heaps) */
71 mem_heap_t* heap, /*!< in: memory heap */
72 ulint n); /*!< in: number of bytes user needs */
76 mem_block_set_len(mem_block_t* block, ulint len)
85 mem_block_get_len(mem_block_t* block)
92 mem_block_set_type(mem_block_t* block, ulint type)
94 ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
95 || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
102 mem_block_get_type(mem_block_t* block)
109 mem_block_set_free(mem_block_t* block, ulint free)
112 ut_ad(free <= mem_block_get_len(block));
119 mem_block_get_free(mem_block_t* block)
126 mem_block_set_start(mem_block_t* block, ulint start)
130 block->start = start;
135 mem_block_get_start(mem_block_t* block)
137 return(block->start);
140 /***************************************************************//**
141 Allocates and zero-fills n bytes of memory from a memory heap.
142 @return allocated, zero-filled storage */
147 mem_heap_t* heap, /*!< in: memory heap */
148 ulint n) /*!< in: number of bytes; if the heap is allowed
149 to grow into the buffer pool, this must be
150 <= MEM_MAX_ALLOC_IN_BUF */
153 ut_ad(!(heap->type & MEM_HEAP_BTR_SEARCH));
154 return(memset(mem_heap_alloc(heap, n), 0, n));
157 /***************************************************************//**
158 Allocates n bytes of memory from a memory heap.
159 @return allocated storage, NULL if did not succeed (only possible for
160 MEM_HEAP_BTR_SEARCH type heaps) */
165 mem_heap_t* heap, /*!< in: memory heap */
166 ulint n) /*!< in: number of bytes; if the heap is allowed
167 to grow into the buffer pool, this must be
168 <= MEM_MAX_ALLOC_IN_BUF */
174 ut_ad(mem_heap_check(heap));
176 block = UT_LIST_GET_LAST(heap->base);
178 ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF));
180 /* Check if there is enough space in block. If not, create a new
183 if (mem_block_get_len(block)
184 < mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) {
186 block = mem_heap_add_block(heap, n);
194 free = mem_block_get_free(block);
196 buf = (byte*)block + free;
198 mem_block_set_free(block, free + MEM_SPACE_NEEDED(n));
200 #ifdef UNIV_MEM_DEBUG
202 n + MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE);
204 /* In the debug version write debugging info to the field */
205 mem_field_init((byte*)buf, n);
207 /* Advance buf to point at the storage which will be given to the
209 buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
212 UNIV_MEM_ALLOC(buf, n);
216 /*****************************************************************//**
217 Returns a pointer to the heap top.
218 @return pointer to the heap top */
221 mem_heap_get_heap_top(
222 /*==================*/
223 mem_heap_t* heap) /*!< in: memory heap */
228 ut_ad(mem_heap_check(heap));
230 block = UT_LIST_GET_LAST(heap->base);
232 buf = (byte*)block + mem_block_get_free(block);
237 /*****************************************************************//**
238 Frees the space in a memory heap exceeding the pointer given. The
239 pointer must have been acquired from mem_heap_get_heap_top. The first
240 memory block of the heap is not freed. */
243 mem_heap_free_heap_top(
244 /*===================*/
245 mem_heap_t* heap, /*!< in: heap from which to free */
246 byte* old_top)/*!< in: pointer to old top of heap */
249 mem_block_t* prev_block;
250 #ifdef UNIV_MEM_DEBUG
256 ut_ad(mem_heap_check(heap));
258 #ifdef UNIV_MEM_DEBUG
260 /* Validate the heap and get its total allocated size */
261 mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
265 /* Get the size below top pointer */
266 mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
272 block = UT_LIST_GET_LAST(heap->base);
274 while (block != NULL) {
275 if (((byte*)block + mem_block_get_free(block) >= old_top)
276 && ((byte*)block <= old_top)) {
277 /* Found the right block */
282 /* Store prev_block value before freeing the current block
283 (the current block will be erased in freeing) */
285 prev_block = UT_LIST_GET_PREV(list, block);
287 mem_heap_block_free(heap, block);
294 /* Set the free field of block */
295 mem_block_set_free(block, old_top - (byte*)block);
297 #ifdef UNIV_MEM_DEBUG
298 ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
300 /* In the debug version erase block from top up */
301 mem_erase_buf(old_top, (byte*)block + block->len - old_top);
303 /* Update allocated memory count */
304 mutex_enter(&mem_hash_mutex);
305 mem_current_allocated_memory -= (total_size - size);
306 mutex_exit(&mem_hash_mutex);
307 #else /* UNIV_MEM_DEBUG */
308 UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top);
309 #endif /* UNIV_MEM_DEBUG */
310 UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top);
312 /* If free == start, we may free the block if it is not the first
315 if ((heap != block) && (mem_block_get_free(block)
316 == mem_block_get_start(block))) {
317 mem_heap_block_free(heap, block);
321 /*****************************************************************//**
322 Empties a memory heap. The first memory block of the heap is not freed. */
327 mem_heap_t* heap) /*!< in: heap to empty */
329 mem_heap_free_heap_top(heap, (byte*)heap + mem_block_get_start(heap));
330 #ifndef UNIV_HOTBACKUP
331 if (heap->free_block) {
332 mem_heap_free_block_free(heap);
334 #endif /* !UNIV_HOTBACKUP */
337 /*****************************************************************//**
338 Returns a pointer to the topmost element in a memory heap. The size of the
339 element must be given.
340 @return pointer to the topmost element */
345 mem_heap_t* heap, /*!< in: memory heap */
346 ulint n) /*!< in: size of the topmost element */
351 ut_ad(mem_heap_check(heap));
353 block = UT_LIST_GET_LAST(heap->base);
355 buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
357 #ifdef UNIV_MEM_DEBUG
358 ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
360 /* In the debug version, advance buf to point at the storage which
361 was given to the caller in the allocation*/
363 buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
365 /* Check that the field lengths agree */
366 ut_ad(n == (ulint)mem_field_header_get_len(buf));
372 /*****************************************************************//**
373 Frees the topmost element in a memory heap. The size of the element must be
379 mem_heap_t* heap, /*!< in: memory heap */
380 ulint n) /*!< in: size of the topmost element */
384 ut_ad(mem_heap_check(heap));
386 block = UT_LIST_GET_LAST(heap->base);
388 /* Subtract the free field of block */
389 mem_block_set_free(block, mem_block_get_free(block)
390 - MEM_SPACE_NEEDED(n));
391 UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
392 #ifdef UNIV_MEM_DEBUG
394 ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
396 /* In the debug version check the consistency, and erase field */
397 mem_field_erase((byte*)block + mem_block_get_free(block), n);
400 /* If free == start, we may free the block if it is not the first
403 if ((heap != block) && (mem_block_get_free(block)
404 == mem_block_get_start(block))) {
405 mem_heap_block_free(heap, block);
407 /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
408 subsequent invocation of mem_heap_free_top().
409 Originally, this was UNIV_MEM_FREE(), to catch writes
411 UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
415 /*****************************************************************//**
416 NOTE: Use the corresponding macros instead of this function. Creates a
417 memory heap. For debugging purposes, takes also the file name and line as
419 @return own: memory heap, NULL if did not succeed (only possible for
420 MEM_HEAP_BTR_SEARCH type heaps) */
423 mem_heap_create_func(
424 /*=================*/
425 ulint n, /*!< in: desired start block size,
426 this means that a single user buffer
427 of size n will fit in the block,
428 0 creates a default size block */
429 ulint type, /*!< in: heap type */
430 const char* file_name, /*!< in: file name where created */
431 ulint line) /*!< in: line where created */
436 n = MEM_BLOCK_START_SIZE;
439 block = mem_heap_create_block(NULL, n, type, file_name, line);
446 UT_LIST_INIT(block->base);
448 /* Add the created block itself as the first block in the list */
449 UT_LIST_ADD_FIRST(list, block->base, block);
451 #ifdef UNIV_MEM_DEBUG
453 mem_hash_insert(block, file_name, line);
460 /*****************************************************************//**
461 NOTE: Use the corresponding macro instead of this function. Frees the space
462 occupied by a memory heap. In the debug version erases the heap memory
468 mem_heap_t* heap, /*!< in, own: heap to be freed */
469 const char* file_name __attribute__((unused)),
470 /*!< in: file name where freed */
471 ulint line __attribute__((unused)))
474 mem_block_t* prev_block;
476 ut_ad(mem_heap_check(heap));
478 block = UT_LIST_GET_LAST(heap->base);
480 #ifdef UNIV_MEM_DEBUG
482 /* In the debug version remove the heap from the hash table of heaps
483 and check its consistency */
485 mem_hash_remove(heap, file_name, line);
488 #ifndef UNIV_HOTBACKUP
489 if (heap->free_block) {
490 mem_heap_free_block_free(heap);
492 #endif /* !UNIV_HOTBACKUP */
494 while (block != NULL) {
495 /* Store the contents of info before freeing current block
496 (it is erased in freeing) */
498 prev_block = UT_LIST_GET_PREV(list, block);
500 mem_heap_block_free(heap, block);
506 /***************************************************************//**
507 NOTE: Use the corresponding macro instead of this function.
508 Allocates a single buffer of memory from the dynamic memory of
509 the C compiler. Is like malloc of C. The buffer must be freed
511 @return own: free storage */
516 ulint n, /*!< in: desired number of bytes */
517 ulint* size, /*!< out: allocated size in bytes,
519 const char* file_name, /*!< in: file name where created */
520 ulint line) /*!< in: line where created */
525 heap = mem_heap_create_func(n, MEM_HEAP_DYNAMIC, file_name, line);
527 /* Note that as we created the first block in the heap big enough
528 for the buffer requested by the caller, the buffer will be in the
529 first block and thus we can calculate the pointer to the heap from
530 the pointer to the buffer when we free the memory buffer. */
532 if (UNIV_LIKELY_NULL(size)) {
533 /* Adjust the allocation to the actual size of the
535 ulint m = mem_block_get_len(heap)
536 - mem_block_get_free(heap);
537 #ifdef UNIV_MEM_DEBUG
538 m -= MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE;
539 #endif /* UNIV_MEM_DEBUG */
544 buf = mem_heap_alloc(heap, n);
546 ut_a((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
547 - MEM_FIELD_HEADER_SIZE);
551 /***************************************************************//**
552 NOTE: Use the corresponding macro instead of this function. Frees a single
553 buffer of storage from the dynamic memory of the C compiler. Similar to the
559 void* ptr, /*!< in, own: buffer to be freed */
560 const char* file_name, /*!< in: file name where created */
561 ulint line) /*!< in: line where created */
565 heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
566 - MEM_FIELD_HEADER_SIZE);
567 mem_heap_free_func(heap, file_name, line);
570 /*****************************************************************//**
571 Returns the space in bytes occupied by a memory heap. */
576 mem_heap_t* heap) /*!< in: heap */
580 ut_ad(mem_heap_check(heap));
582 size = heap->total_size;
584 #ifndef UNIV_HOTBACKUP
585 if (heap->free_block) {
586 size += UNIV_PAGE_SIZE;
588 #endif /* !UNIV_HOTBACKUP */
593 /**********************************************************************//**
594 Duplicates a NUL-terminated string.
595 @return own: a copy of the string, must be deallocated with mem_free */
600 const char* str) /*!< in: string to be copied */
602 ulint len = strlen(str) + 1;
603 return((char*) memcpy(mem_alloc(len), str, len));
606 /**********************************************************************//**
607 Makes a NUL-terminated copy of a nonterminated string.
608 @return own: a copy of the string, must be deallocated with mem_free */
613 const char* str, /*!< in: string to be copied */
614 ulint len) /*!< in: length of str, in bytes */
616 char* s = (char*) mem_alloc(len + 1);
618 return((char*) memcpy(s, str, len));
621 /**********************************************************************//**
622 Makes a NUL-terminated copy of a nonterminated string,
623 allocated from a memory heap.
624 @return own: a copy of the string */
629 mem_heap_t* heap, /*!< in: memory heap where string is allocated */
630 const char* str, /*!< in: string to be copied */
631 ulint len) /*!< in: length of str, in bytes */
633 char* s = (char*) mem_heap_alloc(heap, len + 1);
635 return((char*) memcpy(s, str, len));