1
/************************************************************************
4
(c) 1994, 1995 Innobase Oy
6
Created 6/8/1994 Heikki Tuuri
7
*************************************************************************/
13
/*******************************************************************
14
Creates a memory heap block where data can be allocated. */
17
mem_heap_create_block(
18
/*==================*/
19
/* out, own: memory heap block, NULL if
20
did not succeed (only possible for
21
MEM_HEAP_BTR_SEARCH type heaps) */
22
mem_heap_t* heap, /* in: memory heap or NULL if first block
24
ulint n, /* in: number of bytes needed for user data */
25
ulint type, /* in: type of heap: MEM_HEAP_DYNAMIC or
27
const char* file_name,/* in: file name where created */
28
ulint line); /* in: line where created */
29
/**********************************************************************
30
Frees a block from a memory heap. */
35
mem_heap_t* heap, /* in: heap */
36
mem_block_t* block); /* in: block to free */
37
/**********************************************************************
38
Frees the free_block field from a memory heap. */
41
mem_heap_free_block_free(
42
/*=====================*/
43
mem_heap_t* heap); /* in: heap */
44
/*******************************************************************
45
Adds a new block to a memory heap. */
50
/* out: created block, NULL if did not
51
succeed (only possible for
52
MEM_HEAP_BTR_SEARCH type heaps)*/
53
mem_heap_t* heap, /* in: memory heap */
54
ulint n); /* in: number of bytes user needs */
58
mem_block_set_len(mem_block_t* block, ulint len)
67
mem_block_get_len(mem_block_t* block)
74
mem_block_set_type(mem_block_t* block, ulint type)
76
ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
77
|| (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
84
mem_block_get_type(mem_block_t* block)
91
mem_block_set_free(mem_block_t* block, ulint free)
94
ut_ad(free <= mem_block_get_len(block));
101
mem_block_get_free(mem_block_t* block)
108
mem_block_set_start(mem_block_t* block, ulint start)
112
block->start = start;
117
mem_block_get_start(mem_block_t* block)
119
return(block->start);
122
/*******************************************************************
123
Allocates and zero-fills n bytes of memory from a memory heap. */
128
/* out: allocated, zero-filled storage */
129
mem_heap_t* heap, /* in: memory heap */
130
ulint n) /* in: number of bytes; if the heap is allowed
131
to grow into the buffer pool, this must be
132
<= MEM_MAX_ALLOC_IN_BUF */
135
ut_ad(!(heap->type & MEM_HEAP_BTR_SEARCH));
136
return(memset(mem_heap_alloc(heap, n), 0, n));
139
/*******************************************************************
140
Allocates n bytes of memory from a memory heap. */
145
/* out: allocated storage, NULL if did not
146
succeed (only possible for
147
MEM_HEAP_BTR_SEARCH type heaps) */
148
mem_heap_t* heap, /* in: memory heap */
149
ulint n) /* in: number of bytes; if the heap is allowed
150
to grow into the buffer pool, this must be
151
<= MEM_MAX_ALLOC_IN_BUF */
157
ut_ad(mem_heap_check(heap));
159
block = UT_LIST_GET_LAST(heap->base);
161
ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF));
163
/* Check if there is enough space in block. If not, create a new
166
if (mem_block_get_len(block)
167
< mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) {
169
block = mem_heap_add_block(heap, n);
177
free = mem_block_get_free(block);
179
buf = (byte*)block + free;
181
mem_block_set_free(block, free + MEM_SPACE_NEEDED(n));
183
#ifdef UNIV_MEM_DEBUG
185
n + MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE);
187
/* In the debug version write debugging info to the field */
188
mem_field_init((byte*)buf, n);
190
/* Advance buf to point at the storage which will be given to the
192
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
195
#ifdef UNIV_SET_MEM_TO_ZERO
196
UNIV_MEM_ALLOC(buf, n);
197
memset(buf, '\0', n);
199
UNIV_MEM_ALLOC(buf, n);
203
/*********************************************************************
204
Returns a pointer to the heap top. */
207
mem_heap_get_heap_top(
208
/*==================*/
209
/* out: pointer to the heap top */
210
mem_heap_t* heap) /* in: memory heap */
215
ut_ad(mem_heap_check(heap));
217
block = UT_LIST_GET_LAST(heap->base);
219
buf = (byte*)block + mem_block_get_free(block);
224
/*********************************************************************
225
Frees the space in a memory heap exceeding the pointer given. The
226
pointer must have been acquired from mem_heap_get_heap_top. The first
227
memory block of the heap is not freed. */
230
mem_heap_free_heap_top(
231
/*===================*/
232
mem_heap_t* heap, /* in: heap from which to free */
233
byte* old_top)/* in: pointer to old top of heap */
236
mem_block_t* prev_block;
237
#ifdef UNIV_MEM_DEBUG
243
ut_ad(mem_heap_check(heap));
245
#ifdef UNIV_MEM_DEBUG
247
/* Validate the heap and get its total allocated size */
248
mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
252
/* Get the size below top pointer */
253
mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
259
block = UT_LIST_GET_LAST(heap->base);
261
while (block != NULL) {
262
if (((byte*)block + mem_block_get_free(block) >= old_top)
263
&& ((byte*)block <= old_top)) {
264
/* Found the right block */
269
/* Store prev_block value before freeing the current block
270
(the current block will be erased in freeing) */
272
prev_block = UT_LIST_GET_PREV(list, block);
274
mem_heap_block_free(heap, block);
281
/* Set the free field of block */
282
mem_block_set_free(block, old_top - (byte*)block);
284
#ifdef UNIV_MEM_DEBUG
285
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
287
/* In the debug version erase block from top up */
288
mem_erase_buf(old_top, (byte*)block + block->len - old_top);
290
/* Update allocated memory count */
291
mutex_enter(&mem_hash_mutex);
292
mem_current_allocated_memory -= (total_size - size);
293
mutex_exit(&mem_hash_mutex);
294
#else /* UNIV_MEM_DEBUG */
295
UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top);
296
#endif /* UNIV_MEM_DEBUG */
297
UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top);
299
/* If free == start, we may free the block if it is not the first
302
if ((heap != block) && (mem_block_get_free(block)
303
== mem_block_get_start(block))) {
304
mem_heap_block_free(heap, block);
308
/*********************************************************************
309
Empties a memory heap. The first memory block of the heap is not freed. */
314
mem_heap_t* heap) /* in: heap to empty */
316
mem_heap_free_heap_top(heap, (byte*)heap + mem_block_get_start(heap));
318
if (heap->free_block) {
319
mem_heap_free_block_free(heap);
323
/*********************************************************************
324
Returns a pointer to the topmost element in a memory heap. The size of the
325
element must be given. */
330
/* out: pointer to the topmost element */
331
mem_heap_t* heap, /* in: memory heap */
332
ulint n) /* in: size of the topmost element */
337
ut_ad(mem_heap_check(heap));
339
block = UT_LIST_GET_LAST(heap->base);
341
buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
343
#ifdef UNIV_MEM_DEBUG
344
ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
346
/* In the debug version, advance buf to point at the storage which
347
was given to the caller in the allocation*/
349
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
351
/* Check that the field lengths agree */
352
ut_ad(n == (ulint)mem_field_header_get_len(buf));
358
/*********************************************************************
359
Frees the topmost element in a memory heap. The size of the element must be
365
mem_heap_t* heap, /* in: memory heap */
366
ulint n) /* in: size of the topmost element */
370
ut_ad(mem_heap_check(heap));
372
block = UT_LIST_GET_LAST(heap->base);
374
/* Subtract the free field of block */
375
mem_block_set_free(block, mem_block_get_free(block)
376
- MEM_SPACE_NEEDED(n));
377
UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
378
#ifdef UNIV_MEM_DEBUG
380
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
382
/* In the debug version check the consistency, and erase field */
383
mem_field_erase((byte*)block + mem_block_get_free(block), n);
386
/* If free == start, we may free the block if it is not the first
389
if ((heap != block) && (mem_block_get_free(block)
390
== mem_block_get_start(block))) {
391
mem_heap_block_free(heap, block);
393
/* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
394
subsequent invocation of mem_heap_free_top().
395
Originally, this was UNIV_MEM_FREE(), to catch writes
397
UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
401
/*********************************************************************
402
NOTE: Use the corresponding macros instead of this function. Creates a
403
memory heap. For debugging purposes, takes also the file name and line as
407
mem_heap_create_func(
408
/*=================*/
409
/* out, own: memory heap, NULL if
410
did not succeed (only possible for
411
MEM_HEAP_BTR_SEARCH type heaps)*/
412
ulint n, /* in: desired start block size,
413
this means that a single user buffer
414
of size n will fit in the block,
415
0 creates a default size block */
416
ulint type, /* in: heap type */
417
const char* file_name, /* in: file name where created */
418
ulint line) /* in: line where created */
423
n = MEM_BLOCK_START_SIZE;
426
block = mem_heap_create_block(NULL, n, type, file_name, line);
433
UT_LIST_INIT(block->base);
435
/* Add the created block itself as the first block in the list */
436
UT_LIST_ADD_FIRST(list, block->base, block);
438
#ifdef UNIV_MEM_DEBUG
440
mem_hash_insert(block, file_name, line);
447
/*********************************************************************
448
NOTE: Use the corresponding macro instead of this function. Frees the space
449
occupied by a memory heap. In the debug version erases the heap memory
455
mem_heap_t* heap, /* in, own: heap to be freed */
456
const char* file_name __attribute__((unused)),
457
/* in: file name where freed */
458
ulint line __attribute__((unused)))
461
mem_block_t* prev_block;
463
ut_ad(mem_heap_check(heap));
465
block = UT_LIST_GET_LAST(heap->base);
467
#ifdef UNIV_MEM_DEBUG
469
/* In the debug version remove the heap from the hash table of heaps
470
and check its consistency */
472
mem_hash_remove(heap, file_name, line);
476
if (heap->free_block) {
477
mem_heap_free_block_free(heap);
480
while (block != NULL) {
481
/* Store the contents of info before freeing current block
482
(it is erased in freeing) */
484
prev_block = UT_LIST_GET_PREV(list, block);
486
mem_heap_block_free(heap, block);
492
/*******************************************************************
493
NOTE: Use the corresponding macro instead of this function.
494
Allocates a single buffer of memory from the dynamic memory of
495
the C compiler. Is like malloc of C. The buffer must be freed
501
/* out, own: free storage */
502
ulint n, /* in: desired number of bytes */
503
ulint* size, /* out: allocated size in bytes,
505
const char* file_name, /* in: file name where created */
506
ulint line) /* in: line where created */
511
heap = mem_heap_create_func(n, MEM_HEAP_DYNAMIC, file_name, line);
513
/* Note that as we created the first block in the heap big enough
514
for the buffer requested by the caller, the buffer will be in the
515
first block and thus we can calculate the pointer to the heap from
516
the pointer to the buffer when we free the memory buffer. */
518
if (UNIV_LIKELY_NULL(size)) {
519
/* Adjust the allocation to the actual size of the
521
ulint m = mem_block_get_len(heap)
522
- mem_block_get_free(heap);
523
#ifdef UNIV_MEM_DEBUG
524
m -= MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE;
525
#endif /* UNIV_MEM_DEBUG */
530
buf = mem_heap_alloc(heap, n);
532
ut_a((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
533
- MEM_FIELD_HEADER_SIZE);
537
/*******************************************************************
538
NOTE: Use the corresponding macro instead of this function. Frees a single
539
buffer of storage from the dynamic memory of the C compiler. Similar to the
545
void* ptr, /* in, own: buffer to be freed */
546
const char* file_name, /* in: file name where created */
547
ulint line /* in: line where created */
552
heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
553
- MEM_FIELD_HEADER_SIZE);
554
mem_heap_free_func(heap, file_name, line);
557
/*********************************************************************
558
Returns the space in bytes occupied by a memory heap. */
563
mem_heap_t* heap) /* in: heap */
568
ut_ad(mem_heap_check(heap));
572
while (block != NULL) {
574
size += mem_block_get_len(block);
575
block = UT_LIST_GET_NEXT(list, block);
578
if (heap->free_block) {
579
size += UNIV_PAGE_SIZE;
585
/**************************************************************************
586
Duplicates a NUL-terminated string. */
591
/* out, own: a copy of the string,
592
must be deallocated with mem_free */
593
const char* str) /* in: string to be copied */
595
ulint len = strlen(str) + 1;
596
return((char*) memcpy(mem_alloc(len), str, len));
599
/**************************************************************************
600
Makes a NUL-terminated copy of a nonterminated string. */
605
/* out, own: a copy of the string,
606
must be deallocated with mem_free */
607
const char* str, /* in: string to be copied */
608
ulint len) /* in: length of str, in bytes */
610
char* s = (char*) mem_alloc(len + 1);
612
return((char*) memcpy(s, str, len));
615
/**************************************************************************
616
Makes a NUL-terminated copy of a nonterminated string,
617
allocated from a memory heap. */
622
/* out, own: a copy of the string */
623
mem_heap_t* heap, /* in: memory heap where string is allocated */
624
const char* str, /* in: string to be copied */
625
ulint len) /* in: length of str, in bytes */
627
char* s = (char*) mem_heap_alloc(heap, len + 1);
629
return((char*) memcpy(s, str, len));