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., 51 Franklin
15
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
#ifdef UNIV_SET_MEM_TO_ZERO
213
UNIV_MEM_ALLOC(buf, n);
214
memset(buf, '\0', n);
216
UNIV_MEM_ALLOC(buf, n);
220
/*****************************************************************//**
221
Returns a pointer to the heap top.
222
@return pointer to the heap top */
225
mem_heap_get_heap_top(
226
/*==================*/
227
mem_heap_t* heap) /*!< in: memory heap */
232
ut_ad(mem_heap_check(heap));
234
block = UT_LIST_GET_LAST(heap->base);
236
buf = (byte*)block + mem_block_get_free(block);
241
/*****************************************************************//**
242
Frees the space in a memory heap exceeding the pointer given. The
243
pointer must have been acquired from mem_heap_get_heap_top. The first
244
memory block of the heap is not freed. */
247
mem_heap_free_heap_top(
248
/*===================*/
249
mem_heap_t* heap, /*!< in: heap from which to free */
250
byte* old_top)/*!< in: pointer to old top of heap */
253
mem_block_t* prev_block;
254
#ifdef UNIV_MEM_DEBUG
260
ut_ad(mem_heap_check(heap));
262
#ifdef UNIV_MEM_DEBUG
264
/* Validate the heap and get its total allocated size */
265
mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
269
/* Get the size below top pointer */
270
mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
276
block = UT_LIST_GET_LAST(heap->base);
278
while (block != NULL) {
279
if (((byte*)block + mem_block_get_free(block) >= old_top)
280
&& ((byte*)block <= old_top)) {
281
/* Found the right block */
286
/* Store prev_block value before freeing the current block
287
(the current block will be erased in freeing) */
289
prev_block = UT_LIST_GET_PREV(list, block);
291
mem_heap_block_free(heap, block);
298
/* Set the free field of block */
299
mem_block_set_free(block, old_top - (byte*)block);
301
#ifdef UNIV_MEM_DEBUG
302
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
304
/* In the debug version erase block from top up */
305
mem_erase_buf(old_top, (byte*)block + block->len - old_top);
307
/* Update allocated memory count */
308
mutex_enter(&mem_hash_mutex);
309
mem_current_allocated_memory -= (total_size - size);
310
mutex_exit(&mem_hash_mutex);
311
#else /* UNIV_MEM_DEBUG */
312
UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top);
313
#endif /* UNIV_MEM_DEBUG */
314
UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top);
316
/* If free == start, we may free the block if it is not the first
319
if ((heap != block) && (mem_block_get_free(block)
320
== mem_block_get_start(block))) {
321
mem_heap_block_free(heap, block);
325
/*****************************************************************//**
326
Empties a memory heap. The first memory block of the heap is not freed. */
331
mem_heap_t* heap) /*!< in: heap to empty */
333
mem_heap_free_heap_top(heap, (byte*)heap + mem_block_get_start(heap));
334
#ifndef UNIV_HOTBACKUP
335
if (heap->free_block) {
336
mem_heap_free_block_free(heap);
338
#endif /* !UNIV_HOTBACKUP */
341
/*****************************************************************//**
342
Returns a pointer to the topmost element in a memory heap. The size of the
343
element must be given.
344
@return pointer to the topmost element */
349
mem_heap_t* heap, /*!< in: memory heap */
350
ulint n) /*!< in: size of the topmost element */
355
ut_ad(mem_heap_check(heap));
357
block = UT_LIST_GET_LAST(heap->base);
359
buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
361
#ifdef UNIV_MEM_DEBUG
362
ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
364
/* In the debug version, advance buf to point at the storage which
365
was given to the caller in the allocation*/
367
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
369
/* Check that the field lengths agree */
370
ut_ad(n == (ulint)mem_field_header_get_len(buf));
376
/*****************************************************************//**
377
Frees the topmost element in a memory heap. The size of the element must be
383
mem_heap_t* heap, /*!< in: memory heap */
384
ulint n) /*!< in: size of the topmost element */
388
ut_ad(mem_heap_check(heap));
390
block = UT_LIST_GET_LAST(heap->base);
392
/* Subtract the free field of block */
393
mem_block_set_free(block, mem_block_get_free(block)
394
- MEM_SPACE_NEEDED(n));
395
UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
396
#ifdef UNIV_MEM_DEBUG
398
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
400
/* In the debug version check the consistency, and erase field */
401
mem_field_erase((byte*)block + mem_block_get_free(block), n);
404
/* If free == start, we may free the block if it is not the first
407
if ((heap != block) && (mem_block_get_free(block)
408
== mem_block_get_start(block))) {
409
mem_heap_block_free(heap, block);
411
/* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
412
subsequent invocation of mem_heap_free_top().
413
Originally, this was UNIV_MEM_FREE(), to catch writes
415
UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
419
/*****************************************************************//**
420
NOTE: Use the corresponding macros instead of this function. Creates a
421
memory heap. For debugging purposes, takes also the file name and line as
423
@return own: memory heap, NULL if did not succeed (only possible for
424
MEM_HEAP_BTR_SEARCH type heaps) */
427
mem_heap_create_func(
428
/*=================*/
429
ulint n, /*!< in: desired start block size,
430
this means that a single user buffer
431
of size n will fit in the block,
432
0 creates a default size block */
433
ulint type, /*!< in: heap type */
434
const char* file_name, /*!< in: file name where created */
435
ulint line) /*!< in: line where created */
440
n = MEM_BLOCK_START_SIZE;
443
block = mem_heap_create_block(NULL, n, type, file_name, line);
450
UT_LIST_INIT(block->base);
452
/* Add the created block itself as the first block in the list */
453
UT_LIST_ADD_FIRST(list, block->base, block);
455
#ifdef UNIV_MEM_DEBUG
457
mem_hash_insert(block, file_name, line);
464
/*****************************************************************//**
465
NOTE: Use the corresponding macro instead of this function. Frees the space
466
occupied by a memory heap. In the debug version erases the heap memory
472
mem_heap_t* heap, /*!< in, own: heap to be freed */
473
const char* file_name __attribute__((unused)),
474
/*!< in: file name where freed */
475
ulint line __attribute__((unused)))
480
mem_block_t* prev_block;
482
ut_ad(mem_heap_check(heap));
484
block = UT_LIST_GET_LAST(heap->base);
486
#ifdef UNIV_MEM_DEBUG
488
/* In the debug version remove the heap from the hash table of heaps
489
and check its consistency */
491
mem_hash_remove(heap, file_name, line);
494
#ifndef UNIV_HOTBACKUP
495
if (heap->free_block) {
496
mem_heap_free_block_free(heap);
498
#endif /* !UNIV_HOTBACKUP */
500
while (block != NULL) {
501
/* Store the contents of info before freeing current block
502
(it is erased in freeing) */
504
prev_block = UT_LIST_GET_PREV(list, block);
506
mem_heap_block_free(heap, block);
512
/***************************************************************//**
513
NOTE: Use the corresponding macro instead of this function.
514
Allocates a single buffer of memory from the dynamic memory of
515
the C compiler. Is like malloc of C. The buffer must be freed
517
@return own: free storage */
522
ulint n, /*!< in: desired number of bytes */
523
ulint* size, /*!< out: allocated size in bytes,
525
const char* file_name, /*!< in: file name where created */
526
ulint line) /*!< in: line where created */
531
heap = mem_heap_create_func(n, MEM_HEAP_DYNAMIC, file_name, line);
533
/* Note that as we created the first block in the heap big enough
534
for the buffer requested by the caller, the buffer will be in the
535
first block and thus we can calculate the pointer to the heap from
536
the pointer to the buffer when we free the memory buffer. */
538
if (UNIV_LIKELY_NULL(size)) {
539
/* Adjust the allocation to the actual size of the
541
ulint m = mem_block_get_len(heap)
542
- mem_block_get_free(heap);
543
#ifdef UNIV_MEM_DEBUG
544
m -= MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE;
545
#endif /* UNIV_MEM_DEBUG */
550
buf = mem_heap_alloc(heap, n);
552
ut_a((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
553
- MEM_FIELD_HEADER_SIZE);
557
/***************************************************************//**
558
NOTE: Use the corresponding macro instead of this function. Frees a single
559
buffer of storage from the dynamic memory of the C compiler. Similar to the
565
void* ptr, /*!< in, own: buffer to be freed */
566
const char* file_name, /*!< in: file name where created */
567
ulint line) /*!< in: line where created */
571
heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
572
- MEM_FIELD_HEADER_SIZE);
573
mem_heap_free_func(heap, file_name, line);
576
/*****************************************************************//**
577
Returns the space in bytes occupied by a memory heap. */
582
mem_heap_t* heap) /*!< in: heap */
586
ut_ad(mem_heap_check(heap));
588
size = heap->total_size;
590
#ifndef UNIV_HOTBACKUP
591
if (heap->free_block) {
592
size += UNIV_PAGE_SIZE;
594
#endif /* !UNIV_HOTBACKUP */
599
/**********************************************************************//**
600
Duplicates a NUL-terminated string.
601
@return own: a copy of the string, must be deallocated with mem_free */
606
const char* str) /*!< in: string to be copied */
608
ulint len = strlen(str) + 1;
609
return((char*) memcpy(mem_alloc(len), str, len));
612
/**********************************************************************//**
613
Makes a NUL-terminated copy of a nonterminated string.
614
@return own: a copy of the string, must be deallocated with mem_free */
619
const char* str, /*!< in: string to be copied */
620
ulint len) /*!< in: length of str, in bytes */
622
char* s = (char*) mem_alloc(len + 1);
624
return((char*) memcpy(s, str, len));
627
/**********************************************************************//**
628
Makes a NUL-terminated copy of a nonterminated string,
629
allocated from a memory heap.
630
@return own: a copy of the string */
635
mem_heap_t* heap, /*!< in: memory heap where string is allocated */
636
const char* str, /*!< in: string to be copied */
637
ulint len) /*!< in: length of str, in bytes */
639
char* s = (char*) mem_heap_alloc(heap, len + 1);
641
return((char*) memcpy(s, str, len));