michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: sw=4 ts=4 et : michael@0: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include michael@0: #include // for std::bad_alloc michael@0: #include michael@0: michael@0: #include michael@0: michael@0: #if defined(MALLOC_H) michael@0: # include MALLOC_H // for memalign, valloc, malloc_size, malloc_usable_size michael@0: #endif // if defined(MALLOC_H) michael@0: #include // for size_t michael@0: #include // for malloc, free michael@0: #if defined(XP_UNIX) michael@0: # include // for valloc on *BSD michael@0: #endif //if defined(XP_UNIX) michael@0: michael@0: #if defined(XP_WIN) michael@0: # define MOZALLOC_EXPORT __declspec(dllexport) michael@0: #endif michael@0: michael@0: #include "mozilla/mozalloc.h" michael@0: #include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom michael@0: michael@0: /* Windows doesn't have malloc_usable_size, but jemalloc has */ michael@0: #if defined(MOZ_MEMORY_WINDOWS) michael@0: extern "C" size_t malloc_usable_size(const void *ptr); michael@0: #endif michael@0: michael@0: #ifdef __GNUC__ michael@0: #define LIKELY(x) (__builtin_expect(!!(x), 1)) michael@0: #define UNLIKELY(x) (__builtin_expect(!!(x), 0)) michael@0: #else michael@0: #define LIKELY(x) (x) michael@0: #define UNLIKELY(x) (x) michael@0: #endif michael@0: michael@0: void michael@0: moz_free(void* ptr) michael@0: { michael@0: free(ptr); michael@0: } michael@0: michael@0: void* michael@0: moz_xmalloc(size_t size) michael@0: { michael@0: void* ptr = malloc(size); michael@0: if (UNLIKELY(!ptr && size)) { michael@0: mozalloc_handle_oom(size); michael@0: return moz_xmalloc(size); michael@0: } michael@0: return ptr; michael@0: } michael@0: void* michael@0: moz_malloc(size_t size) michael@0: { michael@0: return malloc(size); michael@0: } michael@0: michael@0: void* michael@0: moz_xcalloc(size_t nmemb, size_t size) michael@0: { michael@0: void* ptr = calloc(nmemb, size); michael@0: if (UNLIKELY(!ptr && nmemb && size)) { michael@0: mozalloc_handle_oom(size); michael@0: return moz_xcalloc(nmemb, size); michael@0: } michael@0: return ptr; michael@0: } michael@0: void* michael@0: moz_calloc(size_t nmemb, size_t size) michael@0: { michael@0: return calloc(nmemb, size); michael@0: } michael@0: michael@0: void* michael@0: moz_xrealloc(void* ptr, size_t size) michael@0: { michael@0: void* newptr = realloc(ptr, size); michael@0: if (UNLIKELY(!newptr && size)) { michael@0: mozalloc_handle_oom(size); michael@0: return moz_xrealloc(ptr, size); michael@0: } michael@0: return newptr; michael@0: } michael@0: void* michael@0: moz_realloc(void* ptr, size_t size) michael@0: { michael@0: return realloc(ptr, size); michael@0: } michael@0: michael@0: char* michael@0: moz_xstrdup(const char* str) michael@0: { michael@0: char* dup = strdup(str); michael@0: if (UNLIKELY(!dup)) { michael@0: mozalloc_handle_oom(0); michael@0: return moz_xstrdup(str); michael@0: } michael@0: return dup; michael@0: } michael@0: char* michael@0: moz_strdup(const char* str) michael@0: { michael@0: return strdup(str); michael@0: } michael@0: michael@0: #if defined(HAVE_STRNDUP) michael@0: char* michael@0: moz_xstrndup(const char* str, size_t strsize) michael@0: { michael@0: char* dup = strndup(str, strsize); michael@0: if (UNLIKELY(!dup)) { michael@0: mozalloc_handle_oom(strsize); michael@0: return moz_xstrndup(str, strsize); michael@0: } michael@0: return dup; michael@0: } michael@0: char* michael@0: moz_strndup(const char* str, size_t strsize) michael@0: { michael@0: return strndup(str, strsize); michael@0: } michael@0: #endif // if defined(HAVE_STRNDUP) michael@0: michael@0: #if defined(HAVE_POSIX_MEMALIGN) michael@0: int michael@0: moz_xposix_memalign(void **ptr, size_t alignment, size_t size) michael@0: { michael@0: int err = posix_memalign(ptr, alignment, size); michael@0: if (UNLIKELY(err && ENOMEM == err)) { michael@0: mozalloc_handle_oom(size); michael@0: return moz_xposix_memalign(ptr, alignment, size); michael@0: } michael@0: // else: (0 == err) or (EINVAL == err) michael@0: return err; michael@0: } michael@0: int michael@0: moz_posix_memalign(void **ptr, size_t alignment, size_t size) michael@0: { michael@0: int code = posix_memalign(ptr, alignment, size); michael@0: if (code) michael@0: return code; michael@0: michael@0: #if defined(XP_MACOSX) michael@0: // Workaround faulty OSX posix_memalign, which provides memory with the michael@0: // incorrect alignment sometimes, but returns 0 as if nothing was wrong. michael@0: size_t mask = alignment - 1; michael@0: if (((size_t)(*ptr) & mask) != 0) { michael@0: void* old = *ptr; michael@0: code = moz_posix_memalign(ptr, alignment, size); michael@0: free(old); michael@0: } michael@0: #endif michael@0: michael@0: return code; michael@0: michael@0: } michael@0: #endif // if defined(HAVE_POSIX_MEMALIGN) michael@0: michael@0: #if defined(HAVE_MEMALIGN) michael@0: void* michael@0: moz_xmemalign(size_t boundary, size_t size) michael@0: { michael@0: void* ptr = memalign(boundary, size); michael@0: if (UNLIKELY(!ptr && EINVAL != errno)) { michael@0: mozalloc_handle_oom(size); michael@0: return moz_xmemalign(boundary, size); michael@0: } michael@0: // non-NULL ptr or errno == EINVAL michael@0: return ptr; michael@0: } michael@0: void* michael@0: moz_memalign(size_t boundary, size_t size) michael@0: { michael@0: return memalign(boundary, size); michael@0: } michael@0: #endif // if defined(HAVE_MEMALIGN) michael@0: michael@0: #if defined(HAVE_VALLOC) michael@0: void* michael@0: moz_xvalloc(size_t size) michael@0: { michael@0: void* ptr = valloc(size); michael@0: if (UNLIKELY(!ptr)) { michael@0: mozalloc_handle_oom(size); michael@0: return moz_xvalloc(size); michael@0: } michael@0: return ptr; michael@0: } michael@0: void* michael@0: moz_valloc(size_t size) michael@0: { michael@0: return valloc(size); michael@0: } michael@0: #endif // if defined(HAVE_VALLOC) michael@0: michael@0: size_t michael@0: moz_malloc_usable_size(void *ptr) michael@0: { michael@0: if (!ptr) michael@0: return 0; michael@0: michael@0: #if defined(XP_MACOSX) michael@0: return malloc_size(ptr); michael@0: #elif defined(HAVE_MALLOC_USABLE_SIZE) || defined(MOZ_MEMORY) michael@0: return malloc_usable_size(ptr); michael@0: #elif defined(XP_WIN) michael@0: return _msize(ptr); michael@0: #else michael@0: return 0; michael@0: #endif michael@0: } michael@0: michael@0: size_t moz_malloc_size_of(const void *ptr) michael@0: { michael@0: return moz_malloc_usable_size((void *)ptr); michael@0: } michael@0: michael@0: namespace mozilla { michael@0: michael@0: const fallible_t fallible = fallible_t(); michael@0: michael@0: } // namespace mozilla