memory/mozalloc/mozalloc.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:a52dd181e152
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: sw=4 ts=4 et :
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #include <errno.h>
9 #include <new> // for std::bad_alloc
10 #include <string.h>
11
12 #include <sys/types.h>
13
14 #if defined(MALLOC_H)
15 # include MALLOC_H // for memalign, valloc, malloc_size, malloc_usable_size
16 #endif // if defined(MALLOC_H)
17 #include <stddef.h> // for size_t
18 #include <stdlib.h> // for malloc, free
19 #if defined(XP_UNIX)
20 # include <unistd.h> // for valloc on *BSD
21 #endif //if defined(XP_UNIX)
22
23 #if defined(XP_WIN)
24 # define MOZALLOC_EXPORT __declspec(dllexport)
25 #endif
26
27 #include "mozilla/mozalloc.h"
28 #include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom
29
30 /* Windows doesn't have malloc_usable_size, but jemalloc has */
31 #if defined(MOZ_MEMORY_WINDOWS)
32 extern "C" size_t malloc_usable_size(const void *ptr);
33 #endif
34
35 #ifdef __GNUC__
36 #define LIKELY(x) (__builtin_expect(!!(x), 1))
37 #define UNLIKELY(x) (__builtin_expect(!!(x), 0))
38 #else
39 #define LIKELY(x) (x)
40 #define UNLIKELY(x) (x)
41 #endif
42
43 void
44 moz_free(void* ptr)
45 {
46 free(ptr);
47 }
48
49 void*
50 moz_xmalloc(size_t size)
51 {
52 void* ptr = malloc(size);
53 if (UNLIKELY(!ptr && size)) {
54 mozalloc_handle_oom(size);
55 return moz_xmalloc(size);
56 }
57 return ptr;
58 }
59 void*
60 moz_malloc(size_t size)
61 {
62 return malloc(size);
63 }
64
65 void*
66 moz_xcalloc(size_t nmemb, size_t size)
67 {
68 void* ptr = calloc(nmemb, size);
69 if (UNLIKELY(!ptr && nmemb && size)) {
70 mozalloc_handle_oom(size);
71 return moz_xcalloc(nmemb, size);
72 }
73 return ptr;
74 }
75 void*
76 moz_calloc(size_t nmemb, size_t size)
77 {
78 return calloc(nmemb, size);
79 }
80
81 void*
82 moz_xrealloc(void* ptr, size_t size)
83 {
84 void* newptr = realloc(ptr, size);
85 if (UNLIKELY(!newptr && size)) {
86 mozalloc_handle_oom(size);
87 return moz_xrealloc(ptr, size);
88 }
89 return newptr;
90 }
91 void*
92 moz_realloc(void* ptr, size_t size)
93 {
94 return realloc(ptr, size);
95 }
96
97 char*
98 moz_xstrdup(const char* str)
99 {
100 char* dup = strdup(str);
101 if (UNLIKELY(!dup)) {
102 mozalloc_handle_oom(0);
103 return moz_xstrdup(str);
104 }
105 return dup;
106 }
107 char*
108 moz_strdup(const char* str)
109 {
110 return strdup(str);
111 }
112
113 #if defined(HAVE_STRNDUP)
114 char*
115 moz_xstrndup(const char* str, size_t strsize)
116 {
117 char* dup = strndup(str, strsize);
118 if (UNLIKELY(!dup)) {
119 mozalloc_handle_oom(strsize);
120 return moz_xstrndup(str, strsize);
121 }
122 return dup;
123 }
124 char*
125 moz_strndup(const char* str, size_t strsize)
126 {
127 return strndup(str, strsize);
128 }
129 #endif // if defined(HAVE_STRNDUP)
130
131 #if defined(HAVE_POSIX_MEMALIGN)
132 int
133 moz_xposix_memalign(void **ptr, size_t alignment, size_t size)
134 {
135 int err = posix_memalign(ptr, alignment, size);
136 if (UNLIKELY(err && ENOMEM == err)) {
137 mozalloc_handle_oom(size);
138 return moz_xposix_memalign(ptr, alignment, size);
139 }
140 // else: (0 == err) or (EINVAL == err)
141 return err;
142 }
143 int
144 moz_posix_memalign(void **ptr, size_t alignment, size_t size)
145 {
146 int code = posix_memalign(ptr, alignment, size);
147 if (code)
148 return code;
149
150 #if defined(XP_MACOSX)
151 // Workaround faulty OSX posix_memalign, which provides memory with the
152 // incorrect alignment sometimes, but returns 0 as if nothing was wrong.
153 size_t mask = alignment - 1;
154 if (((size_t)(*ptr) & mask) != 0) {
155 void* old = *ptr;
156 code = moz_posix_memalign(ptr, alignment, size);
157 free(old);
158 }
159 #endif
160
161 return code;
162
163 }
164 #endif // if defined(HAVE_POSIX_MEMALIGN)
165
166 #if defined(HAVE_MEMALIGN)
167 void*
168 moz_xmemalign(size_t boundary, size_t size)
169 {
170 void* ptr = memalign(boundary, size);
171 if (UNLIKELY(!ptr && EINVAL != errno)) {
172 mozalloc_handle_oom(size);
173 return moz_xmemalign(boundary, size);
174 }
175 // non-NULL ptr or errno == EINVAL
176 return ptr;
177 }
178 void*
179 moz_memalign(size_t boundary, size_t size)
180 {
181 return memalign(boundary, size);
182 }
183 #endif // if defined(HAVE_MEMALIGN)
184
185 #if defined(HAVE_VALLOC)
186 void*
187 moz_xvalloc(size_t size)
188 {
189 void* ptr = valloc(size);
190 if (UNLIKELY(!ptr)) {
191 mozalloc_handle_oom(size);
192 return moz_xvalloc(size);
193 }
194 return ptr;
195 }
196 void*
197 moz_valloc(size_t size)
198 {
199 return valloc(size);
200 }
201 #endif // if defined(HAVE_VALLOC)
202
203 size_t
204 moz_malloc_usable_size(void *ptr)
205 {
206 if (!ptr)
207 return 0;
208
209 #if defined(XP_MACOSX)
210 return malloc_size(ptr);
211 #elif defined(HAVE_MALLOC_USABLE_SIZE) || defined(MOZ_MEMORY)
212 return malloc_usable_size(ptr);
213 #elif defined(XP_WIN)
214 return _msize(ptr);
215 #else
216 return 0;
217 #endif
218 }
219
220 size_t moz_malloc_size_of(const void *ptr)
221 {
222 return moz_malloc_usable_size((void *)ptr);
223 }
224
225 namespace mozilla {
226
227 const fallible_t fallible = fallible_t();
228
229 } // namespace mozilla

mercurial