mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / innodb_plugin / include / mem0mem.ic
blob827debbbe0d6a29cc0a668b08578766cc364f32d
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., 
15 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 *****************************************************************************/
19 /********************************************************************//**
20 @file include/mem0mem.ic
21 The memory management
23 Created 6/8/1994 Heikki Tuuri
24 *************************************************************************/
26 #include "mem0dbg.ic"
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) */
35 UNIV_INTERN
36 mem_block_t*
37 mem_heap_create_block(
38 /*==================*/
39         mem_heap_t*     heap,   /*!< in: memory heap or NULL if first block
40                                 should be created */
41         ulint           n,      /*!< in: number of bytes needed for user data */
42         ulint           type,   /*!< in: type of heap: MEM_HEAP_DYNAMIC or
43                                 MEM_HEAP_BUFFER */
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. */
48 UNIV_INTERN
49 void
50 mem_heap_block_free(
51 /*================*/
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. */
57 UNIV_INTERN
58 void
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) */
67 UNIV_INTERN
68 mem_block_t*
69 mem_heap_add_block(
70 /*===============*/
71         mem_heap_t*     heap,   /*!< in: memory heap */
72         ulint           n);     /*!< in: number of bytes user needs */
74 UNIV_INLINE
75 void
76 mem_block_set_len(mem_block_t* block, ulint len)
78         ut_ad(len > 0);
80         block->len = len;
83 UNIV_INLINE
84 ulint
85 mem_block_get_len(mem_block_t* block)
87         return(block->len);
90 UNIV_INLINE
91 void
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));
97         block->type = type;
100 UNIV_INLINE
101 ulint
102 mem_block_get_type(mem_block_t* block)
104         return(block->type);
107 UNIV_INLINE
108 void
109 mem_block_set_free(mem_block_t* block, ulint free)
111         ut_ad(free > 0);
112         ut_ad(free <= mem_block_get_len(block));
114         block->free = free;
117 UNIV_INLINE
118 ulint
119 mem_block_get_free(mem_block_t* block)
121         return(block->free);
124 UNIV_INLINE
125 void
126 mem_block_set_start(mem_block_t* block, ulint start)
128         ut_ad(start > 0);
130         block->start = start;
133 UNIV_INLINE
134 ulint
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 */
143 UNIV_INLINE
144 void*
145 mem_heap_zalloc(
146 /*============*/
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 */
152         ut_ad(heap);
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) */
161 UNIV_INLINE
162 void*
163 mem_heap_alloc(
164 /*===========*/
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 */
170         mem_block_t*    block;
171         void*           buf;
172         ulint           free;
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
181         block to the heap */
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);
188                 if (block == NULL) {
190                         return(NULL);
191                 }
192         }
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
201         UNIV_MEM_ALLOC(buf,
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
208         caller */
209         buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
211 #endif
212         UNIV_MEM_ALLOC(buf, n);
213         return(buf);
216 /*****************************************************************//**
217 Returns a pointer to the heap top.
218 @return pointer to the heap top */
219 UNIV_INLINE
220 byte*
221 mem_heap_get_heap_top(
222 /*==================*/
223         mem_heap_t*     heap)   /*!< in: memory heap */
225         mem_block_t*    block;
226         byte*           buf;
228         ut_ad(mem_heap_check(heap));
230         block = UT_LIST_GET_LAST(heap->base);
232         buf = (byte*)block + mem_block_get_free(block);
234         return(buf);
237 /*****************************************************************//**
238 Frees the space in a memory heap exceeding the pointer given. The
239 pointer must have been acquired from mem_heap_get_heap_top. The first
240 memory block of the heap is not freed. */
241 UNIV_INLINE
242 void
243 mem_heap_free_heap_top(
244 /*===================*/
245         mem_heap_t*     heap,   /*!< in: heap from which to free */
246         byte*           old_top)/*!< in: pointer to old top of heap */
248         mem_block_t*    block;
249         mem_block_t*    prev_block;
250 #ifdef UNIV_MEM_DEBUG
251         ibool           error;
252         ulint           total_size;
253         ulint           size;
254 #endif
256         ut_ad(mem_heap_check(heap));
258 #ifdef UNIV_MEM_DEBUG
260         /* Validate the heap and get its total allocated size */
261         mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size,
262                                    NULL, NULL);
263         ut_a(!error);
265         /* Get the size below top pointer */
266         mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL,
267                                    NULL);
268         ut_a(!error);
270 #endif
272         block = UT_LIST_GET_LAST(heap->base);
274         while (block != NULL) {
275                 if (((byte*)block + mem_block_get_free(block) >= old_top)
276                     && ((byte*)block <= old_top)) {
277                         /* Found the right block */
279                         break;
280                 }
282                 /* Store prev_block value before freeing the current block
283                 (the current block will be erased in freeing) */
285                 prev_block = UT_LIST_GET_PREV(list, block);
287                 mem_heap_block_free(heap, block);
289                 block = prev_block;
290         }
292         ut_ad(block);
294         /* Set the free field of block */
295         mem_block_set_free(block, old_top - (byte*)block);
297 #ifdef UNIV_MEM_DEBUG
298         ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
300         /* In the debug version erase block from top up */
301         mem_erase_buf(old_top, (byte*)block + block->len - old_top);
303         /* Update allocated memory count */
304         mutex_enter(&mem_hash_mutex);
305         mem_current_allocated_memory -= (total_size - size);
306         mutex_exit(&mem_hash_mutex);
307 #else /* UNIV_MEM_DEBUG */
308         UNIV_MEM_ASSERT_W(old_top, (byte*)block + block->len - old_top);
309 #endif /* UNIV_MEM_DEBUG */
310         UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top);
312         /* If free == start, we may free the block if it is not the first
313         one */
315         if ((heap != block) && (mem_block_get_free(block)
316                                 == mem_block_get_start(block))) {
317                 mem_heap_block_free(heap, block);
318         }
321 /*****************************************************************//**
322 Empties a memory heap. The first memory block of the heap is not freed. */
323 UNIV_INLINE
324 void
325 mem_heap_empty(
326 /*===========*/
327         mem_heap_t*     heap)   /*!< in: heap to empty */
329         mem_heap_free_heap_top(heap, (byte*)heap + mem_block_get_start(heap));
330 #ifndef UNIV_HOTBACKUP
331         if (heap->free_block) {
332                 mem_heap_free_block_free(heap);
333         }
334 #endif /* !UNIV_HOTBACKUP */
337 /*****************************************************************//**
338 Returns a pointer to the topmost element in a memory heap. The size of the
339 element must be given.
340 @return pointer to the topmost element */
341 UNIV_INLINE
342 void*
343 mem_heap_get_top(
344 /*=============*/
345         mem_heap_t*     heap,   /*!< in: memory heap */
346         ulint           n)      /*!< in: size of the topmost element */
348         mem_block_t*    block;
349         void*           buf;
351         ut_ad(mem_heap_check(heap));
353         block = UT_LIST_GET_LAST(heap->base);
355         buf = (byte*)block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n);
357 #ifdef UNIV_MEM_DEBUG
358         ut_ad(mem_block_get_start(block) <=(ulint)((byte*)buf - (byte*)block));
360         /* In the debug version, advance buf to point at the storage which
361         was given to the caller in the allocation*/
363         buf = (byte*)buf + MEM_FIELD_HEADER_SIZE;
365         /* Check that the field lengths agree */
366         ut_ad(n == (ulint)mem_field_header_get_len(buf));
367 #endif
369         return(buf);
372 /*****************************************************************//**
373 Frees the topmost element in a memory heap. The size of the element must be
374 given. */
375 UNIV_INLINE
376 void
377 mem_heap_free_top(
378 /*==============*/
379         mem_heap_t*     heap,   /*!< in: memory heap */
380         ulint           n)      /*!< in: size of the topmost element */
382         mem_block_t*    block;
384         ut_ad(mem_heap_check(heap));
386         block = UT_LIST_GET_LAST(heap->base);
388         /* Subtract the free field of block */
389         mem_block_set_free(block, mem_block_get_free(block)
390                            - MEM_SPACE_NEEDED(n));
391         UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n);
392 #ifdef UNIV_MEM_DEBUG
394         ut_ad(mem_block_get_start(block) <= mem_block_get_free(block));
396         /* In the debug version check the consistency, and erase field */
397         mem_field_erase((byte*)block + mem_block_get_free(block), n);
398 #endif
400         /* If free == start, we may free the block if it is not the first
401         one */
403         if ((heap != block) && (mem_block_get_free(block)
404                                 == mem_block_get_start(block))) {
405                 mem_heap_block_free(heap, block);
406         } else {
407                 /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a
408                 subsequent invocation of mem_heap_free_top().
409                 Originally, this was UNIV_MEM_FREE(), to catch writes
410                 to freed memory. */
411                 UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n);
412         }
415 /*****************************************************************//**
416 NOTE: Use the corresponding macros instead of this function. Creates a
417 memory heap. For debugging purposes, takes also the file name and line as
418 argument.
419 @return own: memory heap, NULL if did not succeed (only possible for
420 MEM_HEAP_BTR_SEARCH type heaps) */
421 UNIV_INLINE
422 mem_heap_t*
423 mem_heap_create_func(
424 /*=================*/
425         ulint           n,              /*!< in: desired start block size,
426                                         this means that a single user buffer
427                                         of size n will fit in the block,
428                                         0 creates a default size block */
429         ulint           type,           /*!< in: heap type */
430         const char*     file_name,      /*!< in: file name where created */
431         ulint           line)           /*!< in: line where created */
433         mem_block_t*   block;
435         if (!n) {
436                 n = MEM_BLOCK_START_SIZE;
437         }
439         block = mem_heap_create_block(NULL, n, type, file_name, line);
441         if (block == NULL) {
443                 return(NULL);
444         }
446         UT_LIST_INIT(block->base);
448         /* Add the created block itself as the first block in the list */
449         UT_LIST_ADD_FIRST(list, block->base, block);
451 #ifdef UNIV_MEM_DEBUG
453         mem_hash_insert(block, file_name, line);
455 #endif
457         return(block);
460 /*****************************************************************//**
461 NOTE: Use the corresponding macro instead of this function. Frees the space
462 occupied by a memory heap. In the debug version erases the heap memory
463 blocks. */
464 UNIV_INLINE
465 void
466 mem_heap_free_func(
467 /*===============*/
468         mem_heap_t*     heap,           /*!< in, own: heap to be freed */
469         const char*     file_name __attribute__((unused)),
470                                         /*!< in: file name where freed */
471         ulint           line  __attribute__((unused)))
473         mem_block_t*    block;
474         mem_block_t*    prev_block;
476         ut_ad(mem_heap_check(heap));
478         block = UT_LIST_GET_LAST(heap->base);
480 #ifdef UNIV_MEM_DEBUG
482         /* In the debug version remove the heap from the hash table of heaps
483         and check its consistency */
485         mem_hash_remove(heap, file_name, line);
487 #endif
488 #ifndef UNIV_HOTBACKUP
489         if (heap->free_block) {
490                 mem_heap_free_block_free(heap);
491         }
492 #endif /* !UNIV_HOTBACKUP */
494         while (block != NULL) {
495                 /* Store the contents of info before freeing current block
496                 (it is erased in freeing) */
498                 prev_block = UT_LIST_GET_PREV(list, block);
500                 mem_heap_block_free(heap, block);
502                 block = prev_block;
503         }
506 /***************************************************************//**
507 NOTE: Use the corresponding macro instead of this function.
508 Allocates a single buffer of memory from the dynamic memory of
509 the C compiler. Is like malloc of C. The buffer must be freed
510 with mem_free.
511 @return own: free storage */
512 UNIV_INLINE
513 void*
514 mem_alloc_func(
515 /*===========*/
516         ulint           n,              /*!< in: desired number of bytes */
517         ulint*          size,           /*!< out: allocated size in bytes,
518                                         or NULL */
519         const char*     file_name,      /*!< in: file name where created */
520         ulint           line)           /*!< in: line where created */
522         mem_heap_t*     heap;
523         void*           buf;
525         heap = mem_heap_create_func(n, MEM_HEAP_DYNAMIC, file_name, line);
527         /* Note that as we created the first block in the heap big enough
528         for the buffer requested by the caller, the buffer will be in the
529         first block and thus we can calculate the pointer to the heap from
530         the pointer to the buffer when we free the memory buffer. */
532         if (UNIV_LIKELY_NULL(size)) {
533                 /* Adjust the allocation to the actual size of the
534                 memory block. */
535                 ulint   m = mem_block_get_len(heap)
536                         - mem_block_get_free(heap);
537 #ifdef UNIV_MEM_DEBUG
538                 m -= MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE;
539 #endif /* UNIV_MEM_DEBUG */
540                 ut_ad(m >= n);
541                 *size = n = m;
542         }
544         buf = mem_heap_alloc(heap, n);
546         ut_a((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
547              - MEM_FIELD_HEADER_SIZE);
548         return(buf);
551 /***************************************************************//**
552 NOTE: Use the corresponding macro instead of this function. Frees a single
553 buffer of storage from the dynamic memory of the C compiler. Similar to the
554 free of C. */
555 UNIV_INLINE
556 void
557 mem_free_func(
558 /*==========*/
559         void*           ptr,            /*!< in, own: buffer to be freed */
560         const char*     file_name,      /*!< in: file name where created */
561         ulint           line)           /*!< in: line where created */
563         mem_heap_t*   heap;
565         heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
566                              - MEM_FIELD_HEADER_SIZE);
567         mem_heap_free_func(heap, file_name, line);
570 /*****************************************************************//**
571 Returns the space in bytes occupied by a memory heap. */
572 UNIV_INLINE
573 ulint
574 mem_heap_get_size(
575 /*==============*/
576         mem_heap_t*     heap)   /*!< in: heap */
578         ulint           size    = 0;
580         ut_ad(mem_heap_check(heap));
582         size = heap->total_size;
584 #ifndef UNIV_HOTBACKUP
585         if (heap->free_block) {
586                 size += UNIV_PAGE_SIZE;
587         }
588 #endif /* !UNIV_HOTBACKUP */
590         return(size);
593 /**********************************************************************//**
594 Duplicates a NUL-terminated string.
595 @return own: a copy of the string, must be deallocated with mem_free */
596 UNIV_INLINE
597 char*
598 mem_strdup(
599 /*=======*/
600         const char*     str)    /*!< in: string to be copied */
602         ulint   len = strlen(str) + 1;
603         return((char*) memcpy(mem_alloc(len), str, len));
606 /**********************************************************************//**
607 Makes a NUL-terminated copy of a nonterminated string.
608 @return own: a copy of the string, must be deallocated with mem_free */
609 UNIV_INLINE
610 char*
611 mem_strdupl(
612 /*========*/
613         const char*     str,    /*!< in: string to be copied */
614         ulint           len)    /*!< in: length of str, in bytes */
616         char*   s = (char*) mem_alloc(len + 1);
617         s[len] = 0;
618         return((char*) memcpy(s, str, len));
621 /**********************************************************************//**
622 Makes a NUL-terminated copy of a nonterminated string,
623 allocated from a memory heap.
624 @return own: a copy of the string */
625 UNIV_INLINE
626 char*
627 mem_heap_strdupl(
628 /*=============*/
629         mem_heap_t*     heap,   /*!< in: memory heap where string is allocated */
630         const char*     str,    /*!< in: string to be copied */
631         ulint           len)    /*!< in: length of str, in bytes */
633         char*   s = (char*) mem_heap_alloc(heap, len + 1);
634         s[len] = 0;
635         return((char*) memcpy(s, str, len));