1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/memory/mozalloc/mozalloc.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,229 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * vim: sw=4 ts=4 et : 1.6 + */ 1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.10 + 1.11 +#include <errno.h> 1.12 +#include <new> // for std::bad_alloc 1.13 +#include <string.h> 1.14 + 1.15 +#include <sys/types.h> 1.16 + 1.17 +#if defined(MALLOC_H) 1.18 +# include MALLOC_H // for memalign, valloc, malloc_size, malloc_usable_size 1.19 +#endif // if defined(MALLOC_H) 1.20 +#include <stddef.h> // for size_t 1.21 +#include <stdlib.h> // for malloc, free 1.22 +#if defined(XP_UNIX) 1.23 +# include <unistd.h> // for valloc on *BSD 1.24 +#endif //if defined(XP_UNIX) 1.25 + 1.26 +#if defined(XP_WIN) 1.27 +# define MOZALLOC_EXPORT __declspec(dllexport) 1.28 +#endif 1.29 + 1.30 +#include "mozilla/mozalloc.h" 1.31 +#include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom 1.32 + 1.33 +/* Windows doesn't have malloc_usable_size, but jemalloc has */ 1.34 +#if defined(MOZ_MEMORY_WINDOWS) 1.35 +extern "C" size_t malloc_usable_size(const void *ptr); 1.36 +#endif 1.37 + 1.38 +#ifdef __GNUC__ 1.39 +#define LIKELY(x) (__builtin_expect(!!(x), 1)) 1.40 +#define UNLIKELY(x) (__builtin_expect(!!(x), 0)) 1.41 +#else 1.42 +#define LIKELY(x) (x) 1.43 +#define UNLIKELY(x) (x) 1.44 +#endif 1.45 + 1.46 +void 1.47 +moz_free(void* ptr) 1.48 +{ 1.49 + free(ptr); 1.50 +} 1.51 + 1.52 +void* 1.53 +moz_xmalloc(size_t size) 1.54 +{ 1.55 + void* ptr = malloc(size); 1.56 + if (UNLIKELY(!ptr && size)) { 1.57 + mozalloc_handle_oom(size); 1.58 + return moz_xmalloc(size); 1.59 + } 1.60 + return ptr; 1.61 +} 1.62 +void* 1.63 +moz_malloc(size_t size) 1.64 +{ 1.65 + return malloc(size); 1.66 +} 1.67 + 1.68 +void* 1.69 +moz_xcalloc(size_t nmemb, size_t size) 1.70 +{ 1.71 + void* ptr = calloc(nmemb, size); 1.72 + if (UNLIKELY(!ptr && nmemb && size)) { 1.73 + mozalloc_handle_oom(size); 1.74 + return moz_xcalloc(nmemb, size); 1.75 + } 1.76 + return ptr; 1.77 +} 1.78 +void* 1.79 +moz_calloc(size_t nmemb, size_t size) 1.80 +{ 1.81 + return calloc(nmemb, size); 1.82 +} 1.83 + 1.84 +void* 1.85 +moz_xrealloc(void* ptr, size_t size) 1.86 +{ 1.87 + void* newptr = realloc(ptr, size); 1.88 + if (UNLIKELY(!newptr && size)) { 1.89 + mozalloc_handle_oom(size); 1.90 + return moz_xrealloc(ptr, size); 1.91 + } 1.92 + return newptr; 1.93 +} 1.94 +void* 1.95 +moz_realloc(void* ptr, size_t size) 1.96 +{ 1.97 + return realloc(ptr, size); 1.98 +} 1.99 + 1.100 +char* 1.101 +moz_xstrdup(const char* str) 1.102 +{ 1.103 + char* dup = strdup(str); 1.104 + if (UNLIKELY(!dup)) { 1.105 + mozalloc_handle_oom(0); 1.106 + return moz_xstrdup(str); 1.107 + } 1.108 + return dup; 1.109 +} 1.110 +char* 1.111 +moz_strdup(const char* str) 1.112 +{ 1.113 + return strdup(str); 1.114 +} 1.115 + 1.116 +#if defined(HAVE_STRNDUP) 1.117 +char* 1.118 +moz_xstrndup(const char* str, size_t strsize) 1.119 +{ 1.120 + char* dup = strndup(str, strsize); 1.121 + if (UNLIKELY(!dup)) { 1.122 + mozalloc_handle_oom(strsize); 1.123 + return moz_xstrndup(str, strsize); 1.124 + } 1.125 + return dup; 1.126 +} 1.127 +char* 1.128 +moz_strndup(const char* str, size_t strsize) 1.129 +{ 1.130 + return strndup(str, strsize); 1.131 +} 1.132 +#endif // if defined(HAVE_STRNDUP) 1.133 + 1.134 +#if defined(HAVE_POSIX_MEMALIGN) 1.135 +int 1.136 +moz_xposix_memalign(void **ptr, size_t alignment, size_t size) 1.137 +{ 1.138 + int err = posix_memalign(ptr, alignment, size); 1.139 + if (UNLIKELY(err && ENOMEM == err)) { 1.140 + mozalloc_handle_oom(size); 1.141 + return moz_xposix_memalign(ptr, alignment, size); 1.142 + } 1.143 + // else: (0 == err) or (EINVAL == err) 1.144 + return err; 1.145 +} 1.146 +int 1.147 +moz_posix_memalign(void **ptr, size_t alignment, size_t size) 1.148 +{ 1.149 + int code = posix_memalign(ptr, alignment, size); 1.150 + if (code) 1.151 + return code; 1.152 + 1.153 +#if defined(XP_MACOSX) 1.154 + // Workaround faulty OSX posix_memalign, which provides memory with the 1.155 + // incorrect alignment sometimes, but returns 0 as if nothing was wrong. 1.156 + size_t mask = alignment - 1; 1.157 + if (((size_t)(*ptr) & mask) != 0) { 1.158 + void* old = *ptr; 1.159 + code = moz_posix_memalign(ptr, alignment, size); 1.160 + free(old); 1.161 + } 1.162 +#endif 1.163 + 1.164 + return code; 1.165 + 1.166 +} 1.167 +#endif // if defined(HAVE_POSIX_MEMALIGN) 1.168 + 1.169 +#if defined(HAVE_MEMALIGN) 1.170 +void* 1.171 +moz_xmemalign(size_t boundary, size_t size) 1.172 +{ 1.173 + void* ptr = memalign(boundary, size); 1.174 + if (UNLIKELY(!ptr && EINVAL != errno)) { 1.175 + mozalloc_handle_oom(size); 1.176 + return moz_xmemalign(boundary, size); 1.177 + } 1.178 + // non-NULL ptr or errno == EINVAL 1.179 + return ptr; 1.180 +} 1.181 +void* 1.182 +moz_memalign(size_t boundary, size_t size) 1.183 +{ 1.184 + return memalign(boundary, size); 1.185 +} 1.186 +#endif // if defined(HAVE_MEMALIGN) 1.187 + 1.188 +#if defined(HAVE_VALLOC) 1.189 +void* 1.190 +moz_xvalloc(size_t size) 1.191 +{ 1.192 + void* ptr = valloc(size); 1.193 + if (UNLIKELY(!ptr)) { 1.194 + mozalloc_handle_oom(size); 1.195 + return moz_xvalloc(size); 1.196 + } 1.197 + return ptr; 1.198 +} 1.199 +void* 1.200 +moz_valloc(size_t size) 1.201 +{ 1.202 + return valloc(size); 1.203 +} 1.204 +#endif // if defined(HAVE_VALLOC) 1.205 + 1.206 +size_t 1.207 +moz_malloc_usable_size(void *ptr) 1.208 +{ 1.209 + if (!ptr) 1.210 + return 0; 1.211 + 1.212 +#if defined(XP_MACOSX) 1.213 + return malloc_size(ptr); 1.214 +#elif defined(HAVE_MALLOC_USABLE_SIZE) || defined(MOZ_MEMORY) 1.215 + return malloc_usable_size(ptr); 1.216 +#elif defined(XP_WIN) 1.217 + return _msize(ptr); 1.218 +#else 1.219 + return 0; 1.220 +#endif 1.221 +} 1.222 + 1.223 +size_t moz_malloc_size_of(const void *ptr) 1.224 +{ 1.225 + return moz_malloc_usable_size((void *)ptr); 1.226 +} 1.227 + 1.228 +namespace mozilla { 1.229 + 1.230 +const fallible_t fallible = fallible_t(); 1.231 + 1.232 +} // namespace mozilla