MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mem0mem.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
4 
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.
8 
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.
12 
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 Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /********************************************************************/
26 #include "mem0mem.h"
27 #ifdef UNIV_NONINL
28 #include "mem0mem.ic"
29 #endif
30 
31 #include "buf0buf.h"
32 #include "srv0srv.h"
33 #include "mem0dbg.cc"
34 #include <stdarg.h>
35 
36 /*
37  THE MEMORY MANAGEMENT
38  =====================
39 
40 The basic element of the memory management is called a memory
41 heap. A memory heap is conceptually a
42 stack from which memory can be allocated. The stack may grow infinitely.
43 The top element of the stack may be freed, or
44 the whole stack can be freed at one time. The advantage of the
45 memory heap concept is that we can avoid using the malloc and free
46 functions of C which are quite expensive, for example, on the Solaris + GCC
47 system (50 MHz Sparc, 1993) the pair takes 3 microseconds,
48 on Win NT + 100MHz Pentium, 2.5 microseconds.
49 When we use a memory heap,
50 we can allocate larger blocks of memory at a time and thus
51 reduce overhead. Slightly more efficient the method is when we
52 allocate the memory from the index page buffer pool, as we can
53 claim a new page fast. This is called buffer allocation.
54 When we allocate the memory from the dynamic memory of the
55 C environment, that is called dynamic allocation.
56 
57 The default way of operation of the memory heap is the following.
58 First, when the heap is created, an initial block of memory is
59 allocated. In dynamic allocation this may be about 50 bytes.
60 If more space is needed, additional blocks are allocated
61 and they are put into a linked list.
62 After the initial block, each allocated block is twice the size of the
63 previous, until a threshold is attained, after which the sizes
64 of the blocks stay the same. An exception is, of course, the case
65 where the caller requests a memory buffer whose size is
66 bigger than the threshold. In that case a block big enough must
67 be allocated.
68 
69 The heap is physically arranged so that if the current block
70 becomes full, a new block is allocated and always inserted in the
71 chain of blocks as the last block.
72 
73 In the debug version of the memory management, all the allocated
74 heaps are kept in a list (which is implemented as a hash table).
75 Thus we can notice if the caller tries to free an already freed
76 heap. In addition, each buffer given to the caller contains
77 start field at the start and a trailer field at the end of the buffer.
78 
79 The start field has the following content:
80 A. sizeof(ulint) bytes of field length (in the standard byte order)
81 B. sizeof(ulint) bytes of check field (a random number)
82 
83 The trailer field contains:
84 A. sizeof(ulint) bytes of check field (the same random number as at the start)
85 
86 Thus we can notice if something has been copied over the
87 borders of the buffer, which is illegal.
88 The memory in the buffers is initialized to a random byte sequence.
89 After freeing, all the blocks in the heap are set to random bytes
90 to help us discover errors which result from the use of
91 buffers in an already freed heap. */
92 
93 #ifdef MEM_PERIODIC_CHECK
94 
95 ibool mem_block_list_inited;
96 /* List of all mem blocks allocated; protected by the mem_comm_pool mutex */
97 UT_LIST_BASE_NODE_T(mem_block_t) mem_block_list;
98 
99 #endif
100 
101 /**********************************************************************/
104 UNIV_INTERN
105 char*
107 /*============*/
108  mem_heap_t* heap,
109  const char* str)
110 {
111  return(static_cast<char*>(mem_heap_dup(heap, str, strlen(str) + 1)));
112 }
113 
114 /**********************************************************************/
117 UNIV_INTERN
118 void*
120 /*=========*/
121  mem_heap_t* heap,
122  const void* data,
123  ulint len)
124 {
125  return(memcpy(mem_heap_alloc(heap, len), data, len));
126 }
127 
128 /**********************************************************************/
131 UNIV_INTERN
132 char*
134 /*============*/
135  mem_heap_t* heap,
136  const char* s1,
137  const char* s2)
138 {
139  char* s;
140  ulint s1_len = strlen(s1);
141  ulint s2_len = strlen(s2);
142 
143  s = static_cast<char*>(mem_heap_alloc(heap, s1_len + s2_len + 1));
144 
145  memcpy(s, s1, s1_len);
146  memcpy(s + s1_len, s2, s2_len);
147 
148  s[s1_len + s2_len] = '\0';
149 
150  return(s);
151 }
152 
153 
154 /****************************************************************/
157 static
158 ulint
159 mem_heap_printf_low(
160 /*================*/
161  char* buf,
163  const char* format,
164  va_list ap)
165 {
166  ulint len = 0;
167 
168  while (*format) {
169 
170  /* Does this format specifier have the 'l' length modifier. */
171  ibool is_long = FALSE;
172 
173  /* Length of one parameter. */
174  size_t plen;
175 
176  if (*format++ != '%') {
177  /* Non-format character. */
178 
179  len++;
180 
181  if (buf) {
182  *buf++ = *(format - 1);
183  }
184 
185  continue;
186  }
187 
188  if (*format == 'l') {
189  is_long = TRUE;
190  format++;
191  }
192 
193  switch (*format++) {
194  case 's':
195  /* string */
196  {
197  char* s = va_arg(ap, char*);
198 
199  /* "%ls" is a non-sensical format specifier. */
200  ut_a(!is_long);
201 
202  plen = strlen(s);
203  len += plen;
204 
205  if (buf) {
206  memcpy(buf, s, plen);
207  buf += plen;
208  }
209  }
210 
211  break;
212 
213  case 'u':
214  /* unsigned int */
215  {
216  char tmp[32];
217  unsigned long val;
218 
219  /* We only support 'long' values for now. */
220  ut_a(is_long);
221 
222  val = va_arg(ap, unsigned long);
223 
224  plen = sprintf(tmp, "%lu", val);
225  len += plen;
226 
227  if (buf) {
228  memcpy(buf, tmp, plen);
229  buf += plen;
230  }
231  }
232 
233  break;
234 
235  case '%':
236 
237  /* "%l%" is a non-sensical format specifier. */
238  ut_a(!is_long);
239 
240  len++;
241 
242  if (buf) {
243  *buf++ = '%';
244  }
245 
246  break;
247 
248  default:
249  ut_error;
250  }
251  }
252 
253  /* For the NUL character. */
254  len++;
255 
256  if (buf) {
257  *buf = '\0';
258  }
259 
260  return(len);
261 }
262 
263 /****************************************************************/
269 UNIV_INTERN
270 char*
272 /*============*/
273  mem_heap_t* heap,
274  const char* format,
275  ...)
276 {
277  va_list ap;
278  char* str;
279  ulint len;
280 
281  /* Calculate length of string */
282  len = 0;
283  va_start(ap, format);
284  len = mem_heap_printf_low(NULL, format, ap);
285  va_end(ap);
286 
287  /* Now create it for real. */
288  str = static_cast<char*>(mem_heap_alloc(heap, len));
289  va_start(ap, format);
290  mem_heap_printf_low(str, format, ap);
291  va_end(ap);
292 
293  return(str);
294 }
295 
296 /***************************************************************/
300 UNIV_INTERN
303 /*==================*/
304  mem_heap_t* heap,
306  ulint n,
307  ulint type,
309  const char* file_name,
310  ulint line)
311 {
312 #ifndef UNIV_HOTBACKUP
313  buf_block_t* buf_block = NULL;
314 #endif /* !UNIV_HOTBACKUP */
316  ulint len;
317 
318  ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
319  || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
320 
321  if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) {
323  }
324 
325  /* In dynamic allocation, calculate the size: block header + data. */
326  len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n);
327 
328 #ifndef UNIV_HOTBACKUP
329  if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) {
330 
331  ut_ad(type == MEM_HEAP_DYNAMIC || n <= MEM_MAX_ALLOC_IN_BUF);
332 
333  block = static_cast<mem_block_t*>(
335  } else {
336  len = UNIV_PAGE_SIZE;
337 
338  if ((type & MEM_HEAP_BTR_SEARCH) && heap) {
339  /* We cannot allocate the block from the
340  buffer pool, but must get the free block from
341  the heap header free block field */
342 
343  buf_block = static_cast<buf_block_t*>(heap->free_block);
344  heap->free_block = NULL;
345 
346  if (UNIV_UNLIKELY(!buf_block)) {
347 
348  return(NULL);
349  }
350  } else {
351  buf_block = buf_block_alloc(NULL);
352  }
353 
354  block = (mem_block_t*) buf_block->frame;
355  }
356 
357  if(!block) {
358  ib_logf(IB_LOG_LEVEL_FATAL,
359  " InnoDB: Unable to allocate memory of size %lu.\n",
360  len);
361  }
362  block->buf_block = buf_block;
363  block->free_block = NULL;
364 #else /* !UNIV_HOTBACKUP */
365  len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n);
366  block = ut_malloc(len);
367  ut_ad(block);
368 #endif /* !UNIV_HOTBACKUP */
369 
370  block->magic_n = MEM_BLOCK_MAGIC_N;
371  ut_strlcpy_rev(block->file_name, file_name, sizeof(block->file_name));
372  block->line = line;
373 
374 #ifdef MEM_PERIODIC_CHECK
375  mutex_enter(&(mem_comm_pool->mutex));
376 
377  if (!mem_block_list_inited) {
378  mem_block_list_inited = TRUE;
379  UT_LIST_INIT(mem_block_list);
380  }
381 
382  UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block);
383 
384  mutex_exit(&(mem_comm_pool->mutex));
385 #endif
386  mem_block_set_len(block, len);
387  mem_block_set_type(block, type);
388  mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
389  mem_block_set_start(block, MEM_BLOCK_HEADER_SIZE);
390 
391  if (UNIV_UNLIKELY(heap == NULL)) {
392  /* This is the first block of the heap. The field
393  total_size should be initialized here */
394  block->total_size = len;
395  } else {
396  /* Not the first allocation for the heap. This block's
397  total_length field should be set to undefined. */
398  ut_d(block->total_size = ULINT_UNDEFINED);
399  UNIV_MEM_INVALID(&block->total_size,
400  sizeof block->total_size);
401 
402  heap->total_size += len;
403  }
404 
405  ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len);
406 
407  return(block);
408 }
409 
410 /***************************************************************/
414 UNIV_INTERN
417 /*===============*/
418  mem_heap_t* heap,
419  ulint n)
420 {
422  mem_block_t* new_block;
423  ulint new_size;
424 
425  ut_ad(mem_heap_check(heap));
426 
427  block = UT_LIST_GET_LAST(heap->base);
428 
429  /* We have to allocate a new block. The size is always at least
430  doubled until the standard size is reached. After that the size
431  stays the same, except in cases where the caller needs more space. */
432 
433  new_size = 2 * mem_block_get_len(block);
434 
435  if (heap->type != MEM_HEAP_DYNAMIC) {
436  /* From the buffer pool we allocate buffer frames */
437  ut_a(n <= MEM_MAX_ALLOC_IN_BUF);
438 
439  if (new_size > MEM_MAX_ALLOC_IN_BUF) {
440  new_size = MEM_MAX_ALLOC_IN_BUF;
441  }
442  } else if (new_size > MEM_BLOCK_STANDARD_SIZE) {
443 
444  new_size = MEM_BLOCK_STANDARD_SIZE;
445  }
446 
447  if (new_size < n) {
448  new_size = n;
449  }
450 
451  new_block = mem_heap_create_block(heap, new_size, heap->type,
452  heap->file_name, heap->line);
453  if (new_block == NULL) {
454 
455  return(NULL);
456  }
457 
458  /* Add the new block as the last block */
459 
460  UT_LIST_INSERT_AFTER(list, heap->base, block, new_block);
461 
462  return(new_block);
463 }
464 
465 /******************************************************************/
467 UNIV_INTERN
468 void
470 /*================*/
471  mem_heap_t* heap,
472  mem_block_t* block)
473 {
474  ulint type;
475  ulint len;
476 #ifndef UNIV_HOTBACKUP
477  buf_block_t* buf_block;
478 
479  buf_block = static_cast<buf_block_t*>(block->buf_block);
480 #endif /* !UNIV_HOTBACKUP */
481 
482  if (block->magic_n != MEM_BLOCK_MAGIC_N) {
483  mem_analyze_corruption(block);
484  }
485 
486  UT_LIST_REMOVE(list, heap->base, block);
487 
488 #ifdef MEM_PERIODIC_CHECK
489  mutex_enter(&(mem_comm_pool->mutex));
490 
491  UT_LIST_REMOVE(mem_block_list, mem_block_list, block);
492 
493  mutex_exit(&(mem_comm_pool->mutex));
494 #endif
495 
496  ut_ad(heap->total_size >= block->len);
497  heap->total_size -= block->len;
498 
499  type = heap->type;
500  len = block->len;
501  block->magic_n = MEM_FREED_BLOCK_MAGIC_N;
502 
503 #ifndef UNIV_HOTBACKUP
504  if (!srv_use_sys_malloc) {
505 #ifdef UNIV_MEM_DEBUG
506  /* In the debug version we set the memory to a random
507  combination of hex 0xDE and 0xAD. */
508 
509  mem_erase_buf((byte*) block, len);
510 #else /* UNIV_MEM_DEBUG */
511  UNIV_MEM_ASSERT_AND_FREE(block, len);
512 #endif /* UNIV_MEM_DEBUG */
513 
514  }
515  if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) {
516 
517  ut_ad(!buf_block);
519  } else {
520  ut_ad(type & MEM_HEAP_BUFFER);
521 
522  buf_block_free(buf_block);
523  }
524 #else /* !UNIV_HOTBACKUP */
525 #ifdef UNIV_MEM_DEBUG
526  /* In the debug version we set the memory to a random
527  combination of hex 0xDE and 0xAD. */
528 
529  mem_erase_buf((byte*) block, len);
530 #else /* UNIV_MEM_DEBUG */
531  UNIV_MEM_ASSERT_AND_FREE(block, len);
532 #endif /* UNIV_MEM_DEBUG */
533  ut_free(block);
534 #endif /* !UNIV_HOTBACKUP */
535 }
536 
537 #ifndef UNIV_HOTBACKUP
538 /******************************************************************/
540 UNIV_INTERN
541 void
543 /*=====================*/
544  mem_heap_t* heap)
545 {
546  if (UNIV_LIKELY_NULL(heap->free_block)) {
547 
548  buf_block_free(static_cast<buf_block_t*>(heap->free_block));
549 
550  heap->free_block = NULL;
551  }
552 }
553 #endif /* !UNIV_HOTBACKUP */
554 
555 #ifdef MEM_PERIODIC_CHECK
556 /******************************************************************/
559 UNIV_INTERN
560 void
561 mem_validate_all_blocks(void)
562 /*=========================*/
563 {
565 
566  mutex_enter(&(mem_comm_pool->mutex));
567 
568  block = UT_LIST_GET_FIRST(mem_block_list);
569 
570  while (block) {
571  if (block->magic_n != MEM_BLOCK_MAGIC_N) {
572  mem_analyze_corruption(block);
573  }
574 
575  block = UT_LIST_GET_NEXT(mem_block_list, block);
576  }
577 
578  mutex_exit(&(mem_comm_pool->mutex));
579 }
580 #endif