Drizzled Public API Documentation

os0proc.cc

00001 /*****************************************************************************
00002 
00003 Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved.
00004 
00005 This program is free software; you can redistribute it and/or modify it under
00006 the terms of the GNU General Public License as published by the Free Software
00007 Foundation; version 2 of the License.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT
00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License along with
00014 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00015 St, Fifth Floor, Boston, MA 02110-1301 USA
00016 
00017 *****************************************************************************/
00018 
00019 /**************************************************/
00027 #include "os0proc.h"
00028 #ifdef UNIV_NONINL
00029 #include "os0proc.ic"
00030 #endif
00031 
00032 #include "ut0mem.h"
00033 #include "ut0byte.h"
00034 #include <errno.h>
00035 #include <unistd.h>
00036 
00037 /* FreeBSD for example has only MAP_ANON, Linux has MAP_ANONYMOUS and
00038 MAP_ANON but MAP_ANON is marked as deprecated */
00039 #if defined(MAP_ANONYMOUS)
00040 #define OS_MAP_ANON MAP_ANONYMOUS
00041 #elif defined(MAP_ANON)
00042 #define OS_MAP_ANON MAP_ANON
00043 #endif
00044 
00045 UNIV_INTERN ibool os_use_large_pages;
00046 /* Large page size. This may be a boot-time option on some platforms */
00047 UNIV_INTERN ulint os_large_page_size;
00048 
00049 /****************************************************************/
00055 UNIV_INTERN
00056 ulint
00057 os_proc_get_number(void)
00058 /*====================*/
00059 {
00060 #ifdef __WIN__
00061   return((ulint)GetCurrentProcessId());
00062 #else
00063   return((ulint)getpid());
00064 #endif
00065 }
00066 
00067 /****************************************************************/
00070 UNIV_INTERN
00071 void*
00072 os_mem_alloc_large(
00073 /*===============*/
00074   ulint*  n)      
00075 {
00076   void* ptr;
00077   ulint size;
00078 #if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
00079   int shmid;
00080   struct shmid_ds buf;
00081 
00082   if (!os_use_large_pages || !os_large_page_size) {
00083     goto skip;
00084   }
00085 
00086   /* Align block size to os_large_page_size */
00087   ut_ad(ut_is_2pow(os_large_page_size));
00088   size = ut_2pow_round(*n + (os_large_page_size - 1),
00089            os_large_page_size);
00090 
00091   shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W);
00092   if (shmid < 0) {
00093     fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate"
00094       " %lu bytes. errno %d\n", size, errno);
00095     ptr = NULL;
00096   } else {
00097     ptr = shmat(shmid, NULL, 0);
00098     if (ptr == (void *)-1) {
00099       fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to"
00100         " attach shared memory segment, errno %d\n",
00101         errno);
00102       ptr = NULL;
00103     }
00104 
00105     /* Remove the shared memory segment so that it will be
00106     automatically freed after memory is detached or
00107     process exits */
00108     shmctl(shmid, IPC_RMID, &buf);
00109   }
00110 
00111   if (ptr) {
00112     *n = size;
00113     os_fast_mutex_lock(&ut_list_mutex);
00114     ut_total_allocated_memory += size;
00115     os_fast_mutex_unlock(&ut_list_mutex);
00116 # ifdef UNIV_SET_MEM_TO_ZERO
00117     memset(ptr, '\0', size);
00118 # endif
00119     UNIV_MEM_ALLOC(ptr, size);
00120     return(ptr);
00121   }
00122 
00123   fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional"
00124     " memory pool\n");
00125 skip:
00126 #endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
00127 
00128 #ifdef __WIN__
00129   SYSTEM_INFO system_info;
00130   GetSystemInfo(&system_info);
00131 
00132   /* Align block size to system page size */
00133   ut_ad(ut_is_2pow(system_info.dwPageSize));
00134   /* system_info.dwPageSize is only 32-bit. Casting to ulint is required
00135   on 64-bit Windows. */
00136   size = *n = ut_2pow_round(*n + (system_info.dwPageSize - 1),
00137           (ulint) system_info.dwPageSize);
00138   ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
00139          PAGE_READWRITE);
00140   if (!ptr) {
00141     fprintf(stderr, "InnoDB: VirtualAlloc(%lu bytes) failed;"
00142       " Windows error %lu\n",
00143       (ulong) size, (ulong) GetLastError());
00144   } else {
00145     os_fast_mutex_lock(&ut_list_mutex);
00146     ut_total_allocated_memory += size;
00147     os_fast_mutex_unlock(&ut_list_mutex);
00148     UNIV_MEM_ALLOC(ptr, size);
00149   }
00150 #elif !defined OS_MAP_ANON
00151   size = *n;
00152   ptr = ut_malloc_low(size, TRUE, FALSE);
00153 #else
00154 # ifdef HAVE_GETPAGESIZE
00155   size = getpagesize();
00156 # else
00157   size = UNIV_PAGE_SIZE;
00158 # endif
00159   /* Align block size to system page size */
00160   ut_ad(ut_is_2pow(size));
00161   size = *n = ut_2pow_round(*n + (size - 1), size);
00162   ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
00163        MAP_PRIVATE | OS_MAP_ANON, -1, 0);
00164   if (UNIV_UNLIKELY(ptr == (void*) -1)) {
00165     fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;"
00166       " errno %lu\n",
00167       (ulong) size, (ulong) errno);
00168     ptr = NULL;
00169   } else {
00170     os_fast_mutex_lock(&ut_list_mutex);
00171     ut_total_allocated_memory += size;
00172     os_fast_mutex_unlock(&ut_list_mutex);
00173     UNIV_MEM_ALLOC(ptr, size);
00174   }
00175 #endif
00176   return(ptr);
00177 }
00178 
00179 /****************************************************************/
00181 UNIV_INTERN
00182 void
00183 os_mem_free_large(
00184 /*==============*/
00185   void  *ptr,     
00187   ulint size)     
00189 {
00190   os_fast_mutex_lock(&ut_list_mutex);
00191   ut_a(ut_total_allocated_memory >= size);
00192   os_fast_mutex_unlock(&ut_list_mutex);
00193 
00194 #if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
00195   if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) {
00196     os_fast_mutex_lock(&ut_list_mutex);
00197     ut_a(ut_total_allocated_memory >= size);
00198     ut_total_allocated_memory -= size;
00199     os_fast_mutex_unlock(&ut_list_mutex);
00200     UNIV_MEM_FREE(ptr, size);
00201     return;
00202   }
00203 #endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
00204 #ifdef __WIN__
00205   /* When RELEASE memory, the size parameter must be 0.
00206   Do not use MEM_RELEASE with MEM_DECOMMIT. */
00207   if (!VirtualFree(ptr, 0, MEM_RELEASE)) {
00208     fprintf(stderr, "InnoDB: VirtualFree(%p, %lu) failed;"
00209       " Windows error %lu\n",
00210       ptr, (ulong) size, (ulong) GetLastError());
00211   } else {
00212     os_fast_mutex_lock(&ut_list_mutex);
00213     ut_a(ut_total_allocated_memory >= size);
00214     ut_total_allocated_memory -= size;
00215     os_fast_mutex_unlock(&ut_list_mutex);
00216     UNIV_MEM_FREE(ptr, size);
00217   }
00218 #elif !defined OS_MAP_ANON
00219   ut_free(ptr);
00220 #else
00221   if (munmap(static_cast<char *>(ptr), size)) {
00222     fprintf(stderr, "InnoDB: munmap(%p, %lu) failed;"
00223       " errno %lu\n",
00224       ptr, (ulong) size, (ulong) errno);
00225   } else {
00226     os_fast_mutex_lock(&ut_list_mutex);
00227     ut_a(ut_total_allocated_memory >= size);
00228     ut_total_allocated_memory -= size;
00229     os_fast_mutex_unlock(&ut_list_mutex);
00230     UNIV_MEM_FREE(ptr, size);
00231   }
00232 #endif
00233 }