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, or
25
if init_block is not NULL, its size in bytes */
26
void* init_block, /* in: init block in fast create,
27
type must be MEM_HEAP_DYNAMIC */
28
ulint type, /* in: type of heap: MEM_HEAP_DYNAMIC or
30
const char* file_name,/* in: file name where created */
31
ulint line); /* in: line where created */
32
/**********************************************************************
33
Frees a block from a memory heap. */
38
mem_heap_t* heap, /* in: heap */
39
mem_block_t* block); /* in: block to free */
40
/**********************************************************************
41
Frees the free_block field from a memory heap. */
44
mem_heap_free_block_free(
45
/*=====================*/
46
mem_heap_t* heap); /* in: heap */
47
/*******************************************************************
48
Adds a new block to a memory heap. */
53
/* out: created block, NULL if did not
54
succeed (only possible for
55
MEM_HEAP_BTR_SEARCH type heaps)*/
56
mem_heap_t* heap, /* in: memory heap */
57
ulint n); /* in: number of bytes user needs */
61
mem_block_set_len(mem_block_t* block, ulint len)
70
mem_block_get_len(mem_block_t* block)
77
mem_block_set_type(mem_block_t* block, ulint type)
79
ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
80
|| (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
87
mem_block_get_type(mem_block_t* block)
94
mem_block_set_free(mem_block_t* block, ulint free)
97
ut_ad(free <= mem_block_get_len(block));
104
mem_block_get_free(mem_block_t* block)
111
mem_block_set_start(mem_block_t* block, ulint start)
115
block->start = start;
120
mem_block_get_start(mem_block_t* block)
122
return(block->start);
125
/*******************************************************************
126
Allocates n bytes of memory from a memory heap. */
131
/* out: allocated storage, NULL if did not
132
succeed (only possible for
133
MEM_HEAP_BTR_SEARCH type heaps) */
134
mem_heap_t* heap, /* in: memory heap */
135
ulint n) /* in: number of bytes; if the heap is allowed
136
to grow into the buffer pool, this must be
137
<= MEM_MAX_ALLOC_IN_BUF */
143
ut_ad(mem_heap_check(heap));
145
block = UT_LIST_GET_LAST(heap->base);
147
ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF));
149
/* Check if there is enough space in block. If not, create a new
152
if (mem_block_get_len(block)
153
< mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) {
155
block = mem_heap_add_block(heap, n);
163
free = mem_block_get_free(block);
165
buf = (byte*)block + free;
167
mem_block_set_free(block, free + MEM_SPACE_NEEDED(n));
169
#ifdef UNIV_MEM_DEBUG
171
n + MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE);
173
/* In the debug version write debugging info to the field */
174
mem_field_init((byte*)buf, n);
176
/* Advance buf to point at the storage which will be given to the
178
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
181
#ifdef UNIV_SET_MEM_TO_ZERO
182
UNIV_MEM_ALLOC(buf, n);
183
memset(buf, '\0', n);
185
UNIV_MEM_ALLOC(buf, n);
189
/*********************************************************************
190
Returns a pointer to the heap top. */
193
mem_heap_get_heap_top(
194
/*==================*/
195
/* out: pointer to the heap top */
196
mem_heap_t* heap) /* in: memory heap */
201
ut_ad(mem_heap_check(heap));
203
block = UT_LIST_GET_LAST(heap->base);
205
buf = (byte*)block + mem_block_get_free(block);
210
/*********************************************************************
211
Frees the space in a memory heap exceeding the pointer given. The
212
pointer must have been acquired from mem_heap_get_heap_top. The first
213
memory block of the heap is not freed. */
216
mem_heap_free_heap_top(
217
/*===================*/
218
mem_heap_t* heap, /* in: heap from which to free */
219
byte* old_top)/* in: pointer to old top of heap */
222
mem_block_t* prev_block;
223
#ifdef UNIV_MEM_DEBUG
229
ut_ad(mem_heap_check(heap));
231
#ifdef UNIV_MEM_DEBUG
233
/* Validate the heap and get its total allocated size */
234
mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
238
/* Get the size below top pointer */
239
mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
245
block = UT_LIST_GET_LAST(heap->base);
247
while (block != NULL) {
248
if (((byte*)block + mem_block_get_free(block) >= old_top)
249
&& ((byte*)block <= old_top)) {
250
/* Found the right block */
255
/* Store prev_block value before freeing the current block
256
(the current block will be erased in freeing) */
258
prev_block = UT_LIST_GET_PREV(list, block);
260
mem_heap_block_free(heap, block);
267
/* Set the free field of block */
268
mem_block_set_free(block, old_top - (byte*)block);
270
#ifdef UNIV_MEM_DEBUG
271
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
273
/* In the debug version erase block from top up */
274
mem_erase_buf(old_top, (byte*)block + block->len - old_top);
276
/* Update allocated memory count */
277
mutex_enter(&mem_hash_mutex);
278
mem_current_allocated_memory -= (total_size - size);
279
mutex_exit(&mem_hash_mutex);
280
#else /* UNIV_MEM_DEBUG */
281
UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top);
282
#endif /* UNIV_MEM_DEBUG */
283
UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top);
285
/* If free == start, we may free the block if it is not the first
288
if ((heap != block) && (mem_block_get_free(block)
289
== mem_block_get_start(block))) {
290
mem_heap_block_free(heap, block);
294
/*********************************************************************
295
Empties a memory heap. The first memory block of the heap is not freed. */
300
mem_heap_t* heap) /* in: heap to empty */
302
mem_heap_free_heap_top(heap, (byte*)heap + mem_block_get_start(heap));
304
if (heap->free_block) {
305
mem_heap_free_block_free(heap);
309
/*********************************************************************
310
Returns a pointer to the topmost element in a memory heap. The size of the
311
element must be given. */
316
/* out: pointer to the topmost element */
317
mem_heap_t* heap, /* in: memory heap */
318
ulint n) /* in: size of the topmost element */
323
ut_ad(mem_heap_check(heap));
325
block = UT_LIST_GET_LAST(heap->base);
327
buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
329
#ifdef UNIV_MEM_DEBUG
330
ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
332
/* In the debug version, advance buf to point at the storage which
333
was given to the caller in the allocation*/
335
buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
337
/* Check that the field lengths agree */
338
ut_ad(n == (ulint)mem_field_header_get_len(buf));
344
/*********************************************************************
345
Frees the topmost element in a memory heap. The size of the element must be
351
mem_heap_t* heap, /* in: memory heap */
352
ulint n) /* in: size of the topmost element */
356
ut_ad(mem_heap_check(heap));
358
block = UT_LIST_GET_LAST(heap->base);
360
/* Subtract the free field of block */
361
mem_block_set_free(block, mem_block_get_free(block)
362
- MEM_SPACE_NEEDED(n));
363
UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
364
#ifdef UNIV_MEM_DEBUG
366
ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
368
/* In the debug version check the consistency, and erase field */
369
mem_field_erase((byte*)block + mem_block_get_free(block), n);
372
/* If free == start, we may free the block if it is not the first
375
if ((heap != block) && (mem_block_get_free(block)
376
== mem_block_get_start(block))) {
377
mem_heap_block_free(heap, block);
379
/* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
380
subsequent invocation of mem_heap_free_top().
381
Originally, this was UNIV_MEM_FREE(), to catch writes
383
UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
387
/*********************************************************************
388
NOTE: Use the corresponding macros instead of this function. Creates a
389
memory heap. For debugging purposes, takes also the file name and line as
393
mem_heap_create_func(
394
/*=================*/
395
/* out, own: memory heap, NULL if
396
did not succeed (only possible for
397
MEM_HEAP_BTR_SEARCH type heaps)*/
398
ulint n, /* in: desired start block size,
399
this means that a single user buffer
400
of size n will fit in the block,
401
0 creates a default size block;
402
if init_block is not NULL, n tells
404
void* init_block, /* in: if very fast creation is
405
wanted, the caller can reserve some
406
memory from its stack, for example,
407
and pass it as the the initial block
408
to the heap: then no OS call of malloc
409
is needed at the creation. CAUTION:
410
the caller must make sure the initial
411
block is not unintentionally erased
412
(if allocated in the stack), before
413
the memory heap is explicitly freed. */
414
ulint type, /* in: heap type */
415
const char* file_name, /* in: file name where created */
416
ulint line) /* in: line where created */
421
block = mem_heap_create_block(NULL, n, init_block, type,
424
block = mem_heap_create_block(NULL, MEM_BLOCK_START_SIZE,
434
UT_LIST_INIT(block->base);
436
/* Add the created block itself as the first block in the list */
437
UT_LIST_ADD_FIRST(list, block->base, block);
439
#ifdef UNIV_MEM_DEBUG
441
mem_hash_insert(block, file_name, line);
448
/*********************************************************************
449
NOTE: Use the corresponding macro instead of this function. Frees the space
450
occupied by a memory heap. In the debug version erases the heap memory
456
mem_heap_t* heap, /* in, own: heap to be freed */
457
const char* file_name __attribute__((unused)),
458
/* in: file name where freed */
459
ulint line __attribute__((unused)))
462
mem_block_t* prev_block;
464
ut_ad(mem_heap_check(heap));
466
block = UT_LIST_GET_LAST(heap->base);
468
#ifdef UNIV_MEM_DEBUG
470
/* In the debug version remove the heap from the hash table of heaps
471
and check its consistency */
473
mem_hash_remove(heap, file_name, line);
477
if (heap->free_block) {
478
mem_heap_free_block_free(heap);
481
while (block != NULL) {
482
/* Store the contents of info before freeing current block
483
(it is erased in freeing) */
485
prev_block = UT_LIST_GET_PREV(list, block);
487
mem_heap_block_free(heap, block);
493
/*******************************************************************
494
NOTE: Use the corresponding macro instead of this function.
495
Allocates a single buffer of memory from the dynamic memory of
496
the C compiler. Is like malloc of C. The buffer must be freed
502
/* out, own: free storage */
503
ulint n, /* in: desired number of bytes */
504
const char* file_name, /* in: file name where created */
505
ulint line /* in: line where created */
511
heap = mem_heap_create_func(n, NULL, MEM_HEAP_DYNAMIC, file_name,
514
/* Note that as we created the first block in the heap big enough
515
for the buffer requested by the caller, the buffer will be in the
516
first block and thus we can calculate the pointer to the heap from
517
the pointer to the buffer when we free the memory buffer. */
519
buf = mem_heap_alloc(heap, n);
521
ut_a((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
522
- MEM_FIELD_HEADER_SIZE);
526
/*******************************************************************
527
NOTE: Use the corresponding macro instead of this function. Frees a single
528
buffer of storage from the dynamic memory of the C compiler. Similar to the
534
void* ptr, /* in, own: buffer to be freed */
535
const char* file_name, /* in: file name where created */
536
ulint line /* in: line where created */
541
heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
542
- MEM_FIELD_HEADER_SIZE);
543
mem_heap_free_func(heap, file_name, line);
546
/*********************************************************************
547
Returns the space in bytes occupied by a memory heap. */
552
mem_heap_t* heap) /* in: heap */
557
ut_ad(mem_heap_check(heap));
561
while (block != NULL) {
563
size += mem_block_get_len(block);
564
block = UT_LIST_GET_NEXT(list, block);
567
if (heap->free_block) {
568
size += UNIV_PAGE_SIZE;
574
/**************************************************************************
575
Duplicates a NUL-terminated string. */
580
/* out, own: a copy of the string,
581
must be deallocated with mem_free */
582
const char* str) /* in: string to be copied */
584
ulint len = strlen(str) + 1;
585
return(memcpy(mem_alloc(len), str, len));
588
/**************************************************************************
589
Makes a NUL-terminated copy of a nonterminated string. */
594
/* out, own: a copy of the string,
595
must be deallocated with mem_free */
596
const char* str, /* in: string to be copied */
597
ulint len) /* in: length of str, in bytes */
599
char* s = mem_alloc(len + 1);
601
return(memcpy(s, str, len));
604
/**************************************************************************
605
Makes a NUL-terminated copy of a nonterminated string,
606
allocated from a memory heap. */
611
/* out, own: a copy of the string */
612
mem_heap_t* heap, /* in: memory heap where string is allocated */
613
const char* str, /* in: string to be copied */
614
ulint len) /* in: length of str, in bytes */
616
char* s = mem_heap_alloc(heap, len + 1);
618
return(memcpy(s, str, len));