1 //===------------------------ malloc.c ------------------*- C -*-=============//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This library provides a cross-platform lock free thread caching malloc
10 // implementation in C11.
13 // This file provides overrides for the standard library malloc entry points for
14 // C and new/delete operators for C++ It also provides automatic
15 // initialization/finalization of process and threads
17 //===----------------------------------------------------------------------===//
19 #if defined(__TINYC__)
20 #include <sys/types.h>
24 #if defined(__LLP64__) || defined(__LP64__) || defined(_WIN64)
26 _Static_assert(sizeof(size_t) == 8, "Data type size mismatch");
27 _Static_assert(sizeof(void *) == 8, "Data type size mismatch");
30 _Static_assert(sizeof(size_t) == 4, "Data type size mismatch");
31 _Static_assert(sizeof(void *) == 4, "Data type size mismatch");
35 #if (defined(__GNUC__) || defined(__clang__))
36 #pragma GCC visibility push(default)
39 #define USE_IMPLEMENT 1
40 #define USE_INTERPOSE 0
43 #if defined(__APPLE__)
45 #define USE_INTERPOSE 1
47 typedef struct interpose_t
{
52 #define MAC_INTERPOSE_PAIR(newf, oldf) {(void *)newf, (void *)oldf}
53 #define MAC_INTERPOSE_SINGLE(newf, oldf) \
54 __attribute__((used)) static const interpose_t macinterpose##newf##oldf \
55 __attribute__((section("__DATA, __interpose"))) = \
56 MAC_INTERPOSE_PAIR(newf, oldf)
60 #if !defined(_WIN32) && !defined(__APPLE__)
63 #define USE_IMPLEMENT 0
68 #pragma warning(disable : 4100)
72 #define RPMALLOC_RESTRICT __declspec(restrict)
74 #define RPMALLOC_RESTRICT
79 typedef struct rp_nothrow_t
{
85 extern inline RPMALLOC_RESTRICT
void *RPMALLOC_CDECL
malloc(size_t size
) {
86 return rpmalloc(size
);
88 extern inline RPMALLOC_RESTRICT
void *RPMALLOC_CDECL
calloc(size_t count
,
90 return rpcalloc(count
, size
);
92 extern inline RPMALLOC_RESTRICT
void *RPMALLOC_CDECL
realloc(void *ptr
,
94 return rprealloc(ptr
, size
);
96 extern inline void *RPMALLOC_CDECL
reallocf(void *ptr
, size_t size
) {
97 return rprealloc(ptr
, size
);
99 extern inline void *RPMALLOC_CDECL
aligned_alloc(size_t alignment
,
101 return rpaligned_alloc(alignment
, size
);
103 extern inline void *RPMALLOC_CDECL
memalign(size_t alignment
, size_t size
) {
104 return rpmemalign(alignment
, size
);
106 extern inline int RPMALLOC_CDECL
posix_memalign(void **memptr
, size_t alignment
,
108 return rpposix_memalign(memptr
, alignment
, size
);
110 extern inline void RPMALLOC_CDECL
free(void *ptr
) { rpfree(ptr
); }
111 extern inline void RPMALLOC_CDECL
cfree(void *ptr
) { rpfree(ptr
); }
112 extern inline size_t RPMALLOC_CDECL
malloc_usable_size(void *ptr
) {
113 return rpmalloc_usable_size(ptr
);
115 extern inline size_t RPMALLOC_CDECL
malloc_size(void *ptr
) {
116 return rpmalloc_usable_size(ptr
);
120 extern inline RPMALLOC_RESTRICT
void *RPMALLOC_CDECL
_malloc_base(size_t size
) {
121 return rpmalloc(size
);
123 extern inline void RPMALLOC_CDECL
_free_base(void *ptr
) { rpfree(ptr
); }
124 extern inline RPMALLOC_RESTRICT
void *RPMALLOC_CDECL
_calloc_base(size_t count
,
126 return rpcalloc(count
, size
);
128 extern inline size_t RPMALLOC_CDECL
_msize(void *ptr
) {
129 return rpmalloc_usable_size(ptr
);
131 extern inline size_t RPMALLOC_CDECL
_msize_base(void *ptr
) {
132 return rpmalloc_usable_size(ptr
);
134 extern inline RPMALLOC_RESTRICT
void *RPMALLOC_CDECL
135 _realloc_base(void *ptr
, size_t size
) {
136 return rprealloc(ptr
, size
);
141 // For Windows, #include <rpnew.h> in one source file to get the C++ operator
142 // overrides implemented in your module
144 // Overload the C++ operators using the mangled names
145 // (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling) operators
146 // delete and delete[]
147 #define RPDEFVIS __attribute__((visibility("default")))
148 extern void _ZdlPv(void *p
);
149 void RPDEFVIS
_ZdlPv(void *p
) { rpfree(p
); }
150 extern void _ZdaPv(void *p
);
151 void RPDEFVIS
_ZdaPv(void *p
) { rpfree(p
); }
153 // 64-bit operators new and new[], normal and aligned
154 extern void *_Znwm(uint64_t size
);
155 void *RPDEFVIS
_Znwm(uint64_t size
) { return rpmalloc(size
); }
156 extern void *_Znam(uint64_t size
);
157 void *RPDEFVIS
_Znam(uint64_t size
) { return rpmalloc(size
); }
158 extern void *_Znwmm(uint64_t size
, uint64_t align
);
159 void *RPDEFVIS
_Znwmm(uint64_t size
, uint64_t align
) {
160 return rpaligned_alloc(align
, size
);
162 extern void *_Znamm(uint64_t size
, uint64_t align
);
163 void *RPDEFVIS
_Znamm(uint64_t size
, uint64_t align
) {
164 return rpaligned_alloc(align
, size
);
166 extern void *_ZnwmSt11align_val_t(uint64_t size
, uint64_t align
);
167 void *RPDEFVIS
_ZnwmSt11align_val_t(uint64_t size
, uint64_t align
) {
168 return rpaligned_alloc(align
, size
);
170 extern void *_ZnamSt11align_val_t(uint64_t size
, uint64_t align
);
171 void *RPDEFVIS
_ZnamSt11align_val_t(uint64_t size
, uint64_t align
) {
172 return rpaligned_alloc(align
, size
);
174 extern void *_ZnwmRKSt9nothrow_t(uint64_t size
, rp_nothrow_t t
);
175 void *RPDEFVIS
_ZnwmRKSt9nothrow_t(uint64_t size
, rp_nothrow_t t
) {
177 return rpmalloc(size
);
179 extern void *_ZnamRKSt9nothrow_t(uint64_t size
, rp_nothrow_t t
);
180 void *RPDEFVIS
_ZnamRKSt9nothrow_t(uint64_t size
, rp_nothrow_t t
) {
182 return rpmalloc(size
);
184 extern void *_ZnwmSt11align_val_tRKSt9nothrow_t(uint64_t size
, uint64_t align
,
186 void *RPDEFVIS
_ZnwmSt11align_val_tRKSt9nothrow_t(uint64_t size
, uint64_t align
,
189 return rpaligned_alloc(align
, size
);
191 extern void *_ZnamSt11align_val_tRKSt9nothrow_t(uint64_t size
, uint64_t align
,
193 void *RPDEFVIS
_ZnamSt11align_val_tRKSt9nothrow_t(uint64_t size
, uint64_t align
,
196 return rpaligned_alloc(align
, size
);
198 // 64-bit operators sized delete and delete[], normal and aligned
199 extern void _ZdlPvm(void *p
, uint64_t size
);
200 void RPDEFVIS
_ZdlPvm(void *p
, uint64_t size
) {
204 extern void _ZdaPvm(void *p
, uint64_t size
);
205 void RPDEFVIS
_ZdaPvm(void *p
, uint64_t size
) {
209 extern void _ZdlPvSt11align_val_t(void *p
, uint64_t align
);
210 void RPDEFVIS
_ZdlPvSt11align_val_t(void *p
, uint64_t align
) {
214 extern void _ZdaPvSt11align_val_t(void *p
, uint64_t align
);
215 void RPDEFVIS
_ZdaPvSt11align_val_t(void *p
, uint64_t align
) {
219 extern void _ZdlPvmSt11align_val_t(void *p
, uint64_t size
, uint64_t align
);
220 void RPDEFVIS
_ZdlPvmSt11align_val_t(void *p
, uint64_t size
, uint64_t align
) {
225 extern void _ZdaPvmSt11align_val_t(void *p
, uint64_t size
, uint64_t align
);
226 void RPDEFVIS
_ZdaPvmSt11align_val_t(void *p
, uint64_t size
, uint64_t align
) {
232 // 32-bit operators new and new[], normal and aligned
233 extern void *_Znwj(uint32_t size
);
234 void *RPDEFVIS
_Znwj(uint32_t size
) { return rpmalloc(size
); }
235 extern void *_Znaj(uint32_t size
);
236 void *RPDEFVIS
_Znaj(uint32_t size
) { return rpmalloc(size
); }
237 extern void *_Znwjj(uint32_t size
, uint32_t align
);
238 void *RPDEFVIS
_Znwjj(uint32_t size
, uint32_t align
) {
239 return rpaligned_alloc(align
, size
);
241 extern void *_Znajj(uint32_t size
, uint32_t align
);
242 void *RPDEFVIS
_Znajj(uint32_t size
, uint32_t align
) {
243 return rpaligned_alloc(align
, size
);
245 extern void *_ZnwjSt11align_val_t(size_t size
, size_t align
);
246 void *RPDEFVIS
_ZnwjSt11align_val_t(size_t size
, size_t align
) {
247 return rpaligned_alloc(align
, size
);
249 extern void *_ZnajSt11align_val_t(size_t size
, size_t align
);
250 void *RPDEFVIS
_ZnajSt11align_val_t(size_t size
, size_t align
) {
251 return rpaligned_alloc(align
, size
);
253 extern void *_ZnwjRKSt9nothrow_t(size_t size
, rp_nothrow_t t
);
254 void *RPDEFVIS
_ZnwjRKSt9nothrow_t(size_t size
, rp_nothrow_t t
) {
256 return rpmalloc(size
);
258 extern void *_ZnajRKSt9nothrow_t(size_t size
, rp_nothrow_t t
);
259 void *RPDEFVIS
_ZnajRKSt9nothrow_t(size_t size
, rp_nothrow_t t
) {
261 return rpmalloc(size
);
263 extern void *_ZnwjSt11align_val_tRKSt9nothrow_t(size_t size
, size_t align
,
265 void *RPDEFVIS
_ZnwjSt11align_val_tRKSt9nothrow_t(size_t size
, size_t align
,
268 return rpaligned_alloc(align
, size
);
270 extern void *_ZnajSt11align_val_tRKSt9nothrow_t(size_t size
, size_t align
,
272 void *RPDEFVIS
_ZnajSt11align_val_tRKSt9nothrow_t(size_t size
, size_t align
,
275 return rpaligned_alloc(align
, size
);
277 // 32-bit operators sized delete and delete[], normal and aligned
278 extern void _ZdlPvj(void *p
, uint64_t size
);
279 void RPDEFVIS
_ZdlPvj(void *p
, uint64_t size
) {
283 extern void _ZdaPvj(void *p
, uint64_t size
);
284 void RPDEFVIS
_ZdaPvj(void *p
, uint64_t size
) {
288 extern void _ZdlPvSt11align_val_t(void *p
, uint32_t align
);
289 void RPDEFVIS
_ZdlPvSt11align_val_t(void *p
, uint64_t a
) {
293 extern void _ZdaPvSt11align_val_t(void *p
, uint32_t align
);
294 void RPDEFVIS
_ZdaPvSt11align_val_t(void *p
, uint64_t a
) {
298 extern void _ZdlPvjSt11align_val_t(void *p
, uint32_t size
, uint32_t align
);
299 void RPDEFVIS
_ZdlPvjSt11align_val_t(void *p
, uint64_t size
, uint64_t align
) {
304 extern void _ZdaPvjSt11align_val_t(void *p
, uint32_t size
, uint32_t align
);
305 void RPDEFVIS
_ZdaPvjSt11align_val_t(void *p
, uint64_t size
, uint64_t align
) {
314 #if USE_INTERPOSE || USE_ALIAS
316 static void *rpmalloc_nothrow(size_t size
, rp_nothrow_t t
) {
318 return rpmalloc(size
);
320 static void *rpaligned_alloc_reverse(size_t size
, size_t align
) {
321 return rpaligned_alloc(align
, size
);
323 static void *rpaligned_alloc_reverse_nothrow(size_t size
, size_t align
,
326 return rpaligned_alloc(align
, size
);
328 static void rpfree_size(void *p
, size_t size
) {
332 static void rpfree_aligned(void *p
, size_t align
) {
336 static void rpfree_size_aligned(void *p
, size_t size
, size_t align
) {
346 __attribute__((used
)) static const interpose_t macinterpose_malloc
[]
347 __attribute__((section("__DATA, __interpose"))) = {
349 MAC_INTERPOSE_PAIR(rpmalloc
, _Znwm
),
350 MAC_INTERPOSE_PAIR(rpmalloc
, _Znam
),
351 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse
, _Znwmm
),
352 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse
, _Znamm
),
353 MAC_INTERPOSE_PAIR(rpmalloc_nothrow
, _ZnwmRKSt9nothrow_t
),
354 MAC_INTERPOSE_PAIR(rpmalloc_nothrow
, _ZnamRKSt9nothrow_t
),
355 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse
, _ZnwmSt11align_val_t
),
356 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse
, _ZnamSt11align_val_t
),
357 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse_nothrow
,
358 _ZnwmSt11align_val_tRKSt9nothrow_t
),
359 MAC_INTERPOSE_PAIR(rpaligned_alloc_reverse_nothrow
,
360 _ZnamSt11align_val_tRKSt9nothrow_t
),
361 // delete and delete[]
362 MAC_INTERPOSE_PAIR(rpfree
, _ZdlPv
), MAC_INTERPOSE_PAIR(rpfree
, _ZdaPv
),
363 MAC_INTERPOSE_PAIR(rpfree_size
, _ZdlPvm
),
364 MAC_INTERPOSE_PAIR(rpfree_size
, _ZdaPvm
),
365 MAC_INTERPOSE_PAIR(rpfree_aligned
, _ZdlPvSt11align_val_t
),
366 MAC_INTERPOSE_PAIR(rpfree_aligned
, _ZdaPvSt11align_val_t
),
367 MAC_INTERPOSE_PAIR(rpfree_size_aligned
, _ZdlPvmSt11align_val_t
),
368 MAC_INTERPOSE_PAIR(rpfree_size_aligned
, _ZdaPvmSt11align_val_t
),
370 MAC_INTERPOSE_PAIR(rpmalloc
, malloc
),
371 MAC_INTERPOSE_PAIR(rpmalloc
, calloc
),
372 MAC_INTERPOSE_PAIR(rprealloc
, realloc
),
373 MAC_INTERPOSE_PAIR(rprealloc
, reallocf
),
374 #if defined(__MAC_10_15) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_15
375 MAC_INTERPOSE_PAIR(rpaligned_alloc
, aligned_alloc
),
377 MAC_INTERPOSE_PAIR(rpmemalign
, memalign
),
378 MAC_INTERPOSE_PAIR(rpposix_memalign
, posix_memalign
),
379 MAC_INTERPOSE_PAIR(rpfree
, free
), MAC_INTERPOSE_PAIR(rpfree
, cfree
),
380 MAC_INTERPOSE_PAIR(rpmalloc_usable_size
, malloc_usable_size
),
381 MAC_INTERPOSE_PAIR(rpmalloc_usable_size
, malloc_size
)};
387 #define RPALIAS(fn) __attribute__((alias(#fn), used, visibility("default")));
389 // Alias the C++ operators using the mangled names
390 // (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling)
392 // operators delete and delete[]
393 void _ZdlPv(void *p
) RPALIAS(rpfree
) void _ZdaPv(void *p
) RPALIAS(rpfree
)
396 // 64-bit operators new and new[], normal and aligned
397 void *_Znwm(uint64_t size
) RPMALLOC_ATTRIB_MALLOC
398 RPMALLOC_ATTRIB_ALLOC_SIZE(1)
399 RPALIAS(rpmalloc
) void *_Znam(uint64_t size
) RPMALLOC_ATTRIB_MALLOC
400 RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc
) void *_Znwmm(uint64_t size
,
402 RPALIAS(rpaligned_alloc_reverse
) void *_Znamm(uint64_t size
,
404 RPALIAS(rpaligned_alloc_reverse
) void *_ZnwmSt11align_val_t(
405 size_t size
, size_t align
)
406 RPALIAS(rpaligned_alloc_reverse
) void *_ZnamSt11align_val_t(
407 size_t size
, size_t align
)
408 RPALIAS(rpaligned_alloc_reverse
) void *_ZnwmRKSt9nothrow_t(
409 size_t size
, rp_nothrow_t t
)
410 RPALIAS(rpmalloc_nothrow
) void *_ZnamRKSt9nothrow_t(
412 rp_nothrow_t t
) RPALIAS(rpmalloc_nothrow
) void
413 *_ZnwmSt11align_val_tRKSt9nothrow_t(size_t size
,
416 RPALIAS(rpaligned_alloc_reverse_nothrow
) void
417 *_ZnamSt11align_val_tRKSt9nothrow_t(
418 size_t size
, size_t align
,
420 RPALIAS(rpaligned_alloc_reverse_nothrow
)
421 // 64-bit operators delete and delete[], sized and aligned
422 void _ZdlPvm(void *p
, size_t n
) RPALIAS(rpfree_size
) void _ZdaPvm(void *p
,
424 RPALIAS(rpfree_size
) void _ZdlPvSt11align_val_t(void *p
, size_t a
)
425 RPALIAS(rpfree_aligned
) void _ZdaPvSt11align_val_t(void *p
,
427 RPALIAS(rpfree_aligned
) void _ZdlPvmSt11align_val_t(void *p
,
430 RPALIAS(rpfree_size_aligned
) void _ZdaPvmSt11align_val_t(
431 void *p
, size_t n
, size_t a
)
432 RPALIAS(rpfree_size_aligned
)
434 // 32-bit operators new and new[], normal and aligned
435 void *_Znwj(uint32_t size
) RPMALLOC_ATTRIB_MALLOC
436 RPMALLOC_ATTRIB_ALLOC_SIZE(1)
437 RPALIAS(rpmalloc
) void *_Znaj(uint32_t size
) RPMALLOC_ATTRIB_MALLOC
438 RPMALLOC_ATTRIB_ALLOC_SIZE(1) RPALIAS(rpmalloc
) void *_Znwjj(uint32_t size
,
440 RPALIAS(rpaligned_alloc_reverse
) void *_Znajj(uint32_t size
,
442 RPALIAS(rpaligned_alloc_reverse
) void *_ZnwjSt11align_val_t(
443 size_t size
, size_t align
)
444 RPALIAS(rpaligned_alloc_reverse
) void *_ZnajSt11align_val_t(
445 size_t size
, size_t align
)
446 RPALIAS(rpaligned_alloc_reverse
) void *_ZnwjRKSt9nothrow_t(
447 size_t size
, rp_nothrow_t t
)
448 RPALIAS(rpmalloc_nothrow
) void *_ZnajRKSt9nothrow_t(
450 rp_nothrow_t t
) RPALIAS(rpmalloc_nothrow
) void
451 *_ZnwjSt11align_val_tRKSt9nothrow_t(size_t size
,
454 RPALIAS(rpaligned_alloc_reverse_nothrow
) void
455 *_ZnajSt11align_val_tRKSt9nothrow_t(
456 size_t size
, size_t align
,
458 RPALIAS(rpaligned_alloc_reverse_nothrow
)
459 // 32-bit operators delete and delete[], sized and aligned
460 void _ZdlPvj(void *p
, size_t n
) RPALIAS(rpfree_size
) void _ZdaPvj(void *p
,
462 RPALIAS(rpfree_size
) void _ZdlPvSt11align_val_t(void *p
, size_t a
)
463 RPALIAS(rpfree_aligned
) void _ZdaPvSt11align_val_t(void *p
,
465 RPALIAS(rpfree_aligned
) void _ZdlPvjSt11align_val_t(void *p
,
468 RPALIAS(rpfree_size_aligned
) void _ZdaPvjSt11align_val_t(
469 void *p
, size_t n
, size_t a
)
470 RPALIAS(rpfree_size_aligned
)
473 void *malloc(size_t size
) RPMALLOC_ATTRIB_MALLOC
474 RPMALLOC_ATTRIB_ALLOC_SIZE(1)
475 RPALIAS(rpmalloc
) void *calloc(size_t count
, size_t size
)
476 RPALIAS(rpcalloc
) void *realloc(void *ptr
, size_t size
)
477 RPALIAS(rprealloc
) void *reallocf(void *ptr
, size_t size
)
478 RPMALLOC_ATTRIB_MALLOC
479 RPMALLOC_ATTRIB_ALLOC_SIZE(2)
480 RPALIAS(rprealloc
) void *aligned_alloc(size_t alignment
, size_t size
)
481 RPALIAS(rpaligned_alloc
) void *memalign(
482 size_t alignment
, size_t size
) RPMALLOC_ATTRIB_MALLOC
483 RPMALLOC_ATTRIB_ALLOC_SIZE(2)
484 RPALIAS(rpmemalign
) int posix_memalign(void **memptr
, size_t alignment
,
486 RPALIAS(rpposix_memalign
) void free(void *ptr
)
487 RPALIAS(rpfree
) void cfree(void *ptr
) RPALIAS(rpfree
)
488 #if defined(__ANDROID__) || defined(__FreeBSD__)
490 malloc_usable_size(const void *ptr
) RPALIAS(rpmalloc_usable_size
)
493 malloc_usable_size(void *ptr
) RPALIAS(rpmalloc_usable_size
)
495 size_t malloc_size(void *ptr
) RPALIAS(rpmalloc_usable_size
)
499 static inline size_t _rpmalloc_page_size(void) {
500 return _memory_page_size
;
503 extern void *RPMALLOC_CDECL
reallocarray(void *ptr
, size_t count
, size_t size
);
505 extern void *RPMALLOC_CDECL
reallocarray(void *ptr
, size_t count
, size_t size
) {
507 #if ENABLE_VALIDATE_ARGS
509 int err
= SizeTMult(count
, size
, &total
);
510 if ((err
!= S_OK
) || (total
>= MAX_ALLOC_SIZE
)) {
515 int err
= __builtin_umull_overflow(count
, size
, &total
);
516 if (err
|| (total
>= MAX_ALLOC_SIZE
)) {
522 total
= count
* size
;
524 return realloc(ptr
, total
);
527 extern inline void *RPMALLOC_CDECL
valloc(size_t size
) {
529 return rpaligned_alloc(_rpmalloc_page_size(), size
);
532 extern inline void *RPMALLOC_CDECL
pvalloc(size_t size
) {
534 const size_t page_size
= _rpmalloc_page_size();
535 const size_t aligned_size
= ((size
+ page_size
- 1) / page_size
) * page_size
;
536 #if ENABLE_VALIDATE_ARGS
537 if (aligned_size
< size
) {
542 return rpaligned_alloc(_rpmalloc_page_size(), aligned_size
);
545 #endif // ENABLE_OVERRIDE
551 #if defined(BUILD_DYNAMIC_LINK) && BUILD_DYNAMIC_LINK
553 extern __declspec(dllexport
) BOOL WINAPI
DllMain(HINSTANCE instance
,
554 DWORD reason
, LPVOID reserved
);
556 extern __declspec(dllexport
) BOOL WINAPI
DllMain(HINSTANCE instance
,
559 (void)sizeof(reserved
);
560 (void)sizeof(instance
);
561 if (reason
== DLL_PROCESS_ATTACH
)
562 rpmalloc_initialize();
563 else if (reason
== DLL_PROCESS_DETACH
)
565 else if (reason
== DLL_THREAD_ATTACH
)
566 rpmalloc_thread_initialize();
567 else if (reason
== DLL_THREAD_DETACH
)
568 rpmalloc_thread_finalize(1);
572 // end BUILD_DYNAMIC_LINK
575 extern void _global_rpmalloc_init(void) {
576 rpmalloc_set_main_thread();
577 rpmalloc_initialize();
580 #if defined(__clang__) || defined(__GNUC__)
582 static void __attribute__((constructor
)) initializer(void) {
583 _global_rpmalloc_init();
586 #elif defined(_MSC_VER)
588 static int _global_rpmalloc_xib(void) {
589 _global_rpmalloc_init();
593 #pragma section(".CRT$XIB", read)
594 __declspec(allocate(".CRT$XIB")) void (*_rpmalloc_module_init
)(void) =
595 _global_rpmalloc_xib
;
596 #if defined(_M_IX86) || defined(__i386__)
597 #pragma comment(linker, "/include:" \
598 "__rpmalloc_module_init")
600 #pragma comment(linker, "/include:" \
601 "_rpmalloc_module_init")
606 // end !BUILD_DYNAMIC_LINK
616 extern void rpmalloc_set_main_thread(void);
618 static pthread_key_t destructor_key
;
620 static void thread_destructor(void *);
622 static void __attribute__((constructor
)) initializer(void) {
623 rpmalloc_set_main_thread();
624 rpmalloc_initialize();
625 pthread_key_create(&destructor_key
, thread_destructor
);
628 static void __attribute__((destructor
)) finalizer(void) { rpmalloc_finalize(); }
631 void *(*real_start
)(void *);
633 } thread_starter_arg
;
635 static void *thread_starter(void *argptr
) {
636 thread_starter_arg
*arg
= argptr
;
637 void *(*real_start
)(void *) = arg
->real_start
;
638 void *real_arg
= arg
->real_arg
;
639 rpmalloc_thread_initialize();
641 pthread_setspecific(destructor_key
, (void *)1);
642 return (*real_start
)(real_arg
);
645 static void thread_destructor(void *value
) {
647 rpmalloc_thread_finalize(1);
652 static int pthread_create_proxy(pthread_t
*thread
, const pthread_attr_t
*attr
,
653 void *(*start_routine
)(void *), void *arg
) {
654 rpmalloc_initialize();
655 thread_starter_arg
*starter_arg
= rpmalloc(sizeof(thread_starter_arg
));
656 starter_arg
->real_start
= start_routine
;
657 starter_arg
->real_arg
= arg
;
658 return pthread_create(thread
, attr
, thread_starter
, starter_arg
);
661 MAC_INTERPOSE_SINGLE(pthread_create_proxy
, pthread_create
);
667 int pthread_create(pthread_t
*thread
, const pthread_attr_t
*attr
,
668 void *(*start_routine
)(void *), void *arg
) {
669 #if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
670 defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__) || \
672 char fname
[] = "pthread_create";
674 char fname
[] = "_pthread_create";
676 void *real_pthread_create
= dlsym(RTLD_NEXT
, fname
);
677 rpmalloc_thread_initialize();
678 thread_starter_arg
*starter_arg
= rpmalloc(sizeof(thread_starter_arg
));
679 starter_arg
->real_start
= start_routine
;
680 starter_arg
->real_arg
= arg
;
681 return (*(int (*)(pthread_t
*, const pthread_attr_t
*, void *(*)(void *),
682 void *))real_pthread_create
)(thread
, attr
, thread_starter
,
694 #if defined(__GLIBC__) && defined(__linux__)
696 void *__libc_malloc(size_t size
) RPMALLOC_ATTRIB_MALLOC
697 RPMALLOC_ATTRIB_ALLOC_SIZE(1)
698 RPALIAS(rpmalloc
) void *__libc_calloc(size_t count
, size_t size
)
699 RPMALLOC_ATTRIB_MALLOC
RPMALLOC_ATTRIB_ALLOC_SIZE2(1, 2)
700 RPALIAS(rpcalloc
) void *__libc_realloc(void *p
, size_t size
)
701 RPMALLOC_ATTRIB_MALLOC
702 RPMALLOC_ATTRIB_ALLOC_SIZE(2) RPALIAS(rprealloc
) void __libc_free(void *p
)
703 RPALIAS(rpfree
) void __libc_cfree(void *p
)
704 RPALIAS(rpfree
) void *__libc_memalign(size_t align
, size_t size
)
705 RPMALLOC_ATTRIB_MALLOC
706 RPMALLOC_ATTRIB_ALLOC_SIZE(2)
707 RPALIAS(rpmemalign
) int __posix_memalign(void **p
, size_t align
,
709 RPALIAS(rpposix_memalign
)
711 extern void *__libc_valloc(size_t size
);
712 extern void *__libc_pvalloc(size_t size
);
714 void *__libc_valloc(size_t size
) { return valloc(size
); }
716 void *__libc_pvalloc(size_t size
) { return pvalloc(size
); }
722 #if (defined(__GNUC__) || defined(__clang__))
723 #pragma GCC visibility pop