summaryrefslogtreecommitdiff
path: root/storage/innobase/mem/mem0mem.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/mem/mem0mem.cc')
-rw-r--r--storage/innobase/mem/mem0mem.cc231
1 files changed, 64 insertions, 167 deletions
diff --git a/storage/innobase/mem/mem0mem.cc b/storage/innobase/mem/mem0mem.cc
index e066aff5b30..41292ccf842 100644
--- a/storage/innobase/mem/mem0mem.cc
+++ b/storage/innobase/mem/mem0mem.cc
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -23,6 +23,8 @@ The memory management
Created 6/9/1994 Heikki Tuuri
*************************************************************************/
+#include "ha_prototypes.h"
+
#include "mem0mem.h"
#ifdef UNIV_NONINL
#include "mem0mem.ic"
@@ -30,91 +32,23 @@ Created 6/9/1994 Heikki Tuuri
#include "buf0buf.h"
#include "srv0srv.h"
-#include "mem0dbg.cc"
#include <stdarg.h>
-/*
- THE MEMORY MANAGEMENT
- =====================
-
-The basic element of the memory management is called a memory
-heap. A memory heap is conceptually a
-stack from which memory can be allocated. The stack may grow infinitely.
-The top element of the stack may be freed, or
-the whole stack can be freed at one time. The advantage of the
-memory heap concept is that we can avoid using the malloc and free
-functions of C which are quite expensive, for example, on the Solaris + GCC
-system (50 MHz Sparc, 1993) the pair takes 3 microseconds,
-on Win NT + 100MHz Pentium, 2.5 microseconds.
-When we use a memory heap,
-we can allocate larger blocks of memory at a time and thus
-reduce overhead. Slightly more efficient the method is when we
-allocate the memory from the index page buffer pool, as we can
-claim a new page fast. This is called buffer allocation.
-When we allocate the memory from the dynamic memory of the
-C environment, that is called dynamic allocation.
-
-The default way of operation of the memory heap is the following.
-First, when the heap is created, an initial block of memory is
-allocated. In dynamic allocation this may be about 50 bytes.
-If more space is needed, additional blocks are allocated
-and they are put into a linked list.
-After the initial block, each allocated block is twice the size of the
-previous, until a threshold is attained, after which the sizes
-of the blocks stay the same. An exception is, of course, the case
-where the caller requests a memory buffer whose size is
-bigger than the threshold. In that case a block big enough must
-be allocated.
-
-The heap is physically arranged so that if the current block
-becomes full, a new block is allocated and always inserted in the
-chain of blocks as the last block.
-
-In the debug version of the memory management, all the allocated
-heaps are kept in a list (which is implemented as a hash table).
-Thus we can notice if the caller tries to free an already freed
-heap. In addition, each buffer given to the caller contains
-start field at the start and a trailer field at the end of the buffer.
-
-The start field has the following content:
-A. sizeof(ulint) bytes of field length (in the standard byte order)
-B. sizeof(ulint) bytes of check field (a random number)
-
-The trailer field contains:
-A. sizeof(ulint) bytes of check field (the same random number as at the start)
-
-Thus we can notice if something has been copied over the
-borders of the buffer, which is illegal.
-The memory in the buffers is initialized to a random byte sequence.
-After freeing, all the blocks in the heap are set to random bytes
-to help us discover errors which result from the use of
-buffers in an already freed heap. */
-
-#ifdef MEM_PERIODIC_CHECK
-
-ibool mem_block_list_inited;
-/* List of all mem blocks allocated; protected by the mem_comm_pool mutex */
-UT_LIST_BASE_NODE_T(mem_block_t) mem_block_list;
-
-#endif
-
-/**********************************************************************//**
-Duplicates a NUL-terminated string, allocated from a memory heap.
-@return own: a copy of the string */
-UNIV_INTERN
+/** Duplicates a NUL-terminated string, allocated from a memory heap.
+@param[in] heap, memory heap where string is allocated
+@param[in] str) string to be copied
+@return own: a copy of the string */
char*
mem_heap_strdup(
-/*============*/
- mem_heap_t* heap, /*!< in: memory heap where string is allocated */
- const char* str) /*!< in: string to be copied */
+ mem_heap_t* heap,
+ const char* str)
{
return(static_cast<char*>(mem_heap_dup(heap, str, strlen(str) + 1)));
}
/**********************************************************************//**
Duplicate a block of data, allocated from a memory heap.
-@return own: a copy of the data */
-UNIV_INTERN
+@return own: a copy of the data */
void*
mem_heap_dup(
/*=========*/
@@ -127,8 +61,7 @@ mem_heap_dup(
/**********************************************************************//**
Concatenate two strings and return the result, using a memory heap.
-@return own: the result */
-UNIV_INTERN
+@return own: the result */
char*
mem_heap_strcat(
/*============*/
@@ -153,7 +86,7 @@ mem_heap_strcat(
/****************************************************************//**
Helper function for mem_heap_printf.
-@return length of formatted string, including terminating NUL */
+@return length of formatted string, including terminating NUL */
static
ulint
mem_heap_printf_low(
@@ -265,8 +198,7 @@ A simple sprintf replacement that dynamically allocates the space for the
formatted string from the given heap. This supports a very limited set of
the printf syntax: types 's' and 'u' and length modifier 'l' (which is
required for the 'u' type).
-@return heap-allocated formatted string */
-UNIV_INTERN
+@return heap-allocated formatted string */
char*
mem_heap_printf(
/*============*/
@@ -293,11 +225,45 @@ mem_heap_printf(
return(str);
}
+#ifdef UNIV_DEBUG
+/** Validates the contents of a memory heap.
+Checks a memory heap for consistency, prints the contents if any error
+is detected. A fatal error is logged if an error is detected.
+@param[in] heap Memory heap to validate. */
+void
+mem_heap_validate(
+ const mem_heap_t* heap)
+{
+ ulint size = 0;
+
+ for (const mem_block_t* block = heap;
+ block != NULL;
+ block = UT_LIST_GET_NEXT(list, block)) {
+
+ mem_block_validate(block);
+
+ switch (block->type) {
+ case MEM_HEAP_DYNAMIC:
+ break;
+ case MEM_HEAP_BUFFER:
+ case MEM_HEAP_BUFFER | MEM_HEAP_BTR_SEARCH:
+ ut_ad(block->len <= UNIV_PAGE_SIZE);
+ break;
+ default:
+ ut_error;
+ }
+
+ size += block->len;
+ }
+
+ ut_ad(size == heap->total_size);
+}
+#endif /* UNIV_DEBUG */
+
/***************************************************************//**
Creates a memory heap block where data can be allocated.
@return own: memory heap block, NULL if did not succeed (only possible
for MEM_HEAP_BTR_SEARCH type heaps) */
-UNIV_INTERN
mem_block_t*
mem_heap_create_block_func(
/*=======================*/
@@ -320,8 +286,9 @@ mem_heap_create_block_func(
ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
|| (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
- if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) {
- mem_analyze_corruption(heap);
+ if (heap != NULL) {
+ mem_block_validate(heap);
+ ut_d(mem_heap_validate(heap));
}
/* In dynamic allocation, calculate the size: block header + data. */
@@ -332,8 +299,7 @@ mem_heap_create_block_func(
ut_ad(type == MEM_HEAP_DYNAMIC || n <= MEM_MAX_ALLOC_IN_BUF);
- block = static_cast<mem_block_t*>(
- mem_area_alloc(&len, mem_comm_pool));
+ block = static_cast<mem_block_t*>(ut_malloc_nokey(len));
} else {
len = UNIV_PAGE_SIZE;
@@ -356,16 +322,16 @@ mem_heap_create_block_func(
block = (mem_block_t*) buf_block->frame;
}
- if(!block) {
- ib_logf(IB_LOG_LEVEL_FATAL,
- " InnoDB: Unable to allocate memory of size %lu.\n",
- len);
+ if (block == NULL) {
+ ib::fatal() << "Unable to allocate memory of size "
+ << len << ".";
}
+
block->buf_block = buf_block;
block->free_block = NULL;
#else /* !UNIV_HOTBACKUP */
len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n);
- block = ut_malloc(len);
+ block = ut_malloc_nokey(len);
ut_ad(block);
#endif /* !UNIV_HOTBACKUP */
@@ -374,18 +340,6 @@ mem_heap_create_block_func(
sizeof(block->file_name)));
ut_d(block->line = line);
-#ifdef MEM_PERIODIC_CHECK
- mutex_enter(&(mem_comm_pool->mutex));
-
- if (!mem_block_list_inited) {
- mem_block_list_inited = TRUE;
- UT_LIST_INIT(mem_block_list);
- }
-
- UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block);
-
- mutex_exit(&(mem_comm_pool->mutex));
-#endif
mem_block_set_len(block, len);
mem_block_set_type(block, type);
mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
@@ -414,7 +368,6 @@ mem_heap_create_block_func(
Adds a new block to a memory heap.
@return created block, NULL if did not succeed (only possible for
MEM_HEAP_BTR_SEARCH type heaps) */
-UNIV_INTERN
mem_block_t*
mem_heap_add_block(
/*===============*/
@@ -425,7 +378,7 @@ mem_heap_add_block(
mem_block_t* new_block;
ulint new_size;
- ut_ad(mem_heap_check(heap));
+ ut_d(mem_block_validate(heap));
block = UT_LIST_GET_LAST(heap->base);
@@ -460,14 +413,13 @@ mem_heap_add_block(
/* Add the new block as the last block */
- UT_LIST_INSERT_AFTER(list, heap->base, block, new_block);
+ UT_LIST_INSERT_AFTER(heap->base, block, new_block);
return(new_block);
}
/******************************************************************//**
Frees a block from a memory heap. */
-UNIV_INTERN
void
mem_heap_block_free(
/*================*/
@@ -482,19 +434,9 @@ mem_heap_block_free(
buf_block = static_cast<buf_block_t*>(block->buf_block);
#endif /* !UNIV_HOTBACKUP */
- if (block->magic_n != MEM_BLOCK_MAGIC_N) {
- mem_analyze_corruption(block);
- }
+ mem_block_validate(block);
- UT_LIST_REMOVE(list, heap->base, block);
-
-#ifdef MEM_PERIODIC_CHECK
- mutex_enter(&(mem_comm_pool->mutex));
-
- UT_LIST_REMOVE(mem_block_list, mem_block_list, block);
-
- mutex_exit(&(mem_comm_pool->mutex));
-#endif
+ UT_LIST_REMOVE(heap->base, block);
ut_ad(heap->total_size >= block->len);
heap->total_size -= block->len;
@@ -503,36 +445,19 @@ mem_heap_block_free(
len = block->len;
block->magic_n = MEM_FREED_BLOCK_MAGIC_N;
-#ifndef UNIV_HOTBACKUP
- if (!srv_use_sys_malloc) {
-#ifdef UNIV_MEM_DEBUG
- /* In the debug version we set the memory to a random
- combination of hex 0xDE and 0xAD. */
-
- mem_erase_buf((byte*) block, len);
-#else /* UNIV_MEM_DEBUG */
- UNIV_MEM_ASSERT_AND_FREE(block, len);
-#endif /* UNIV_MEM_DEBUG */
+ UNIV_MEM_ASSERT_W(block, len);
- }
+#ifndef UNIV_HOTBACKUP
if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) {
ut_ad(!buf_block);
- mem_area_free(block, mem_comm_pool);
+ ut_free(block);
} else {
ut_ad(type & MEM_HEAP_BUFFER);
buf_block_free(buf_block);
}
#else /* !UNIV_HOTBACKUP */
-#ifdef UNIV_MEM_DEBUG
- /* In the debug version we set the memory to a random
- combination of hex 0xDE and 0xAD. */
-
- mem_erase_buf((byte*) block, len);
-#else /* UNIV_MEM_DEBUG */
- UNIV_MEM_ASSERT_AND_FREE(block, len);
-#endif /* UNIV_MEM_DEBUG */
ut_free(block);
#endif /* !UNIV_HOTBACKUP */
}
@@ -540,7 +465,6 @@ mem_heap_block_free(
#ifndef UNIV_HOTBACKUP
/******************************************************************//**
Frees the free_block field from a memory heap. */
-UNIV_INTERN
void
mem_heap_free_block_free(
/*=====================*/
@@ -554,30 +478,3 @@ mem_heap_free_block_free(
}
}
#endif /* !UNIV_HOTBACKUP */
-
-#ifdef MEM_PERIODIC_CHECK
-/******************************************************************//**
-Goes through the list of all allocated mem blocks, checks their magic
-numbers, and reports possible corruption. */
-UNIV_INTERN
-void
-mem_validate_all_blocks(void)
-/*=========================*/
-{
- mem_block_t* block;
-
- mutex_enter(&(mem_comm_pool->mutex));
-
- block = UT_LIST_GET_FIRST(mem_block_list);
-
- while (block) {
- if (block->magic_n != MEM_BLOCK_MAGIC_N) {
- mem_analyze_corruption(block);
- }
-
- block = UT_LIST_GET_NEXT(mem_block_list, block);
- }
-
- mutex_exit(&(mem_comm_pool->mutex));
-}
-#endif