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( ...@@ -634,7 +634,6 @@ buf_pool_init(
byte* frame; byte* frame;
ulint i; ulint i;
buf_block_t* block; buf_block_t* block;
ulint n_frames = curr_size;
buf_pool = mem_alloc(sizeof(buf_pool_t)); buf_pool = mem_alloc(sizeof(buf_pool_t));
...@@ -644,27 +643,35 @@ buf_pool_init( ...@@ -644,27 +643,35 @@ buf_pool_init(
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
buf_pool->frame_mem = os_mem_alloc_large( buf_pool->frame_mem_size = (curr_size + 1) * UNIV_PAGE_SIZE;
UNIV_PAGE_SIZE * (n_frames + 1), TRUE, FALSE);
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); 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); 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); return(NULL);
} }
buf_pool->curr_size = curr_size; 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 /* Init block structs and assign frames for them. Then we
assign the frames to the first blocks (we already mapped the assign the frames to the first blocks (we already mapped the
memory above). */ memory above). */
......
...@@ -587,15 +587,6 @@ buf_page_io_query( ...@@ -587,15 +587,6 @@ buf_page_io_query(
/*==============*/ /*==============*/
/* out: TRUE if io going on */ /* out: TRUE if io going on */
buf_block_t* block); /* in: pool block, must be bufferfixed */ 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 Function which inits a page for read to the buffer buf_pool. If the page is
(1) already in buf_pool, or (1) already in buf_pool, or
...@@ -830,6 +821,8 @@ struct buf_pool_struct{ ...@@ -830,6 +821,8 @@ struct buf_pool_struct{
read-write lock in them */ read-write lock in them */
byte* frame_mem; /* pointer to the memory area which byte* frame_mem; /* pointer to the memory area which
was allocated for the frames */ 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 */ buf_block_t* blocks; /* array of buffer control blocks */
ulint curr_size; /* current pool size in pages */ ulint curr_size; /* current pool size in pages */
hash_table_t* page_hash; /* hash table of the file pages */ hash_table_t* page_hash; /* hash table of the file pages */
......
...@@ -48,19 +48,17 @@ void* ...@@ -48,19 +48,17 @@ void*
os_mem_alloc_large( os_mem_alloc_large(
/*===============*/ /*===============*/
/* out: allocated memory */ /* out: allocated memory */
ulint n, /* in: number of bytes */ ulint* n); /* in/out: 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 */
/******************************************************************** /********************************************************************
Frees large pages memory. */ Frees large pages memory. */
void void
os_mem_free_large( 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 Sets the priority boost for threads released from waiting within the current
process. */ process. */
......
...@@ -35,6 +35,9 @@ if we are compiling on Windows. */ ...@@ -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> to get S_I... macros defined for os0file.c */
# include <sys/stat.h> # include <sys/stat.h>
# ifndef __NETWARE__
# include <sys/mman.h> /* mmap() for os0proc.c */
# endif
# undef PACKAGE # undef PACKAGE
# undef VERSION # undef VERSION
......
...@@ -65,31 +65,26 @@ void* ...@@ -65,31 +65,26 @@ void*
os_mem_alloc_large( os_mem_alloc_large(
/*===============*/ /*===============*/
/* out: allocated memory */ /* out: allocated memory */
ulint n, /* in: number of bytes */ ulint* n) /* in/out: 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 void* ptr;
ulint size; ulint size;
#if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
int shmid; int shmid;
void *ptr = NULL;
struct shmid_ds buf; struct shmid_ds buf;
if (!os_use_large_pages || !os_large_page_size) { if (!os_use_large_pages || !os_large_page_size) {
goto skip; goto skip;
} }
#ifdef UNIV_LINUX
/* Align block size to os_large_page_size */ /* 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); shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W);
if (shmid < 0) { if (shmid < 0) {
fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate" 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 { } else {
ptr = shmat(shmid, NULL, 0); ptr = shmat(shmid, NULL, 0);
if (ptr == (void *)-1) { if (ptr == (void *)-1) {
...@@ -103,24 +98,56 @@ os_mem_alloc_large( ...@@ -103,24 +98,56 @@ os_mem_alloc_large(
process exits */ process exits */
shmctl(shmid, IPC_RMID, &buf); shmctl(shmid, IPC_RMID, &buf);
} }
#endif
if (ptr) { if (ptr) {
if (set_to_zero) { *n = size;
#ifdef UNIV_SET_MEM_TO_ZERO # ifdef UNIV_SET_MEM_TO_ZERO
memset(ptr, '\0', size); memset(ptr, '\0', size);
#endif # endif
}
return(ptr); return(ptr);
} }
fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional" fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional"
" memory pool\n"); " memory pool\n");
skip: 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. */ ...@@ -129,19 +156,32 @@ Frees large pages memory. */
void void
os_mem_free_large( 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 defined HAVE_LARGE_PAGES && defined UNIV_LINUX
if (os_use_large_pages && os_large_page_size if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) {
#ifdef UNIV_LINUX
&& !shmdt(ptr)
#endif
) {
return; 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); 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