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