1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: sw=4 ts=4 et :
3 : */
4 : /* ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is mozilla.org code.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * Mozilla Foundation
21 : * Portions created by the Initial Developer are Copyright (C) 2009
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * Chris Jones <jones.chris.g@gmail.com>
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #include <errno.h>
42 : #include <new> // for std::bad_alloc
43 : #include <string.h>
44 :
45 : #include <sys/types.h>
46 :
47 : #if defined(MALLOC_H)
48 : # include MALLOC_H // for memalign, valloc where available
49 : #endif // if defined(MALLOC_H)
50 : #include <stddef.h> // for size_t
51 : #include <stdlib.h> // for malloc, free
52 : #if defined(XP_UNIX)
53 : # include <unistd.h> // for valloc on *BSD
54 : #endif //if defined(XP_UNIX)
55 :
56 : #if defined(MOZ_MEMORY)
57 : // jemalloc.h doesn't redeclare symbols if they're provided by the OS
58 : # include "jemalloc.h"
59 : #endif
60 :
61 : #if defined(XP_WIN) || (defined(XP_OS2) && defined(__declspec))
62 : # define MOZALLOC_EXPORT __declspec(dllexport)
63 : #endif
64 :
65 : // Make sure that "malloc" et al. resolve to their libc variants.
66 : #define MOZALLOC_DONT_DEFINE_MACRO_WRAPPERS
67 : #include "mozilla/mozalloc.h"
68 : #include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom
69 :
70 :
71 : #if defined(__GNUC__) && (__GNUC__ > 2)
72 : #define LIKELY(x) (__builtin_expect(!!(x), 1))
73 : #define UNLIKELY(x) (__builtin_expect(!!(x), 0))
74 : #else
75 : #define LIKELY(x) (x)
76 : #define UNLIKELY(x) (x)
77 : #endif
78 :
79 : #ifdef MOZ_MEMORY_DARWIN
80 : #include "jemalloc.h"
81 : #define malloc(a) je_malloc(a)
82 : #define posix_memalign(a, b, c) je_posix_memalign(a, b, c)
83 : #define valloc(a) je_valloc(a)
84 : #define calloc(a, b) je_calloc(a, b)
85 : #define memalign(a, b) je_memalign(a, b)
86 : #define strdup(a) je_strdup(a)
87 : #define strndup(a, b) je_strndup(a, b)
88 : /* We omit functions which could be passed a memory region that was not
89 : * allocated by jemalloc (realloc, free and malloc_usable_size). Instead,
90 : * we use the system-provided functions, which will in turn call the
91 : * jemalloc versions when appropriate */
92 : #endif
93 :
94 : void
95 47302311 : moz_free(void* ptr)
96 : {
97 47302311 : free(ptr);
98 47302311 : }
99 :
100 : void*
101 32352673 : moz_xmalloc(size_t size)
102 : {
103 32352673 : void* ptr = malloc(size);
104 32352673 : if (UNLIKELY(!ptr && size)) {
105 0 : mozalloc_handle_oom(size);
106 0 : return moz_xmalloc(size);
107 : }
108 32352673 : return ptr;
109 : }
110 : void*
111 15669283 : moz_malloc(size_t size)
112 : {
113 15669283 : return malloc(size);
114 : }
115 :
116 : void*
117 0 : moz_xcalloc(size_t nmemb, size_t size)
118 : {
119 0 : void* ptr = calloc(nmemb, size);
120 0 : if (UNLIKELY(!ptr && nmemb && size)) {
121 0 : mozalloc_handle_oom(size);
122 0 : return moz_xcalloc(nmemb, size);
123 : }
124 0 : return ptr;
125 : }
126 : void*
127 8284 : moz_calloc(size_t nmemb, size_t size)
128 : {
129 8284 : return calloc(nmemb, size);
130 : }
131 :
132 : void*
133 266246 : moz_xrealloc(void* ptr, size_t size)
134 : {
135 266246 : void* newptr = realloc(ptr, size);
136 266246 : if (UNLIKELY(!newptr && size)) {
137 0 : mozalloc_handle_oom(size);
138 0 : return moz_xrealloc(ptr, size);
139 : }
140 266246 : return newptr;
141 : }
142 : void*
143 870102 : moz_realloc(void* ptr, size_t size)
144 : {
145 870102 : return realloc(ptr, size);
146 : }
147 :
148 : char*
149 0 : moz_xstrdup(const char* str)
150 : {
151 0 : char* dup = strdup(str);
152 0 : if (UNLIKELY(!dup)) {
153 0 : mozalloc_handle_oom(0);
154 0 : return moz_xstrdup(str);
155 : }
156 0 : return dup;
157 : }
158 : char*
159 84241 : moz_strdup(const char* str)
160 : {
161 84241 : return strdup(str);
162 : }
163 :
164 : #if defined(HAVE_STRNDUP)
165 : char*
166 0 : moz_xstrndup(const char* str, size_t strsize)
167 : {
168 0 : char* dup = strndup(str, strsize);
169 0 : if (UNLIKELY(!dup)) {
170 0 : mozalloc_handle_oom(strsize);
171 0 : return moz_xstrndup(str, strsize);
172 : }
173 0 : return dup;
174 : }
175 : char*
176 0 : moz_strndup(const char* str, size_t strsize)
177 : {
178 0 : return strndup(str, strsize);
179 : }
180 : #endif // if defined(HAVE_STRNDUP)
181 :
182 : #if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_JEMALLOC_POSIX_MEMALIGN)
183 : int
184 0 : moz_xposix_memalign(void **ptr, size_t alignment, size_t size)
185 : {
186 0 : int err = posix_memalign(ptr, alignment, size);
187 0 : if (UNLIKELY(err && ENOMEM == err)) {
188 0 : mozalloc_handle_oom(size);
189 0 : return moz_xposix_memalign(ptr, alignment, size);
190 : }
191 : // else: (0 == err) or (EINVAL == err)
192 0 : return err;
193 : }
194 : int
195 65 : moz_posix_memalign(void **ptr, size_t alignment, size_t size)
196 : {
197 65 : int code = posix_memalign(ptr, alignment, size);
198 65 : if (code)
199 0 : return code;
200 :
201 : #if defined(XP_MACOSX)
202 : // Workaround faulty OSX posix_memalign, which provides memory with the
203 : // incorrect alignment sometimes, but returns 0 as if nothing was wrong.
204 : size_t mask = alignment - 1;
205 : if (((size_t)(*ptr) & mask) != 0) {
206 : void* old = *ptr;
207 : code = moz_posix_memalign(ptr, alignment, size);
208 : free(old);
209 : }
210 : #endif
211 :
212 65 : return code;
213 :
214 : }
215 : #endif // if defined(HAVE_POSIX_MEMALIGN)
216 :
217 : #if defined(HAVE_MEMALIGN) || defined(HAVE_JEMALLOC_MEMALIGN)
218 : void*
219 0 : moz_xmemalign(size_t boundary, size_t size)
220 : {
221 0 : void* ptr = memalign(boundary, size);
222 0 : if (UNLIKELY(!ptr && EINVAL != errno)) {
223 0 : mozalloc_handle_oom(size);
224 0 : return moz_xmemalign(boundary, size);
225 : }
226 : // non-NULL ptr or errno == EINVAL
227 0 : return ptr;
228 : }
229 : void*
230 0 : moz_memalign(size_t boundary, size_t size)
231 : {
232 0 : return memalign(boundary, size);
233 : }
234 : #endif // if defined(HAVE_MEMALIGN)
235 :
236 : #if defined(HAVE_VALLOC) || defined(HAVE_JEMALLOC_VALLOC)
237 : void*
238 0 : moz_xvalloc(size_t size)
239 : {
240 0 : void* ptr = valloc(size);
241 0 : if (UNLIKELY(!ptr)) {
242 0 : mozalloc_handle_oom(size);
243 0 : return moz_xvalloc(size);
244 : }
245 0 : return ptr;
246 : }
247 : void*
248 0 : moz_valloc(size_t size)
249 : {
250 0 : return valloc(size);
251 : }
252 : #endif // if defined(HAVE_VALLOC)
253 :
254 : size_t
255 15912901 : moz_malloc_usable_size(void *ptr)
256 : {
257 15912901 : if (!ptr)
258 1694720 : return 0;
259 :
260 : #if defined(XP_MACOSX)
261 : return malloc_size(ptr);
262 : #elif defined(MOZ_MEMORY) || defined(XP_LINUX)
263 : // XXX: the |defined(XP_LINUX)| may be too lax; some Linux installations
264 : // might use a libc that doesn't have malloc_usable_size. Let's fix this
265 : // if/when it happens.
266 14218181 : return malloc_usable_size(ptr);
267 : #elif defined(XP_WIN)
268 : return _msize(ptr);
269 : #else
270 : return 0;
271 : #endif
272 : }
273 :
274 53214 : size_t moz_malloc_size_of(const void *ptr)
275 : {
276 53214 : return moz_malloc_usable_size((void *)ptr);
277 : }
278 :
279 : namespace mozilla {
280 :
281 1487 : const fallible_t fallible = fallible_t();
282 :
283 4461 : } // namespace mozilla
|