/********************************************************************//** Creates a memory pool. @return memory pool */ UNIV_INTERN mem_pool_t* mem_pool_create( /*============*/ ulint size) /*!< in: pool size in bytes */ { mem_pool_t* pool; mem_area_t* area; ulint i; ulint used; pool = ut_malloc(sizeof(mem_pool_t)); pool->buf = ut_malloc_low(size, TRUE); pool->size = size; mutex_create(&pool->mutex, SYNC_MEM_POOL); /* Initialize the free lists */ for (i = 0; i < 64; i++) { UT_LIST_INIT(pool->free_list[i]); } used = 0; while (size - used >= MEM_AREA_MIN_SIZE) { i = ut_2_log(size - used); if (ut_2_exp(i) > size - used) { /* ut_2_log rounds upward */ i--; } area = (mem_area_t*)(pool->buf + used); mem_area_set_size(area, ut_2_exp(i)); mem_area_set_free(area, TRUE); UNIV_MEM_FREE(MEM_AREA_EXTRA_SIZE + (byte*) area, ut_2_exp(i) - MEM_AREA_EXTRA_SIZE); UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area); used = used + ut_2_exp(i); } ut_ad(size >= used); pool->reserved = 0; return(pool); }
/**********************************************************************//** Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is defined. @return own: allocated memory */ UNIV_INTERN void* ut_malloc( /*======*/ ulint n) /*!< in: number of bytes to allocate */ { #ifndef UNIV_HOTBACKUP return(ut_malloc_low(n, TRUE, TRUE)); #else /* !UNIV_HOTBACKUP */ return(malloc(n)); #endif /* !UNIV_HOTBACKUP */ }
/* allocate memory and zero-fills n bytes of memory */ UNIV_INTERN void* ut_zalloc(ulint n){ return (memset(ut_malloc_low(n,TRUE),0,n)); }
/****************************************************************//** Allocates large pages memory. @return allocated memory */ UNIV_INTERN void* os_mem_alloc_large( /*===============*/ ulint* n) /*!< in/out: number of bytes */ { void* ptr; ulint size; #if defined HAVE_LARGE_PAGES && defined UNIV_LINUX int shmid; struct shmid_ds buf; if (!os_use_large_pages || !os_large_page_size) { goto skip; } /* Align block size to os_large_page_size */ ut_ad(ut_is_2pow(os_large_page_size)); size = ut_2pow_round(*n + (os_large_page_size - 1), os_large_page_size); shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W); if (shmid < 0) { fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate" " %lu bytes. errno %d\n", size, errno); ptr = NULL; } else { ptr = shmat(shmid, NULL, 0); if (ptr == (void *)-1) { fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to" " attach shared memory segment, errno %d\n", errno); ptr = NULL; } /* Remove the shared memory segment so that it will be automatically freed after memory is detached or process exits */ shmctl(shmid, IPC_RMID, &buf); } if (ptr) { *n = size; os_fast_mutex_lock(&ut_list_mutex); ut_total_allocated_memory += size; os_fast_mutex_unlock(&ut_list_mutex); UNIV_MEM_ALLOC(ptr, size); return(ptr); } fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional" " memory pool\n"); skip: #endif /* HAVE_LARGE_PAGES && UNIV_LINUX */ #ifdef __WIN__ SYSTEM_INFO system_info; GetSystemInfo(&system_info); /* Align block size to system page size */ ut_ad(ut_is_2pow(system_info.dwPageSize)); /* system_info.dwPageSize is only 32-bit. Casting to ulint is required on 64-bit Windows. */ size = *n = ut_2pow_round(*n + (system_info.dwPageSize - 1), (ulint) system_info.dwPageSize); ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!ptr) { fprintf(stderr, "InnoDB: VirtualAlloc(%lu bytes) failed;" " Windows error %lu\n", (ulong) size, (ulong) GetLastError()); } else { os_fast_mutex_lock(&ut_list_mutex); ut_total_allocated_memory += size; os_fast_mutex_unlock(&ut_list_mutex); UNIV_MEM_ALLOC(ptr, size); } #elif !defined OS_MAP_ANON size = *n; ptr = ut_malloc_low(size, TRUE, FALSE); #else # ifdef HAVE_GETPAGESIZE size = getpagesize(); # else size = UNIV_PAGE_SIZE; # endif /* Align block size to system page size */ ut_ad(ut_is_2pow(size)); size = *n = ut_2pow_round(*n + (size - 1), size); ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | OS_MAP_ANON, -1, 0); if (UNIV_UNLIKELY(ptr == (void*) -1)) { fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;" " errno %lu\n", (ulong) size, (ulong) errno); ptr = NULL; } else { os_fast_mutex_lock(&ut_list_mutex); ut_total_allocated_memory += size; os_fast_mutex_unlock(&ut_list_mutex); UNIV_MEM_ALLOC(ptr, size); } #endif return(ptr); }
mem_pool_t* mem_pool_create( /*============*/ /* out: memory pool */ ulint size) /* in: pool size in bytes */ { mem_pool_t* pool; mem_area_t* area; ulint i; ulint used; ut_a(size > 10000); pool = ut_malloc(sizeof(mem_pool_t)); /* We do not set the memory to zero (FALSE) in the pool, but only when allocated at a higher level in mem0mem.c. This is to avoid masking useful Purify warnings. */ pool->buf = ut_malloc_low(size, FALSE, TRUE); pool->size = size; mutex_create(&pool->mutex, SYNC_MEM_POOL); /* Initialize the free lists */ for (i = 0; i < 64; i++) { UT_LIST_INIT(pool->free_list[i]); } used = 0; while (size - used >= MEM_AREA_MIN_SIZE) { i = ut_2_log(size - used); if (ut_2_exp(i) > size - used) { /* ut_2_log rounds upward */ i--; } area = (mem_area_t*)(pool->buf + used); mem_area_set_size(area, ut_2_exp(i)); mem_area_set_free(area, TRUE); UNIV_MEM_FREE(MEM_AREA_EXTRA_SIZE + (byte*) area, ut_2_exp(i) - MEM_AREA_EXTRA_SIZE); UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area); used = used + ut_2_exp(i); } ut_ad(size >= used); pool->reserved = 0; return(pool); }
void* os_mem_alloc_large( /*===============*/ /* out: allocated memory */ ulint n, /* in: number of bytes */ ibool set_to_zero, /* in: TRUE if allocated memory should be set to zero if UNIV_SET_MEM_TO_ZERO is defined */ ibool assert_on_error)/* in: if TRUE, we crash mysqld if the memory cannot be allocated */ { #ifdef HAVE_LARGE_PAGES ulint size; int shmid; void *ptr = NULL; struct shmid_ds buf; if (!os_use_large_pages || !os_large_page_size) { goto skip; } #ifdef UNIV_LINUX /* Align block size to os_large_page_size */ size = ((n - 1) & ~(os_large_page_size - 1)) + os_large_page_size; shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W); if (shmid < 0) { fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate" " %lu bytes. errno %d\n", n, errno); } else { ptr = shmat(shmid, NULL, 0); if (ptr == (void *)-1) { fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to" " attach shared memory segment, errno %d\n", errno); } /* Remove the shared memory segment so that it will be automatically freed after memory is detached or process exits */ shmctl(shmid, IPC_RMID, &buf); } #endif if (ptr) { if (set_to_zero) { #ifdef UNIV_SET_MEM_TO_ZERO memset(ptr, '\0', size); #endif } return(ptr); } fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional" " memory pool\n"); skip: #endif /* HAVE_LARGE_PAGES */ return(ut_malloc_low(n, set_to_zero, assert_on_error)); }