github.com/moontrade/unsafe@v0.9.1/memory/rpmalloc/malloc.c (about) 1 /* malloc.c - Memory allocator - Public Domain - 2016 Mattias Jansson 2 * 3 * This library provides a cross-platform lock free thread caching malloc implementation in C11. 4 * The latest source code is always available at 5 * 6 * https://github.com/mjansson/rpmalloc 7 * 8 * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. 9 * 10 */ 11 12 // 13 // This file provides overrides for the standard library malloc entry points for C and new/delete operators for C++ 14 // It also provides automatic initialization/finalization of process and threads 15 // 16 #if defined(__TINYC__) || defined(__APPLE__) 17 #include <sys/types.h> 18 #endif 19 20 #include <stddef.h> 21 22 #ifndef ARCH_64BIT 23 # if defined(__LLP64__) || defined(__LP64__) || defined(_WIN64) 24 # define ARCH_64BIT 1 25 _Static_assert(sizeof(size_t) == 8, "Data type size mismatch"); 26 _Static_assert(sizeof(void*) == 8, "Data type size mismatch"); 27 # else 28 # define ARCH_64BIT 0 29 _Static_assert(sizeof(size_t) == 4, "Data type size mismatch"); 30 _Static_assert(sizeof(void*) == 4, "Data type size mismatch"); 31 # endif 32 #endif 33 34 #if (defined(__GNUC__) || defined(__clang__)) 35 #pragma GCC visibility push(default) 36 #endif 37 38 #define USE_IMPLEMENT 1 39 #define USE_INTERPOSE 0 40 #define USE_ALIAS 0 41 42 #if defined(__APPLE__) 43 #undef USE_INTERPOSE 44 #define USE_INTERPOSE 1 45 46 typedef struct interpose_t { 47 void* new_func; 48 void* orig_func; 49 } interpose_t; 50 51 #define MAC_INTERPOSE_PAIR(newf, oldf) { (void*)newf, (void*)oldf } 52 #define MAC_INTERPOSE_SINGLE(newf, oldf) \ 53 __attribute__((used)) static const interpose_t macinterpose##newf##oldf \ 54 __attribute__ ((section("__DATA, __interpose"))) = MAC_INTERPOSE_PAIR(newf, oldf) 55 56 #endif 57 58 #if !defined(_WIN32) && !defined(__APPLE__) 59 #undef USE_IMPLEMENT 60 #undef USE_ALIAS 61 #define USE_IMPLEMENT 0 62 #define USE_ALIAS 1 63 #endif 64 65 #ifdef _MSC_VER 66 #pragma warning (disable : 4100) 67 #undef malloc 68 #undef free 69 #undef calloc 70 #define RPMALLOC_RESTRICT __declspec(restrict) 71 #else 72 #define RPMALLOC_RESTRICT 73 #endif 74 75 #if ENABLE_OVERRIDE 76 77 typedef struct rp_nothrow_t { int __dummy; } rp_nothrow_t; 78 79 #if USE_IMPLEMENT 80 81 extern inline RPMALLOC_RESTRICT void* RPMALLOC_CDECL malloc(size_t size) { return rpmalloc(size); } 82 extern inline RPMALLOC_RESTRICT void* RPMALLOC_CDECL calloc(size_t count, size_t size) { return rpcalloc(count, size); } 83 extern inline RPMALLOC_RESTRICT void* RPMALLOC_CDECL realloc(void* ptr, size_t size) { return rprealloc(ptr, size); } 84 extern inline void* RPMALLOC_CDECL reallocf(void* ptr, size_t size) { return rprealloc(ptr, size); } 85 extern inline void* RPMALLOC_CDECL aligned_alloc(size_t alignment, size_t size) { return rpaligned_alloc(alignment, size); } 86 extern inline void* RPMALLOC_CDECL memalign(size_t alignment, size_t size) { return rpmemalign(alignment, size); } 87 extern inline int RPMALLOC_CDECL posix_memalign(void** memptr, size_t alignment, size_t size) { return rpposix_memalign(memptr, alignment, size); } 88 extern inline void RPMALLOC_CDECL free(void* ptr) { rpfree(ptr); } 89 extern inline void RPMALLOC_CDECL cfree(void* ptr) { rpfree(ptr); } 90 extern inline size_t RPMALLOC_CDECL malloc_usable_size(void* ptr) { return rpmalloc_usable_size(ptr); } 91 extern inline size_t RPMALLOC_CDECL malloc_size(void* ptr) { return rpmalloc_usable_size(ptr); } 92 93 #ifdef _WIN32 94 // For Windows, #include <rpnew.h> in one source file to get the C++ operator overrides implemented in your module 95 #else 96 // Overload the C++ operators using the mangled names (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling) 97 // operators delete and delete[] 98 #define RPDEFVIS __attribute__((visibility("default"))) 99 extern void _ZdlPv(void* p); void RPDEFVIS _ZdlPv(void* p) { rpfree(p); } 100 extern void _ZdaPv(void* p); void RPDEFVIS _ZdaPv(void* p) { rpfree(p); } 101 #if ARCH_64BIT 102 // 64-bit operators new and new[], normal and aligned 103 extern void* _Znwm(uint64_t size); void* RPDEFVIS _Znwm(uint64_t size) { return rpmalloc(size); } 104 extern void* _Znam(uint64_t size); void* RPDEFVIS _Znam(uint64_t size) { return rpmalloc(size); } 105 extern void* _Znwmm(uint64_t size, uint64_t align); void* RPDEFVIS _Znwmm(uint64_t size, uint64_t align) { return rpaligned_alloc(align, size); } 106 extern void* _Znamm(uint64_t size, uint64_t align); void* RPDEFVIS _Znamm(uint64_t size, uint64_t align) { return rpaligned_alloc(align, size); } 107 extern void* _ZnwmSt11align_val_t(uint64_t size, uint64_t align); void* RPDEFVIS _ZnwmSt11align_val_t(uint64_t size, uint64_t align) { return rpaligned_alloc(align, size); } 108 extern void* _ZnamSt11align_val_t(uint64_t size, uint64_t align); void* RPDEFVIS _ZnamSt11align_val_t(uint64_t size, uint64_t align) { return rpaligned_alloc(align, size); } 109 extern void* _ZnwmRKSt9nothrow_t(uint64_t size, rp_nothrow_t t); void* RPDEFVIS _ZnwmRKSt9nothrow_t(uint64_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } 110 extern void* _ZnamRKSt9nothrow_t(uint64_t size, rp_nothrow_t t); void* RPDEFVIS _ZnamRKSt9nothrow_t(uint64_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } 111 extern void* _ZnwmSt11align_val_tRKSt9nothrow_t(uint64_t size, uint64_t align, rp_nothrow_t t); void* RPDEFVIS _ZnwmSt11align_val_tRKSt9nothrow_t(uint64_t size, uint64_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } 112 extern void* _ZnamSt11align_val_tRKSt9nothrow_t(uint64_t size, uint64_t align, rp_nothrow_t t); void* RPDEFVIS _ZnamSt11align_val_tRKSt9nothrow_t(uint64_t size, uint64_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } 113 // 64-bit operators sized delete and delete[], normal and aligned 114 extern void _ZdlPvm(void* p, uint64_t size); void RPDEFVIS _ZdlPvm(void* p, uint64_t size) { rpfree(p); (void)sizeof(size); } 115 extern void _ZdaPvm(void* p, uint64_t size); void RPDEFVIS _ZdaPvm(void* p, uint64_t size) { rpfree(p); (void)sizeof(size); } 116 extern void _ZdlPvSt11align_val_t(void* p, uint64_t align); void RPDEFVIS _ZdlPvSt11align_val_t(void* p, uint64_t align) { rpfree(p); (void)sizeof(align); } 117 extern void _ZdaPvSt11align_val_t(void* p, uint64_t align); void RPDEFVIS _ZdaPvSt11align_val_t(void* p, uint64_t align) { rpfree(p); (void)sizeof(align); } 118 extern void _ZdlPvmSt11align_val_t(void* p, uint64_t size, uint64_t align); void RPDEFVIS _ZdlPvmSt11align_val_t(void* p, uint64_t size, uint64_t align) { rpfree(p); (void)sizeof(size); (void)sizeof(align); } 119 extern void _ZdaPvmSt11align_val_t(void* p, uint64_t size, uint64_t align); void RPDEFVIS _ZdaPvmSt11align_val_t(void* p, uint64_t size, uint64_t align) { rpfree(p); (void)sizeof(size); (void)sizeof(align); } 120 #else 121 // 32-bit operators new and new[], normal and aligned 122 extern void* _Znwj(uint32_t size); void* RPDEFVIS _Znwj(uint32_t size) { return rpmalloc(size); } 123 extern void* _Znaj(uint32_t size); void* RPDEFVIS _Znaj(uint32_t size) { return rpmalloc(size); } 124 extern void* _Znwjj(uint32_t size, uint32_t align); void* RPDEFVIS _Znwjj(uint32_t size, uint32_t align) { return rpaligned_alloc(align, size); } 125 extern void* _Znajj(uint32_t size, uint32_t align); void* RPDEFVIS _Znajj(uint32_t size, uint32_t align) { return rpaligned_alloc(align, size); } 126 extern void* _ZnwjSt11align_val_t(size_t size, size_t align); void* RPDEFVIS _ZnwjSt11align_val_t(size_t size, size_t align) { return rpaligned_alloc(align, size); } 127 extern void* _ZnajSt11align_val_t(size_t size, size_t align); void* RPDEFVIS _ZnajSt11align_val_t(size_t size, size_t align) { return rpaligned_alloc(align, size); } 128 extern void* _ZnwjRKSt9nothrow_t(size_t size, rp_nothrow_t t); void* RPDEFVIS _ZnwjRKSt9nothrow_t(size_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } 129 extern void* _ZnajRKSt9nothrow_t(size_t size, rp_nothrow_t t); void* RPDEFVIS _ZnajRKSt9nothrow_t(size_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } 130 extern void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t); void* RPDEFVIS _ZnwjSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } 131 extern void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t); void* RPDEFVIS _ZnajSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } 132 // 32-bit operators sized delete and delete[], normal and aligned 133 extern void _ZdlPvj(void* p, uint64_t size); void RPDEFVIS _ZdlPvj(void* p, uint64_t size) { rpfree(p); (void)sizeof(size); } 134 extern void _ZdaPvj(void* p, uint64_t size); void RPDEFVIS _ZdaPvj(void* p, uint64_t size) { rpfree(p); (void)sizeof(size); } 135 extern void _ZdlPvSt11align_val_t(void* p, uint32_t align); void RPDEFVIS _ZdlPvSt11align_val_t(void* p, uint64_t a) { rpfree(p); (void)sizeof(align); } 136 extern void _ZdaPvSt11align_val_t(void* p, uint32_t align); void RPDEFVIS _ZdaPvSt11align_val_t(void* p, uint64_t a) { rpfree(p); (void)sizeof(align); } 137 extern void _ZdlPvjSt11align_val_t(void* p, uint32_t size, uint32_t align); void RPDEFVIS _ZdlPvjSt11align_val_t(void* p, uint64_t size, uint64_t align) { rpfree(p); (void)sizeof(size); (void)sizeof(a); } 138 extern void _ZdaPvjSt11align_val_t(void* p, uint32_t size, uint32_t align); void RPDEFVIS _ZdaPvjSt11align_val_t(void* p, uint64_t size, uint64_t align) { rpfree(p); (void)sizeof(size); (void)sizeof(a); } 139 #endif 140 #endif 141 #endif 142 143 #if USE_INTERPOSE || USE_ALIAS 144 145 static void* rpmalloc_nothrow(size_t size, rp_nothrow_t t) { (void)sizeof(t); return rpmalloc(size); } 146 static void* rpaligned_alloc_reverse(size_t size, size_t align) { return rpaligned_alloc(align, size); } 147 static void* rpaligned_alloc_reverse_nothrow(size_t size, size_t align, rp_nothrow_t t) { (void)sizeof(t); return rpaligned_alloc(align, size); } 148 static void rpfree_size(void* p, size_t size) { (void)sizeof(size); rpfree(p); } 149 static void rpfree_aligned(void* p, size_t align) { (void)sizeof(align); rpfree(p); } 150 static void rpfree_size_aligned(void* p, size_t size, size_t align) { (void)sizeof(size); (void)sizeof(align); rpfree(p); } 151 152 #endif 153 154 #if USE_INTERPOSE 155 156 __attribute__((used)) static const interpose_t macinterpose_malloc[] 157 __attribute__ ((section("__DATA, __interpose"))) = { 158 //new and new[] 159 MAC_INTERPOSE_PAIR(rpmalloc, _Znwm), 160 MAC_INTERPOSE_PAIR(rpmalloc, _Znam), 161 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse, _Znwmm), 162 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse, _Znamm), 163 MAC_INTERPOSE_PAIR(rpmalloc_nothrow, _ZnwmRKSt9nothrow_t), 164 MAC_INTERPOSE_PAIR(rpmalloc_nothrow, _ZnamRKSt9nothrow_t), 165 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse, _ZnwmSt11align_val_t), 166 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse, _ZnamSt11align_val_t), 167 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse_nothrow, _ZnwmSt11align_val_tRKSt9nothrow_t), 168 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse_nothrow, _ZnamSt11align_val_tRKSt9nothrow_t), 169 //delete and delete[] 170 MAC_INTERPOSE_PAIR(rpfree, _ZdlPv), 171 MAC_INTERPOSE_PAIR(rpfree, _ZdaPv), 172 MAC_INTERPOSE_PAIR(rpfree_size, _ZdlPvm), 173 MAC_INTERPOSE_PAIR(rpfree_size, _ZdaPvm), 174 MAC_INTERPOSE_PAIR(rpfree_aligned, _ZdlPvSt11align_val_t), 175 MAC_INTERPOSE_PAIR(rpfree_aligned, _ZdaPvSt11align_val_t), 176 MAC_INTERPOSE_PAIR(rpfree_size_aligned, _ZdlPvmSt11align_val_t), 177 MAC_INTERPOSE_PAIR(rpfree_size_aligned, _ZdaPvmSt11align_val_t), 178 //libc entry points 179 MAC_INTERPOSE_PAIR(rpmalloc, malloc), 180 MAC_INTERPOSE_PAIR(rpmalloc, calloc), 181 MAC_INTERPOSE_PAIR(rprealloc, realloc), 182 MAC_INTERPOSE_PAIR(rprealloc, reallocf), 183 #if defined(__MAC_10_15) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_15 184 MAC_INTERPOSE_PAIR(rpaligned_alloc, aligned_alloc), 185 #endif 186 MAC_INTERPOSE_PAIR(rpmemalign, memalign), 187 MAC_INTERPOSE_PAIR(rpposix_memalign, posix_memalign), 188 MAC_INTERPOSE_PAIR(rpfree, free), 189 MAC_INTERPOSE_PAIR(rpfree, cfree), 190 MAC_INTERPOSE_PAIR(rpmalloc_usable_size, malloc_usable_size), 191 MAC_INTERPOSE_PAIR(rpmalloc_usable_size, malloc_size) 192 }; 193 194 #endif 195 196 #if USE_ALIAS 197 198 #define RPALIAS(fn) __attribute__((alias(#fn), used, visibility("default"))); 199 200 // Alias the C++ operators using the mangled names (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling) 201 202 // operators delete and delete[] 203 void _ZdlPv(void* p) RPALIAS(rpfree) 204 void _ZdaPv(void* p) RPALIAS(rpfree) 205 206 #if ARCH_64BIT 207 // 64-bit operators new and new[], normal and aligned 208 void* _Znwm(uint64_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) 209 void* _Znam(uint64_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) 210 void* _Znwmm(uint64_t size, uint64_t align) RPALIAS(rpaligned_alloc_reverse) 211 void* _Znamm(uint64_t size, uint64_t align) RPALIAS(rpaligned_alloc_reverse) 212 void* _ZnwmSt11align_val_t(size_t size, size_t align) RPALIAS(rpaligned_alloc_reverse) 213 void* _ZnamSt11align_val_t(size_t size, size_t align) RPALIAS(rpaligned_alloc_reverse) 214 void* _ZnwmRKSt9nothrow_t(size_t size, rp_nothrow_t t) RPALIAS(rpmalloc_nothrow) 215 void* _ZnamRKSt9nothrow_t(size_t size, rp_nothrow_t t) RPALIAS(rpmalloc_nothrow) 216 void* _ZnwmSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) RPALIAS(rpaligned_alloc_reverse_nothrow) 217 void* _ZnamSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) RPALIAS(rpaligned_alloc_reverse_nothrow) 218 // 64-bit operators delete and delete[], sized and aligned 219 void _ZdlPvm(void* p, size_t n) RPALIAS(rpfree_size) 220 void _ZdaPvm(void* p, size_t n) RPALIAS(rpfree_size) 221 void _ZdlPvSt11align_val_t(void* p, size_t a) RPALIAS(rpfree_aligned) 222 void _ZdaPvSt11align_val_t(void* p, size_t a) RPALIAS(rpfree_aligned) 223 void _ZdlPvmSt11align_val_t(void* p, size_t n, size_t a) RPALIAS(rpfree_size_aligned) 224 void _ZdaPvmSt11align_val_t(void* p, size_t n, size_t a) RPALIAS(rpfree_size_aligned) 225 #else 226 // 32-bit operators new and new[], normal and aligned 227 void* _Znwj(uint32_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) 228 void* _Znaj(uint32_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) 229 void* _Znwjj(uint32_t size, uint32_t align) RPALIAS(rpaligned_alloc_reverse) 230 void* _Znajj(uint32_t size, uint32_t align) RPALIAS(rpaligned_alloc_reverse) 231 void* _ZnwjSt11align_val_t(size_t size, size_t align) RPALIAS(rpaligned_alloc_reverse) 232 void* _ZnajSt11align_val_t(size_t size, size_t align) RPALIAS(rpaligned_alloc_reverse) 233 void* _ZnwjRKSt9nothrow_t(size_t size, rp_nothrow_t t) RPALIAS(rpmalloc_nothrow) 234 void* _ZnajRKSt9nothrow_t(size_t size, rp_nothrow_t t) RPALIAS(rpmalloc_nothrow) 235 void* _ZnwjSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) RPALIAS(rpaligned_alloc_reverse_nothrow) 236 void* _ZnajSt11align_val_tRKSt9nothrow_t(size_t size, size_t align, rp_nothrow_t t) RPALIAS(rpaligned_alloc_reverse_nothrow) 237 // 32-bit operators delete and delete[], sized and aligned 238 void _ZdlPvj(void* p, size_t n) RPALIAS(rpfree_size) 239 void _ZdaPvj(void* p, size_t n) RPALIAS(rpfree_size) 240 void _ZdlPvSt11align_val_t(void* p, size_t a) RPALIAS(rpfree_aligned) 241 void _ZdaPvSt11align_val_t(void* p, size_t a) RPALIAS(rpfree_aligned) 242 void _ZdlPvjSt11align_val_t(void* p, size_t n, size_t a) RPALIAS(rpfree_size_aligned) 243 void _ZdaPvjSt11align_val_t(void* p, size_t n, size_t a) RPALIAS(rpfree_size_aligned) 244 #endif 245 246 void* malloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) 247 void* calloc(size_t count, size_t size) RPALIAS(rpcalloc) 248 void* realloc(void* ptr, size_t size) RPALIAS(rprealloc) 249 void* reallocf(void* ptr, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2) RPALIAS(rprealloc) 250 void* aligned_alloc(size_t alignment, size_t size) RPALIAS(rpaligned_alloc) 251 void* memalign(size_t alignment, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2) RPALIAS(rpmemalign) 252 int posix_memalign(void** memptr, size_t alignment, size_t size) RPALIAS(rpposix_memalign) 253 void free(void* ptr) RPALIAS(rpfree) 254 void cfree(void* ptr) RPALIAS(rpfree) 255 #if defined(__ANDROID__) || defined(__FreeBSD__) 256 size_t malloc_usable_size(const void* ptr) RPALIAS(rpmalloc_usable_size) 257 #else 258 size_t malloc_usable_size(void* ptr) RPALIAS(rpmalloc_usable_size) 259 #endif 260 size_t malloc_size(void* ptr) RPALIAS(rpmalloc_usable_size) 261 262 #endif 263 264 static inline size_t 265 _rpmalloc_page_size(void) { 266 return _memory_page_size; 267 } 268 269 extern void* RPMALLOC_CDECL 270 reallocarray(void* ptr, size_t count, size_t size) { 271 size_t total; 272 #if ENABLE_VALIDATE_ARGS 273 #ifdef _MSC_VER 274 int err = SizeTMult(count, size, &total); 275 if ((err != S_OK) || (total >= MAX_ALLOC_SIZE)) { 276 errno = EINVAL; 277 return 0; 278 } 279 #else 280 int err = __builtin_umull_overflow(count, size, &total); 281 if (err || (total >= MAX_ALLOC_SIZE)) { 282 errno = EINVAL; 283 return 0; 284 } 285 #endif 286 #else 287 total = count * size; 288 #endif 289 return realloc(ptr, total); 290 } 291 292 extern inline void* RPMALLOC_CDECL 293 valloc(size_t size) { 294 get_thread_heap(); 295 return rpaligned_alloc(_rpmalloc_page_size(), size); 296 } 297 298 extern inline void* RPMALLOC_CDECL 299 pvalloc(size_t size) { 300 get_thread_heap(); 301 const size_t page_size = _rpmalloc_page_size(); 302 const size_t aligned_size = ((size + page_size - 1) / page_size) * page_size; 303 #if ENABLE_VALIDATE_ARGS 304 if (aligned_size < size) { 305 errno = EINVAL; 306 return 0; 307 } 308 #endif 309 return rpaligned_alloc(_rpmalloc_page_size(), aligned_size); 310 } 311 312 #endif // ENABLE_OVERRIDE 313 314 #if ENABLE_PRELOAD 315 316 #ifdef _WIN32 317 318 #if defined(BUILD_DYNAMIC_LINK) && BUILD_DYNAMIC_LINK 319 320 extern __declspec(dllexport) BOOL WINAPI 321 DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved); 322 323 extern __declspec(dllexport) BOOL WINAPI 324 DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) { 325 (void)sizeof(reserved); 326 (void)sizeof(instance); 327 if (reason == DLL_PROCESS_ATTACH) 328 rpmalloc_initialize(); 329 else if (reason == DLL_PROCESS_DETACH) 330 rpmalloc_finalize(); 331 else if (reason == DLL_THREAD_ATTACH) 332 rpmalloc_thread_initialize(); 333 else if (reason == DLL_THREAD_DETACH) 334 rpmalloc_thread_finalize(1); 335 return TRUE; 336 } 337 338 //end BUILD_DYNAMIC_LINK 339 #else 340 341 extern void 342 _global_rpmalloc_init(void) { 343 rpmalloc_set_main_thread(); 344 rpmalloc_initialize(); 345 } 346 347 #if defined(__clang__) || defined(__GNUC__) 348 349 static void __attribute__((constructor)) 350 initializer(void) { 351 _global_rpmalloc_init(); 352 } 353 354 #elif defined(_MSC_VER) 355 356 #pragma section(".CRT$XIB",read) 357 __declspec(allocate(".CRT$XIB")) void (*_rpmalloc_module_init)(void) = _global_rpmalloc_init; 358 #pragma comment(linker, "/include:_rpmalloc_module_init") 359 360 #endif 361 362 //end !BUILD_DYNAMIC_LINK 363 #endif 364 365 #else 366 367 #include <pthread.h> 368 #include <stdlib.h> 369 #include <stdint.h> 370 #include <unistd.h> 371 372 extern void 373 rpmalloc_set_main_thread(void); 374 375 static pthread_key_t destructor_key; 376 377 static void 378 thread_destructor(void*); 379 380 static void __attribute__((constructor)) 381 initializer(void) { 382 rpmalloc_set_main_thread(); 383 rpmalloc_initialize(); 384 pthread_key_create(&destructor_key, thread_destructor); 385 } 386 387 static void __attribute__((destructor)) 388 finalizer(void) { 389 rpmalloc_finalize(); 390 } 391 392 typedef struct { 393 void* (*real_start)(void*); 394 void* real_arg; 395 } thread_starter_arg; 396 397 static void* 398 thread_starter(void* argptr) { 399 thread_starter_arg* arg = argptr; 400 void* (*real_start)(void*) = arg->real_start; 401 void* real_arg = arg->real_arg; 402 rpmalloc_thread_initialize(); 403 rpfree(argptr); 404 pthread_setspecific(destructor_key, (void*)1); 405 return (*real_start)(real_arg); 406 } 407 408 static void 409 thread_destructor(void* value) { 410 (void)sizeof(value); 411 rpmalloc_thread_finalize(1); 412 } 413 414 #ifdef __APPLE__ 415 416 static int 417 pthread_create_proxy(pthread_t* thread, 418 const pthread_attr_t* attr, 419 void* (*start_routine)(void*), 420 void* arg) { 421 rpmalloc_initialize(); 422 thread_starter_arg* starter_arg = rpmalloc(sizeof(thread_starter_arg)); 423 starter_arg->real_start = start_routine; 424 starter_arg->real_arg = arg; 425 return pthread_create(thread, attr, thread_starter, starter_arg); 426 } 427 428 MAC_INTERPOSE_SINGLE(pthread_create_proxy, pthread_create); 429 430 #else 431 432 #include <dlfcn.h> 433 434 int 435 pthread_create(pthread_t* thread, 436 const pthread_attr_t* attr, 437 void* (*start_routine)(void*), 438 void* arg) { 439 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ 440 defined(__APPLE__) || defined(__HAIKU__) 441 char fname[] = "pthread_create"; 442 #else 443 char fname[] = "_pthread_create"; 444 #endif 445 void* real_pthread_create = dlsym(RTLD_NEXT, fname); 446 rpmalloc_thread_initialize(); 447 thread_starter_arg* starter_arg = rpmalloc(sizeof(thread_starter_arg)); 448 starter_arg->real_start = start_routine; 449 starter_arg->real_arg = arg; 450 return (*(int (*)(pthread_t*, const pthread_attr_t*, void* (*)(void*), void*))real_pthread_create)(thread, attr, thread_starter, starter_arg); 451 } 452 453 #endif 454 455 #endif 456 457 #endif 458 459 #if ENABLE_OVERRIDE 460 461 #if defined(__GLIBC__) && defined(__linux__) 462 463 void* __libc_malloc(size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc) 464 void* __libc_calloc(size_t count, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2) RPALIAS(rpcalloc) 465 void* __libc_realloc(void* p, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2) RPALIAS(rprealloc) 466 void __libc_free(void* p) RPALIAS(rpfree) 467 void __libc_cfree(void* p) RPALIAS(rpfree) 468 void* __libc_memalign(size_t align, size_t size) RPMALLOC_ATTRIB_MALLOC RPMALLOC_ATTRIB_ALLOC_SIZE(2) RPALIAS(rpmemalign) 469 int __posix_memalign(void** p, size_t align, size_t size) RPALIAS(rpposix_memalign) 470 471 extern void* __libc_valloc(size_t size); 472 extern void* __libc_pvalloc(size_t size); 473 474 void* 475 __libc_valloc(size_t size) { 476 return valloc(size); 477 } 478 479 void* 480 __libc_pvalloc(size_t size) { 481 return pvalloc(size); 482 } 483 484 #endif 485 486 #endif 487 488 #if (defined(__GNUC__) || defined(__clang__)) 489 #pragma GCC visibility pop 490 #endif