Commit 42bd3289 authored by marko's avatar marko

branches/zip: os_mem_alloc_large(), os_mem_free_large():

On POSIX, use mmap() and munmap().  On Windows, use VirtualAlloc()
and VirtualFree().  Only on Netware, use ut_malloc_low() and ut_free().
The lower-level functions on POSIX and Windows allow InnoDB to return
memory to the operating system when the buffer pool is shrunk.
parent 839ef125
......@@ -634,7 +634,6 @@ buf_pool_init(
byte* frame;
ulint i;
buf_block_t* block;
ulint n_frames = curr_size;
buf_pool = mem_alloc(sizeof(buf_pool_t));
......@@ -644,27 +643,35 @@ buf_pool_init(
mutex_enter(&(buf_pool->mutex));
buf_pool->frame_mem = os_mem_alloc_large(
UNIV_PAGE_SIZE * (n_frames + 1), TRUE, FALSE);
buf_pool->frame_mem_size = (curr_size + 1) * UNIV_PAGE_SIZE;
if (buf_pool->frame_mem == NULL) {
buf_pool->frame_mem = os_mem_alloc_large(&buf_pool->frame_mem_size);
if (UNIV_UNLIKELY(buf_pool->frame_mem == NULL)) {
return(NULL);
}
/* Align pointer to the first frame */
frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE);
curr_size = buf_pool->frame_mem_size / UNIV_PAGE_SIZE
- (frame != buf_pool->frame_mem);
buf_pool->blocks = ut_malloc(sizeof(buf_block_t) * curr_size);
if (buf_pool->blocks == NULL) {
if (UNIV_UNLIKELY(buf_pool->blocks == NULL)) {
os_mem_free_large(buf_pool->frame_mem,
buf_pool->frame_mem_size);
buf_pool->frame_mem = NULL;
return(NULL);
}
buf_pool->curr_size = curr_size;
/* Align pointer to the first frame */
frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE);
/* Init block structs and assign frames for them. Then we
assign the frames to the first blocks (we already mapped the
memory above). */
......
......@@ -587,15 +587,6 @@ buf_page_io_query(
/*==============*/
/* out: TRUE if io going on */
buf_block_t* block); /* in: pool block, must be bufferfixed */
/***********************************************************************
Accessor function for block array. */
UNIV_INLINE
buf_block_t*
buf_pool_get_nth_block(
/*===================*/
/* out: pointer to block */
buf_pool_t* pool, /* in: pool */
ulint i); /* in: index of the block */
/************************************************************************
Function which inits a page for read to the buffer buf_pool. If the page is
(1) already in buf_pool, or
......@@ -830,6 +821,8 @@ struct buf_pool_struct{
read-write lock in them */
byte* frame_mem; /* pointer to the memory area which
was allocated for the frames */
ulint frame_mem_size; /* allocated length of frame_mem
in bytes */
buf_block_t* blocks; /* array of buffer control blocks */
ulint curr_size; /* current pool size in pages */
hash_table_t* page_hash; /* hash table of the file pages */
......
......@@ -48,19 +48,17 @@ 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 */
ulint* n); /* in/out: number of bytes */
/********************************************************************
Frees large pages memory. */
void
os_mem_free_large(
/*==============*/
void *ptr); /* in: number of bytes */
void *ptr, /* in: pointer returned by
os_mem_alloc_large() */
ulint size); /* in: size returned by
os_mem_alloc_large() */
/********************************************************************
Sets the priority boost for threads released from waiting within the current
process. */
......
......@@ -35,6 +35,9 @@ if we are compiling on Windows. */
/* Include <sys/stat.h> to get S_I... macros defined for os0file.c */
# include <sys/stat.h>
# ifndef __NETWARE__
# include <sys/mman.h> /* mmap() for os0proc.c */
# endif
# undef PACKAGE
# undef VERSION
......
......@@ -65,31 +65,26 @@ 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 */
ulint* n) /* in/out: number of bytes */
{
#ifdef HAVE_LARGE_PAGES
ulint size;
void* ptr;
ulint size;
#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
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;
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", n, errno);
" %lu bytes. errno %d\n", size, errno);
ptr = NULL;
} else {
ptr = shmat(shmid, NULL, 0);
if (ptr == (void *)-1) {
......@@ -103,24 +98,56 @@ os_mem_alloc_large(
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
}
*n = size;
# 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 */
#endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
return(ut_malloc_low(n, set_to_zero, assert_on_error));
#ifdef __WIN__
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
/* Align block size to system page size */
size = *n = ut_2pow_round(*n + system_info.dwPageSize - 1,
system_info.dwPageSize);
ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE | PAGE_WRITECOMBINE);
if (!ptr) {
fprintf(stderr, "InnoDB: VirtualAlloc(%lu bytes) failed;"
" Windows error %lu\n",
(ulong) size, (ulong) GetLastError());
}
#elif defined __NETWARE__
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 */
size = *n = ut_2pow_round(*n + size - 1, size);
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (UNIV_UNLIKELY(ptr == (void*) -1)) {
fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;"
" errno %lu\n",
(ulong) size, (ulong) errno);
ptr = NULL;
}
#endif
return(ptr);
}
/********************************************************************
......@@ -129,19 +156,32 @@ Frees large pages memory. */
void
os_mem_free_large(
/*==============*/
void *ptr) /* in: number of bytes */
void *ptr, /* in: pointer returned by
os_mem_alloc_large() */
ulint size) /* in: size returned by
os_mem_alloc_large() */
{
#ifdef HAVE_LARGE_PAGES
if (os_use_large_pages && os_large_page_size
#ifdef UNIV_LINUX
&& !shmdt(ptr)
#endif
) {
#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) {
return;
}
#endif
#endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
#ifdef __WIN__
if (!VirtualFree(ptr, size, MEM_DECOMMIT | MEM_RELEASE)) {
fprintf(stderr, "InnoDB: VirtualFree(%p, %lu) failed;"
" Windows error %lu\n",
ptr, (ulong) size, (ulong) GetLastError());
}
#elif defined __NETWARE__
ut_free(ptr);
#else
if (munmap(ptr, size)) {
fprintf(stderr, "InnoDB: munmap(%p, %lu) failed;"
" errno %lu\n",
ptr, (ulong) size, (ulong) errno);
}
#endif
}
/********************************************************************
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment