MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
os0proc.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************/
27 #include "os0proc.h"
28 #ifdef UNIV_NONINL
29 #include "os0proc.ic"
30 #endif
31 
32 #include "ut0mem.h"
33 #include "ut0byte.h"
34 
35 /* FreeBSD for example has only MAP_ANON, Linux has MAP_ANONYMOUS and
36 MAP_ANON but MAP_ANON is marked as deprecated */
37 #if defined(MAP_ANONYMOUS)
38 #define OS_MAP_ANON MAP_ANONYMOUS
39 #elif defined(MAP_ANON)
40 #define OS_MAP_ANON MAP_ANON
41 #endif
42 
43 UNIV_INTERN ibool os_use_large_pages;
44 /* Large page size. This may be a boot-time option on some platforms */
45 UNIV_INTERN ulint os_large_page_size;
46 
47 /****************************************************************/
53 UNIV_INTERN
54 ulint
56 /*====================*/
57 {
58 #ifdef __WIN__
59  return((ulint)GetCurrentProcessId());
60 #else
61  return((ulint) getpid());
62 #endif
63 }
64 
65 /****************************************************************/
68 UNIV_INTERN
69 void*
71 /*===============*/
72  ulint* n)
73 {
74  void* ptr;
75  ulint size;
76 #if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
77  int shmid;
78  struct shmid_ds buf;
79 
80  if (!os_use_large_pages || !os_large_page_size) {
81  goto skip;
82  }
83 
84  /* Align block size to os_large_page_size */
85  ut_ad(ut_is_2pow(os_large_page_size));
86  size = ut_2pow_round(*n + (os_large_page_size - 1),
87  os_large_page_size);
88 
89  shmid = shmget(IPC_PRIVATE, (size_t) size, SHM_HUGETLB | SHM_R | SHM_W);
90  if (shmid < 0) {
91  fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate"
92  " %lu bytes. errno %d\n", size, errno);
93  ptr = NULL;
94  } else {
95  ptr = shmat(shmid, NULL, 0);
96  if (ptr == (void*)-1) {
97  fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to"
98  " attach shared memory segment, errno %d\n",
99  errno);
100  ptr = NULL;
101  }
102 
103  /* Remove the shared memory segment so that it will be
104  automatically freed after memory is detached or
105  process exits */
106  shmctl(shmid, IPC_RMID, &buf);
107  }
108 
109  if (ptr) {
110  *n = size;
111  os_fast_mutex_lock(&ut_list_mutex);
113  os_fast_mutex_unlock(&ut_list_mutex);
114  UNIV_MEM_ALLOC(ptr, size);
115  return(ptr);
116  }
117 
118  fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional"
119  " memory pool\n");
120 skip:
121 #endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
122 
123 #ifdef __WIN__
124  SYSTEM_INFO system_info;
125  GetSystemInfo(&system_info);
126 
127  /* Align block size to system page size */
128  ut_ad(ut_is_2pow(system_info.dwPageSize));
129  /* system_info.dwPageSize is only 32-bit. Casting to ulint is required
130  on 64-bit Windows. */
131  size = *n = ut_2pow_round(*n + (system_info.dwPageSize - 1),
132  (ulint) system_info.dwPageSize);
133  ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE,
134  PAGE_READWRITE);
135  if (!ptr) {
136  fprintf(stderr, "InnoDB: VirtualAlloc(%lu bytes) failed;"
137  " Windows error %lu\n",
138  (ulong) size, (ulong) GetLastError());
139  } else {
140  os_fast_mutex_lock(&ut_list_mutex);
142  os_fast_mutex_unlock(&ut_list_mutex);
143  UNIV_MEM_ALLOC(ptr, size);
144  }
145 #elif !defined OS_MAP_ANON
146  size = *n;
147  ptr = ut_malloc_low(size, TRUE, FALSE);
148 #else
149 # ifdef HAVE_GETPAGESIZE
150  size = getpagesize();
151 # else
152  size = UNIV_PAGE_SIZE;
153 # endif
154  /* Align block size to system page size */
155  ut_ad(ut_is_2pow(size));
156  size = *n = ut_2pow_round(*n + (size - 1), size);
157  ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
158  MAP_PRIVATE | OS_MAP_ANON, -1, 0);
159  if (UNIV_UNLIKELY(ptr == (void*) -1)) {
160  fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;"
161  " errno %lu\n",
162  (ulong) size, (ulong) errno);
163  ptr = NULL;
164  } else {
165  os_fast_mutex_lock(&ut_list_mutex);
167  os_fast_mutex_unlock(&ut_list_mutex);
168  UNIV_MEM_ALLOC(ptr, size);
169  }
170 #endif
171  return(ptr);
172 }
173 
174 /****************************************************************/
176 UNIV_INTERN
177 void
179 /*==============*/
180  void *ptr,
182  ulint size)
184 {
185  os_fast_mutex_lock(&ut_list_mutex);
187  os_fast_mutex_unlock(&ut_list_mutex);
188 
189 #if defined HAVE_LARGE_PAGES && defined UNIV_LINUX
190  if (os_use_large_pages && os_large_page_size && !shmdt(ptr)) {
191  os_fast_mutex_lock(&ut_list_mutex);
194  os_fast_mutex_unlock(&ut_list_mutex);
195  UNIV_MEM_FREE(ptr, size);
196  return;
197  }
198 #endif /* HAVE_LARGE_PAGES && UNIV_LINUX */
199 #ifdef __WIN__
200  /* When RELEASE memory, the size parameter must be 0.
201  Do not use MEM_RELEASE with MEM_DECOMMIT. */
202  if (!VirtualFree(ptr, 0, MEM_RELEASE)) {
203  fprintf(stderr, "InnoDB: VirtualFree(%p, %lu) failed;"
204  " Windows error %lu\n",
205  ptr, (ulong) size, (ulong) GetLastError());
206  } else {
207  os_fast_mutex_lock(&ut_list_mutex);
210  os_fast_mutex_unlock(&ut_list_mutex);
211  UNIV_MEM_FREE(ptr, size);
212  }
213 #elif !defined OS_MAP_ANON
214  ut_free(ptr);
215 #else
216 # if defined(UNIV_SOLARIS)
217  if (munmap(static_cast<caddr_t>(ptr), size)) {
218 # else
219  if (munmap(ptr, size)) {
220 # endif /* UNIV_SOLARIS */
221  fprintf(stderr, "InnoDB: munmap(%p, %lu) failed;"
222  " errno %lu\n",
223  ptr, (ulong) size, (ulong) errno);
224  } else {
225  os_fast_mutex_lock(&ut_list_mutex);
228  os_fast_mutex_unlock(&ut_list_mutex);
229  UNIV_MEM_FREE(ptr, size);
230  }
231 #endif
232 }