1/***************************************************************************** 2 3Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. 4 5This program is free software; you can redistribute it and/or modify 6it under the terms of the GNU General Public License, version 2.0, 7as published by the Free Software Foundation. 8 9This program is also distributed with certain software (including 10but not limited to OpenSSL) that is licensed under separate terms, 11as designated in a particular file or component or in included license 12documentation. The authors of MySQL hereby grant you an additional 13permission to link the program and your derivative works with the 14separately licensed software that they have included with MySQL. 15 16This program is distributed in the hope that it will be useful, 17but WITHOUT ANY WARRANTY; without even the implied warranty of 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19GNU General Public License, version 2.0, for more details. 20 21You should have received a copy of the GNU General Public License along with 22this program; if not, write to the Free Software Foundation, Inc., 2351 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 24 25*****************************************************************************/ 26 27/********************************************************************//** 28@file include/mem0mem.ic 29The memory management 30 31Created 6/8/1994 Heikki Tuuri 32*************************************************************************/ 33 34#include "mem0dbg.ic" 35#ifndef UNIV_HOTBACKUP 36# include "mem0pool.h" 37#endif /* !UNIV_HOTBACKUP */ 38 39#ifdef UNIV_DEBUG 40# define mem_heap_create_block(heap, n, type, file_name, line) \ 41 mem_heap_create_block_func(heap, n, file_name, line, type) 42# define mem_heap_create_at(N, file_name, line) \ 43 mem_heap_create_func(N, file_name, line, MEM_HEAP_DYNAMIC) 44#else /* UNIV_DEBUG */ 45# define mem_heap_create_block(heap, n, type, file_name, line) \ 46 mem_heap_create_block_func(heap, n, type) 47# define mem_heap_create_at(N, file_name, line) \ 48 mem_heap_create_func(N, MEM_HEAP_DYNAMIC) 49#endif /* UNIV_DEBUG */ 50/***************************************************************//** 51Creates a memory heap block where data can be allocated. 52@return own: memory heap block, NULL if did not succeed (only possible 53for MEM_HEAP_BTR_SEARCH type heaps) */ 54UNIV_INTERN 55mem_block_t* 56mem_heap_create_block_func( 57/*=======================*/ 58 mem_heap_t* heap, /*!< in: memory heap or NULL if first block 59 should be created */ 60 ulint n, /*!< in: number of bytes needed for user data */ 61#ifdef UNIV_DEBUG 62 const char* file_name,/*!< in: file name where created */ 63 ulint line, /*!< in: line where created */ 64#endif /* UNIV_DEBUG */ 65 ulint type); /*!< in: type of heap: MEM_HEAP_DYNAMIC or 66 MEM_HEAP_BUFFER */ 67/******************************************************************//** 68Frees a block from a memory heap. */ 69UNIV_INTERN 70void 71mem_heap_block_free( 72/*================*/ 73 mem_heap_t* heap, /*!< in: heap */ 74 mem_block_t* block); /*!< in: block to free */ 75#ifndef UNIV_HOTBACKUP 76/******************************************************************//** 77Frees the free_block field from a memory heap. */ 78UNIV_INTERN 79void 80mem_heap_free_block_free( 81/*=====================*/ 82 mem_heap_t* heap); /*!< in: heap */ 83#endif /* !UNIV_HOTBACKUP */ 84/***************************************************************//** 85Adds a new block to a memory heap. 86@return created block, NULL if did not succeed (only possible for 87MEM_HEAP_BTR_SEARCH type heaps) */ 88UNIV_INTERN 89mem_block_t* 90mem_heap_add_block( 91/*===============*/ 92 mem_heap_t* heap, /*!< in: memory heap */ 93 ulint n); /*!< in: number of bytes user needs */ 94 95UNIV_INLINE 96void 97mem_block_set_len(mem_block_t* block, ulint len) 98{ 99 ut_ad(len > 0); 100 101 block->len = len; 102} 103 104UNIV_INLINE 105ulint 106mem_block_get_len(mem_block_t* block) 107{ 108 return(block->len); 109} 110 111UNIV_INLINE 112void 113mem_block_set_type(mem_block_t* block, ulint type) 114{ 115 ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER) 116 || (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH)); 117 118 block->type = type; 119} 120 121UNIV_INLINE 122ulint 123mem_block_get_type(mem_block_t* block) 124{ 125 return(block->type); 126} 127 128UNIV_INLINE 129void 130mem_block_set_free(mem_block_t* block, ulint free) 131{ 132 ut_ad(free > 0); 133 ut_ad(free <= mem_block_get_len(block)); 134 135 block->free = free; 136} 137 138UNIV_INLINE 139ulint 140mem_block_get_free(mem_block_t* block) 141{ 142 return(block->free); 143} 144 145UNIV_INLINE 146void 147mem_block_set_start(mem_block_t* block, ulint start) 148{ 149 ut_ad(start > 0); 150 151 block->start = start; 152} 153 154UNIV_INLINE 155ulint 156mem_block_get_start(mem_block_t* block) 157{ 158 return(block->start); 159} 160 161/***************************************************************//** 162Allocates and zero-fills n bytes of memory from a memory heap. 163@return allocated, zero-filled storage */ 164UNIV_INLINE 165void* 166mem_heap_zalloc( 167/*============*/ 168 mem_heap_t* heap, /*!< in: memory heap */ 169 ulint n) /*!< in: number of bytes; if the heap is allowed 170 to grow into the buffer pool, this must be 171 <= MEM_MAX_ALLOC_IN_BUF */ 172{ 173 ut_ad(heap); 174 ut_ad(!(heap->type & MEM_HEAP_BTR_SEARCH)); 175 return(memset(mem_heap_alloc(heap, n), 0, n)); 176} 177 178/***************************************************************//** 179Allocates n bytes of memory from a memory heap. 180@return allocated storage, NULL if did not succeed (only possible for 181MEM_HEAP_BTR_SEARCH type heaps) */ 182UNIV_INLINE 183void* 184mem_heap_alloc( 185/*===========*/ 186 mem_heap_t* heap, /*!< in: memory heap */ 187 ulint n) /*!< in: number of bytes; if the heap is allowed 188 to grow into the buffer pool, this must be 189 <= MEM_MAX_ALLOC_IN_BUF */ 190{ 191 mem_block_t* block; 192 void* buf; 193 ulint free; 194 195 ut_ad(mem_heap_check(heap)); 196 197 block = UT_LIST_GET_LAST(heap->base); 198 199 ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF)); 200 201 /* Check if there is enough space in block. If not, create a new 202 block to the heap */ 203 204 if (mem_block_get_len(block) 205 < mem_block_get_free(block) + MEM_SPACE_NEEDED(n)) { 206 207 block = mem_heap_add_block(heap, n); 208 209 if (block == NULL) { 210 211 return(NULL); 212 } 213 } 214 215 free = mem_block_get_free(block); 216 217 buf = (byte*) block + free; 218 219 mem_block_set_free(block, free + MEM_SPACE_NEEDED(n)); 220 221#ifdef UNIV_MEM_DEBUG 222 UNIV_MEM_ALLOC(buf, 223 n + MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE); 224 225 /* In the debug version write debugging info to the field */ 226 mem_field_init((byte*) buf, n); 227 228 /* Advance buf to point at the storage which will be given to the 229 caller */ 230 buf = (byte*) buf + MEM_FIELD_HEADER_SIZE; 231 232#endif 233 UNIV_MEM_ALLOC(buf, n); 234 return(buf); 235} 236 237/*****************************************************************//** 238Returns a pointer to the heap top. 239@return pointer to the heap top */ 240UNIV_INLINE 241byte* 242mem_heap_get_heap_top( 243/*==================*/ 244 mem_heap_t* heap) /*!< in: memory heap */ 245{ 246 mem_block_t* block; 247 byte* buf; 248 249 ut_ad(mem_heap_check(heap)); 250 251 block = UT_LIST_GET_LAST(heap->base); 252 253 buf = (byte*) block + mem_block_get_free(block); 254 255 return(buf); 256} 257 258/*****************************************************************//** 259Frees the space in a memory heap exceeding the pointer given. The 260pointer must have been acquired from mem_heap_get_heap_top. The first 261memory block of the heap is not freed. */ 262UNIV_INLINE 263void 264mem_heap_free_heap_top( 265/*===================*/ 266 mem_heap_t* heap, /*!< in: heap from which to free */ 267 byte* old_top)/*!< in: pointer to old top of heap */ 268{ 269 mem_block_t* block; 270 mem_block_t* prev_block; 271#if defined UNIV_MEM_DEBUG || defined UNIV_DEBUG 272 ibool error; 273 ulint total_size; 274 ulint size; 275 276 ut_ad(mem_heap_check(heap)); 277 278 /* Validate the heap and get its total allocated size */ 279 mem_heap_validate_or_print(heap, NULL, FALSE, &error, &total_size, 280 NULL, NULL); 281 ut_a(!error); 282 283 /* Get the size below top pointer */ 284 mem_heap_validate_or_print(heap, old_top, FALSE, &error, &size, NULL, 285 NULL); 286 ut_a(!error); 287 288#endif 289 290 block = UT_LIST_GET_LAST(heap->base); 291 292 while (block != NULL) { 293 if (((byte*) block + mem_block_get_free(block) >= old_top) 294 && ((byte*) block <= old_top)) { 295 /* Found the right block */ 296 297 break; 298 } 299 300 /* Store prev_block value before freeing the current block 301 (the current block will be erased in freeing) */ 302 303 prev_block = UT_LIST_GET_PREV(list, block); 304 305 mem_heap_block_free(heap, block); 306 307 block = prev_block; 308 } 309 310 ut_ad(block); 311 312 /* Set the free field of block */ 313 mem_block_set_free(block, old_top - (byte*) block); 314 315 ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); 316 UNIV_MEM_ASSERT_W(old_top, (byte*) block + block->len - old_top); 317#if defined UNIV_MEM_DEBUG 318 /* In the debug version erase block from top up */ 319 mem_erase_buf(old_top, (byte*) block + block->len - old_top); 320 321 /* Update allocated memory count */ 322 mutex_enter(&mem_hash_mutex); 323 mem_current_allocated_memory -= (total_size - size); 324 mutex_exit(&mem_hash_mutex); 325#endif /* UNIV_MEM_DEBUG */ 326 UNIV_MEM_ALLOC(old_top, (byte*) block + block->len - old_top); 327 328 /* If free == start, we may free the block if it is not the first 329 one */ 330 331 if ((heap != block) && (mem_block_get_free(block) 332 == mem_block_get_start(block))) { 333 mem_heap_block_free(heap, block); 334 } 335} 336 337/*****************************************************************//** 338Empties a memory heap. The first memory block of the heap is not freed. */ 339UNIV_INLINE 340void 341mem_heap_empty( 342/*===========*/ 343 mem_heap_t* heap) /*!< in: heap to empty */ 344{ 345 mem_heap_free_heap_top(heap, (byte*) heap + mem_block_get_start(heap)); 346#ifndef UNIV_HOTBACKUP 347 if (heap->free_block) { 348 mem_heap_free_block_free(heap); 349 } 350#endif /* !UNIV_HOTBACKUP */ 351} 352 353/*****************************************************************//** 354Returns a pointer to the topmost element in a memory heap. The size of the 355element must be given. 356@return pointer to the topmost element */ 357UNIV_INLINE 358void* 359mem_heap_get_top( 360/*=============*/ 361 mem_heap_t* heap, /*!< in: memory heap */ 362 ulint n) /*!< in: size of the topmost element */ 363{ 364 mem_block_t* block; 365 byte* buf; 366 367 ut_ad(mem_heap_check(heap)); 368 369 block = UT_LIST_GET_LAST(heap->base); 370 371 buf = (byte*) block + mem_block_get_free(block) - MEM_SPACE_NEEDED(n); 372 373#ifdef UNIV_MEM_DEBUG 374 ut_ad(mem_block_get_start(block) <= (ulint) (buf - (byte*) block)); 375 376 /* In the debug version, advance buf to point at the storage which 377 was given to the caller in the allocation*/ 378 379 buf += MEM_FIELD_HEADER_SIZE; 380 381 /* Check that the field lengths agree */ 382 ut_ad(n == mem_field_header_get_len(buf)); 383#endif 384 385 return((void*) buf); 386} 387 388/*****************************************************************//** 389Frees the topmost element in a memory heap. The size of the element must be 390given. */ 391UNIV_INLINE 392void 393mem_heap_free_top( 394/*==============*/ 395 mem_heap_t* heap, /*!< in: memory heap */ 396 ulint n) /*!< in: size of the topmost element */ 397{ 398 mem_block_t* block; 399 400 ut_ad(mem_heap_check(heap)); 401 402 block = UT_LIST_GET_LAST(heap->base); 403 404 /* Subtract the free field of block */ 405 mem_block_set_free(block, mem_block_get_free(block) 406 - MEM_SPACE_NEEDED(n)); 407 UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n); 408#ifdef UNIV_MEM_DEBUG 409 410 ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); 411 412 /* In the debug version check the consistency, and erase field */ 413 mem_field_erase((byte*) block + mem_block_get_free(block), n); 414#endif 415 416 /* If free == start, we may free the block if it is not the first 417 one */ 418 419 if ((heap != block) && (mem_block_get_free(block) 420 == mem_block_get_start(block))) { 421 mem_heap_block_free(heap, block); 422 } else { 423 /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a 424 subsequent invocation of mem_heap_free_top(). 425 Originally, this was UNIV_MEM_FREE(), to catch writes 426 to freed memory. */ 427 UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n); 428 } 429} 430 431/*****************************************************************//** 432NOTE: Use the corresponding macros instead of this function. Creates a 433memory heap. For debugging purposes, takes also the file name and line as 434argument. 435@return own: memory heap, NULL if did not succeed (only possible for 436MEM_HEAP_BTR_SEARCH type heaps) */ 437UNIV_INLINE 438mem_heap_t* 439mem_heap_create_func( 440/*=================*/ 441 ulint n, /*!< in: desired start block size, 442 this means that a single user buffer 443 of size n will fit in the block, 444 0 creates a default size block */ 445#ifdef UNIV_DEBUG 446 const char* file_name, /*!< in: file name where created */ 447 ulint line, /*!< in: line where created */ 448#endif /* UNIV_DEBUG */ 449 ulint type) /*!< in: heap type */ 450{ 451 mem_block_t* block; 452 453 if (!n) { 454 n = MEM_BLOCK_START_SIZE; 455 } 456 457 block = mem_heap_create_block(NULL, n, type, file_name, line); 458 459 if (block == NULL) { 460 461 return(NULL); 462 } 463 464 UT_LIST_INIT(block->base); 465 466 /* Add the created block itself as the first block in the list */ 467 UT_LIST_ADD_FIRST(list, block->base, block); 468 469#ifdef UNIV_MEM_DEBUG 470 471 mem_hash_insert(block, file_name, line); 472 473#endif 474 475 return(block); 476} 477 478/*****************************************************************//** 479NOTE: Use the corresponding macro instead of this function. Frees the space 480occupied by a memory heap. In the debug version erases the heap memory 481blocks. */ 482UNIV_INLINE 483void 484mem_heap_free_func( 485/*===============*/ 486 mem_heap_t* heap, /*!< in, own: heap to be freed */ 487 const char* file_name MY_ATTRIBUTE((unused)), 488 /*!< in: file name where freed */ 489 ulint line MY_ATTRIBUTE((unused))) 490{ 491 mem_block_t* block; 492 mem_block_t* prev_block; 493 494 ut_ad(mem_heap_check(heap)); 495 496 block = UT_LIST_GET_LAST(heap->base); 497 498#ifdef UNIV_MEM_DEBUG 499 500 /* In the debug version remove the heap from the hash table of heaps 501 and check its consistency */ 502 503 mem_hash_remove(heap, file_name, line); 504 505#endif 506#ifndef UNIV_HOTBACKUP 507 if (heap->free_block) { 508 mem_heap_free_block_free(heap); 509 } 510#endif /* !UNIV_HOTBACKUP */ 511 512 while (block != NULL) { 513 /* Store the contents of info before freeing current block 514 (it is erased in freeing) */ 515 516 prev_block = UT_LIST_GET_PREV(list, block); 517 518 mem_heap_block_free(heap, block); 519 520 block = prev_block; 521 } 522} 523 524/***************************************************************//** 525NOTE: Use the corresponding macro instead of this function. 526Allocates a single buffer of memory from the dynamic memory of 527the C compiler. Is like malloc of C. The buffer must be freed 528with mem_free. 529@return own: free storage */ 530UNIV_INLINE 531void* 532mem_alloc_func( 533/*===========*/ 534 ulint n, /*!< in: desired number of bytes */ 535#ifdef UNIV_DEBUG 536 const char* file_name, /*!< in: file name where created */ 537 ulint line, /*!< in: line where created */ 538#endif /* UNIV_DEBUG */ 539 ulint* size) /*!< out: allocated size in bytes, 540 or NULL */ 541{ 542 mem_heap_t* heap; 543 void* buf; 544 545 heap = mem_heap_create_at(n, file_name, line); 546 547 /* Note that as we created the first block in the heap big enough 548 for the buffer requested by the caller, the buffer will be in the 549 first block and thus we can calculate the pointer to the heap from 550 the pointer to the buffer when we free the memory buffer. */ 551 552 if (size) { 553 /* Adjust the allocation to the actual size of the 554 memory block. */ 555 ulint m = mem_block_get_len(heap) 556 - mem_block_get_free(heap); 557#ifdef UNIV_MEM_DEBUG 558 m -= MEM_FIELD_HEADER_SIZE + MEM_FIELD_TRAILER_SIZE; 559#endif /* UNIV_MEM_DEBUG */ 560 ut_ad(m >= n); 561 n = m; 562 *size = m; 563 } 564 565 buf = mem_heap_alloc(heap, n); 566 567 ut_a((byte*) heap == (byte*) buf - MEM_BLOCK_HEADER_SIZE 568 - MEM_FIELD_HEADER_SIZE); 569 return(buf); 570} 571 572/***************************************************************//** 573NOTE: Use the corresponding macro instead of this function. Frees a single 574buffer of storage from the dynamic memory of the C compiler. Similar to the 575free of C. */ 576UNIV_INLINE 577void 578mem_free_func( 579/*==========*/ 580 void* ptr, /*!< in, own: buffer to be freed */ 581 const char* file_name, /*!< in: file name where created */ 582 ulint line) /*!< in: line where created */ 583{ 584 mem_heap_t* heap; 585 586 heap = (mem_heap_t*)((byte*) ptr - MEM_BLOCK_HEADER_SIZE 587 - MEM_FIELD_HEADER_SIZE); 588 mem_heap_free_func(heap, file_name, line); 589} 590 591/*****************************************************************//** 592Returns the space in bytes occupied by a memory heap. */ 593UNIV_INLINE 594ulint 595mem_heap_get_size( 596/*==============*/ 597 mem_heap_t* heap) /*!< in: heap */ 598{ 599 ulint size = 0; 600 601 ut_ad(mem_heap_check(heap)); 602 603 size = heap->total_size; 604 605#ifndef UNIV_HOTBACKUP 606 if (heap->free_block) { 607 size += UNIV_PAGE_SIZE; 608 } 609#endif /* !UNIV_HOTBACKUP */ 610 611 return(size); 612} 613 614/**********************************************************************//** 615Duplicates a NUL-terminated string. 616@return own: a copy of the string, must be deallocated with mem_free */ 617UNIV_INLINE 618char* 619mem_strdup( 620/*=======*/ 621 const char* str) /*!< in: string to be copied */ 622{ 623 ulint len = strlen(str) + 1; 624 return((char*) memcpy(mem_alloc(len), str, len)); 625} 626 627/**********************************************************************//** 628Makes a NUL-terminated copy of a nonterminated string. 629@return own: a copy of the string, must be deallocated with mem_free */ 630UNIV_INLINE 631char* 632mem_strdupl( 633/*========*/ 634 const char* str, /*!< in: string to be copied */ 635 ulint len) /*!< in: length of str, in bytes */ 636{ 637 char* s = (char*) mem_alloc(len + 1); 638 s[len] = 0; 639 return((char*) memcpy(s, str, len)); 640} 641 642/**********************************************************************//** 643Makes a NUL-terminated copy of a nonterminated string, 644allocated from a memory heap. 645@return own: a copy of the string */ 646UNIV_INLINE 647char* 648mem_heap_strdupl( 649/*=============*/ 650 mem_heap_t* heap, /*!< in: memory heap where string is allocated */ 651 const char* str, /*!< in: string to be copied */ 652 ulint len) /*!< in: length of str, in bytes */ 653{ 654 char* s = (char*) mem_heap_alloc(heap, len + 1); 655 s[len] = 0; 656 return((char*) memcpy(s, str, len)); 657} 658