[176] | 1 | /* -*- C++ -*- */ |
---|
| 2 | |
---|
| 3 | /* |
---|
| 4 | |
---|
| 5 | Heap Layers: An Extensible Memory Allocation Infrastructure |
---|
| 6 | |
---|
| 7 | Copyright (C) 2000-2007 by Emery Berger |
---|
| 8 | http://www.cs.umass.edu/~emery |
---|
| 9 | emery@cs.umass.edu |
---|
| 10 | |
---|
| 11 | This program is free software; you can redistribute it and/or modify |
---|
| 12 | it under the terms of the GNU General Public License as published by |
---|
| 13 | the Free Software Foundation; either version 2 of the License, or |
---|
| 14 | (at your option) any later version. |
---|
| 15 | |
---|
| 16 | This program is distributed in the hope that it will be useful, |
---|
| 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 19 | GNU General Public License for more details. |
---|
| 20 | |
---|
| 21 | You should have received a copy of the GNU General Public License |
---|
| 22 | along with this program; if not, write to the Free Software |
---|
| 23 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
| 24 | |
---|
| 25 | */ |
---|
| 26 | |
---|
| 27 | /* |
---|
| 28 | * @file wrapper.cpp |
---|
| 29 | * @brief Replaces malloc with appropriate calls to TheCustomHeapType. |
---|
| 30 | * @author Emery Berger <http://www.cs.umass.edu/~emery> |
---|
| 31 | */ |
---|
| 32 | |
---|
| 33 | #include <string.h> // for memcpy |
---|
| 34 | |
---|
| 35 | #if defined(__APPLE__) |
---|
| 36 | #include <malloc/malloc.h> |
---|
| 37 | #elif defined(__FreeBSD__) |
---|
| 38 | #include <stdlib.h> |
---|
| 39 | #else |
---|
| 40 | #include <malloc.h> // for memalign |
---|
| 41 | #endif |
---|
| 42 | |
---|
| 43 | #ifdef _WIN32 |
---|
| 44 | #define WIN32_LEAN_AND_MEAN |
---|
| 45 | #include <windows.h> |
---|
| 46 | // Disable warnings about long (> 255 chars) identifiers. |
---|
| 47 | #pragma warning(disable:4786) |
---|
| 48 | // Set inlining to the maximum possible depth. |
---|
| 49 | #pragma inline_depth(255) |
---|
| 50 | #pragma warning(disable: 4074) // initializers put in compiler reserved area |
---|
| 51 | #pragma init_seg(compiler) |
---|
| 52 | |
---|
| 53 | #pragma comment(linker, "/merge:.CRT=.data") |
---|
| 54 | |
---|
| 55 | #pragma comment(linker, "/disallowlib:libc.lib") |
---|
| 56 | #pragma comment(linker, "/disallowlib:libcd.lib") |
---|
| 57 | #pragma comment(linker, "/disallowlib:libcmt.lib") |
---|
| 58 | #pragma comment(linker, "/disallowlib:libcmtd.lib") |
---|
| 59 | #pragma comment(linker, "/disallowlib:msvcrtd.lib") |
---|
| 60 | |
---|
| 61 | #else |
---|
| 62 | #include <errno.h> |
---|
| 63 | #endif |
---|
| 64 | |
---|
| 65 | #if !defined(CUSTOM_PREFIX) |
---|
| 66 | #define CUSTOM_PREFIX(n) n |
---|
| 67 | #endif |
---|
| 68 | |
---|
| 69 | #define CUSTOM_MALLOC(x) CUSTOM_PREFIX(malloc)(x) |
---|
| 70 | #define CUSTOM_FREE(x) CUSTOM_PREFIX(free)(x) |
---|
| 71 | #define CUSTOM_REALLOC(x,y) CUSTOM_PREFIX(realloc)(x,y) |
---|
| 72 | #define CUSTOM_CALLOC(x,y) CUSTOM_PREFIX(calloc)(x,y) |
---|
| 73 | #define CUSTOM_MEMALIGN(x,y) CUSTOM_PREFIX(memalign)(x,y) |
---|
| 74 | #define CUSTOM_GETSIZE(x) CUSTOM_PREFIX(malloc_usable_size)(x) |
---|
| 75 | #define CUSTOM_MALLOPT(x,y) CUSTOM_PREFIX(mallopt)(x,y) |
---|
| 76 | #define CUSTOM_VALLOC(x) CUSTOM_PREFIX(valloc)(x) |
---|
| 77 | #define CUSTOM_PVALLOC(x) CUSTOM_PREFIX(pvalloc)(x) |
---|
| 78 | |
---|
| 79 | #if defined(_WIN32) |
---|
| 80 | #define MYCDECL __cdecl |
---|
| 81 | #if !defined(NO_INLINE) |
---|
| 82 | #define NO_INLINE __declspec(noinline) |
---|
| 83 | #endif |
---|
| 84 | #pragma inline_depth(255) |
---|
| 85 | |
---|
| 86 | #if !defined(NDEBUG) |
---|
| 87 | #define __forceinline inline |
---|
| 88 | #endif |
---|
| 89 | |
---|
| 90 | #else |
---|
| 91 | #define MYCDECL |
---|
| 92 | #endif |
---|
| 93 | |
---|
| 94 | /***** generic malloc functions *****/ |
---|
| 95 | |
---|
| 96 | extern "C" void * MYCDECL CUSTOM_MALLOC (size_t sz) |
---|
| 97 | { |
---|
| 98 | TheCustomHeapType * theCustomHeap = getCustomHeap(); |
---|
| 99 | void * ptr = theCustomHeap->malloc (sz); |
---|
| 100 | return ptr; |
---|
| 101 | } |
---|
| 102 | |
---|
| 103 | extern "C" void * MYCDECL CUSTOM_CALLOC (size_t nelem, size_t elsize) |
---|
| 104 | { |
---|
| 105 | size_t n = nelem * elsize; |
---|
| 106 | void * ptr = CUSTOM_MALLOC (n); |
---|
| 107 | // Zero out the malloc'd block. |
---|
| 108 | if (ptr != NULL) { |
---|
| 109 | memset (ptr, 0, n); |
---|
| 110 | } |
---|
| 111 | return ptr; |
---|
| 112 | } |
---|
| 113 | |
---|
| 114 | |
---|
| 115 | #if !defined(_WIN32) |
---|
| 116 | extern "C" void * MYCDECL CUSTOM_MEMALIGN (size_t alignment, size_t size); |
---|
| 117 | |
---|
| 118 | extern "C" int posix_memalign (void **memptr, size_t alignment, size_t size) |
---|
| 119 | { |
---|
| 120 | // Check for non power-of-two alignment. |
---|
| 121 | if ((alignment == 0) || |
---|
| 122 | (alignment & (alignment - 1))) |
---|
| 123 | { |
---|
| 124 | return EINVAL; |
---|
| 125 | } |
---|
| 126 | void * ptr = CUSTOM_MEMALIGN (alignment, size); |
---|
| 127 | if (!ptr) { |
---|
| 128 | return ENOMEM; |
---|
| 129 | } else { |
---|
| 130 | *memptr = ptr; |
---|
| 131 | return 0; |
---|
| 132 | } |
---|
| 133 | } |
---|
| 134 | #endif |
---|
| 135 | |
---|
| 136 | |
---|
| 137 | extern "C" void * MYCDECL CUSTOM_MEMALIGN (size_t alignment, size_t size) |
---|
| 138 | { |
---|
| 139 | // NOTE: This function is deprecated. |
---|
| 140 | if (alignment == sizeof(double)) { |
---|
| 141 | return CUSTOM_MALLOC (size); |
---|
| 142 | } else { |
---|
| 143 | void * ptr = CUSTOM_MALLOC (size + 2 * alignment); |
---|
| 144 | void * alignedPtr = (void *) (((size_t) ptr + alignment - 1) & ~(alignment - 1)); |
---|
| 145 | return alignedPtr; |
---|
| 146 | } |
---|
| 147 | } |
---|
| 148 | |
---|
| 149 | extern "C" size_t MYCDECL CUSTOM_GETSIZE (void * ptr) |
---|
| 150 | { |
---|
| 151 | TheCustomHeapType * theCustomHeap = getCustomHeap(); |
---|
| 152 | if (ptr == NULL) { |
---|
| 153 | return 0; |
---|
| 154 | } |
---|
| 155 | return theCustomHeap->getSize(ptr); |
---|
| 156 | } |
---|
| 157 | |
---|
| 158 | extern "C" void MYCDECL CUSTOM_FREE (void * ptr) |
---|
| 159 | { |
---|
| 160 | TheCustomHeapType * theCustomHeap = getCustomHeap(); |
---|
| 161 | theCustomHeap->free (ptr); |
---|
| 162 | } |
---|
| 163 | |
---|
| 164 | extern "C" void * MYCDECL CUSTOM_REALLOC (void * ptr, size_t sz) |
---|
| 165 | { |
---|
| 166 | if (ptr == NULL) { |
---|
| 167 | ptr = CUSTOM_MALLOC (sz); |
---|
| 168 | return ptr; |
---|
| 169 | } |
---|
| 170 | if (sz == 0) { |
---|
| 171 | CUSTOM_FREE (ptr); |
---|
| 172 | return NULL; |
---|
| 173 | } |
---|
| 174 | |
---|
| 175 | size_t objSize = CUSTOM_GETSIZE (ptr); |
---|
| 176 | |
---|
| 177 | void * buf = CUSTOM_MALLOC ((size_t) (sz)); |
---|
| 178 | |
---|
| 179 | if (buf != NULL) { |
---|
| 180 | if (objSize == CUSTOM_GETSIZE(buf)) { |
---|
| 181 | // The objects are the same actual size. |
---|
| 182 | // Free the new object and return the original. |
---|
| 183 | CUSTOM_FREE (buf); |
---|
| 184 | return ptr; |
---|
| 185 | } |
---|
| 186 | // Copy the contents of the original object |
---|
| 187 | // up to the size of the new block. |
---|
| 188 | size_t minSize = (objSize < sz) ? objSize : sz; |
---|
| 189 | memcpy (buf, ptr, minSize); |
---|
| 190 | } |
---|
| 191 | |
---|
| 192 | // Free the old block. |
---|
| 193 | CUSTOM_FREE (ptr); |
---|
| 194 | |
---|
| 195 | // Return a pointer to the new one. |
---|
| 196 | return buf; |
---|
| 197 | } |
---|
| 198 | |
---|
| 199 | #if defined(linux) |
---|
| 200 | extern "C" char * MYCDECL CUSTOM_PREFIX(strndup) (const char * s, size_t sz) |
---|
| 201 | { |
---|
| 202 | char * newString = NULL; |
---|
| 203 | if (s != NULL) { |
---|
| 204 | size_t cappedLength = strnlen (s, sz); |
---|
| 205 | if ((newString = (char *) CUSTOM_MALLOC(cappedLength + 1))) { |
---|
| 206 | strncpy(newString, s, cappedLength); |
---|
| 207 | newString[cappedLength] = '\0'; |
---|
| 208 | } |
---|
| 209 | } |
---|
| 210 | return newString; |
---|
| 211 | } |
---|
| 212 | #endif |
---|
| 213 | |
---|
| 214 | extern "C" char * MYCDECL CUSTOM_PREFIX(strdup) (const char * s) |
---|
| 215 | { |
---|
| 216 | char * newString = NULL; |
---|
| 217 | if (s != NULL) { |
---|
| 218 | if ((newString = (char *) CUSTOM_MALLOC(strlen(s) + 1))) { |
---|
| 219 | strcpy(newString, s); |
---|
| 220 | } |
---|
| 221 | } |
---|
| 222 | return newString; |
---|
| 223 | } |
---|
| 224 | |
---|
| 225 | #if !defined(_WIN32) |
---|
| 226 | #include <dlfcn.h> |
---|
| 227 | #include <limits.h> |
---|
| 228 | |
---|
| 229 | #if !defined(RTLD_NEXT) |
---|
| 230 | #define RTLD_NEXT ((void *) -1) |
---|
| 231 | #endif |
---|
| 232 | |
---|
| 233 | |
---|
| 234 | typedef char * getcwdFunction (char *, size_t); |
---|
| 235 | |
---|
| 236 | extern "C" char * MYCDECL CUSTOM_PREFIX(getcwd) (char * buf, size_t size) |
---|
| 237 | { |
---|
| 238 | static getcwdFunction * real_getcwd |
---|
| 239 | = (getcwdFunction *) dlsym (RTLD_NEXT, "getcwd"); |
---|
| 240 | |
---|
| 241 | if (!buf) { |
---|
| 242 | if (size == 0) { |
---|
| 243 | size = PATH_MAX; |
---|
| 244 | } |
---|
| 245 | buf = (char *) CUSTOM_PREFIX(malloc)(size); |
---|
| 246 | } |
---|
| 247 | return (real_getcwd)(buf, size); |
---|
| 248 | } |
---|
| 249 | |
---|
| 250 | #endif |
---|
| 251 | |
---|
| 252 | |
---|
| 253 | void * operator new (size_t sz) |
---|
| 254 | { |
---|
| 255 | void * ptr = CUSTOM_MALLOC (sz); |
---|
| 256 | if (ptr == NULL) { |
---|
| 257 | throw std::bad_alloc(); |
---|
| 258 | } else { |
---|
| 259 | return ptr; |
---|
| 260 | } |
---|
| 261 | } |
---|
| 262 | |
---|
| 263 | void operator delete (void * ptr) |
---|
| 264 | { |
---|
| 265 | CUSTOM_FREE (ptr); |
---|
| 266 | } |
---|
| 267 | |
---|
| 268 | #if !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x420 |
---|
| 269 | void * operator new (size_t sz, const std::nothrow_t&) throw() { |
---|
| 270 | return CUSTOM_MALLOC(sz); |
---|
| 271 | } |
---|
| 272 | |
---|
| 273 | void * operator new[] (size_t size) |
---|
| 274 | { |
---|
| 275 | void * ptr = CUSTOM_MALLOC(size); |
---|
| 276 | if (ptr == NULL) { |
---|
| 277 | throw std::bad_alloc(); |
---|
| 278 | } else { |
---|
| 279 | return ptr; |
---|
| 280 | } |
---|
| 281 | } |
---|
| 282 | |
---|
| 283 | void * operator new[] (size_t sz, const std::nothrow_t&) throw() { |
---|
| 284 | return CUSTOM_MALLOC (sz); |
---|
| 285 | } |
---|
| 286 | |
---|
| 287 | void operator delete[] (void * ptr) |
---|
| 288 | { |
---|
| 289 | CUSTOM_FREE (ptr); |
---|
| 290 | } |
---|
| 291 | |
---|
| 292 | #endif |
---|
| 293 | |
---|
| 294 | |
---|
| 295 | /***** replacement functions for GNU libc extensions to malloc *****/ |
---|
| 296 | |
---|
| 297 | // A stub function to ensure that we capture mallopt. |
---|
| 298 | // It does nothing and always returns a failure value (0). |
---|
| 299 | extern "C" int MYCDECL CUSTOM_MALLOPT (int number, int value) |
---|
| 300 | { |
---|
| 301 | number = number; |
---|
| 302 | value = value; |
---|
| 303 | // Always fail. |
---|
| 304 | return 0; |
---|
| 305 | } |
---|
| 306 | |
---|
| 307 | // NOTE: for convenience, we assume page size = 8192. |
---|
| 308 | |
---|
| 309 | extern "C" void * MYCDECL CUSTOM_VALLOC (size_t sz) |
---|
| 310 | { |
---|
| 311 | return CUSTOM_MEMALIGN (8192, sz); |
---|
| 312 | } |
---|
| 313 | |
---|
| 314 | |
---|
| 315 | extern "C" void * MYCDECL CUSTOM_PVALLOC (size_t sz) |
---|
| 316 | { |
---|
| 317 | // Rounds up to the next pagesize and then calls valloc. Hoard |
---|
| 318 | // doesn't support aligned memory requests. |
---|
| 319 | return CUSTOM_VALLOC ((sz + 8191) & ~8191); |
---|
| 320 | } |
---|