24#if defined(__LLP64__) || defined(__LP64__) || defined(_WIN64)
35#if (defined(__GNUC__) || defined(__clang__))
36#pragma GCC visibility push(default)
39#define USE_IMPLEMENT 1
40#define USE_INTERPOSE 0
45#define USE_INTERPOSE 1
47typedef 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
79typedef struct rp_nothrow_t {
96extern inline void *
RPMALLOC_CDECL reallocf(
void *ptr,
size_t size) {
103extern inline void *
RPMALLOC_CDECL memalign(
size_t alignment,
size_t size) {
106extern inline int RPMALLOC_CDECL posix_memalign(
void **memptr,
size_t alignment,
112extern inline size_t RPMALLOC_CDECL malloc_usable_size(
void *ptr) {
135_realloc_base(
void *ptr,
size_t size) {
147#define RPDEFVIS __attribute__((visibility("default")))
148extern void _ZdlPv(
void *p);
149void RPDEFVIS _ZdlPv(
void *p) {
rpfree(p); }
150extern void _ZdaPv(
void *p);
151void RPDEFVIS _ZdaPv(
void *p) {
rpfree(p); }
174extern void *_ZnwmRKSt9nothrow_t(
uint64_t size, rp_nothrow_t t);
175void *RPDEFVIS _ZnwmRKSt9nothrow_t(
uint64_t size, rp_nothrow_t t) {
179extern void *_ZnamRKSt9nothrow_t(
uint64_t size, rp_nothrow_t t);
180void *RPDEFVIS _ZnamRKSt9nothrow_t(
uint64_t size, rp_nothrow_t t) {
184extern void *_ZnwmSt11align_val_tRKSt9nothrow_t(
uint64_t size,
uint64_t align,
186void *RPDEFVIS _ZnwmSt11align_val_tRKSt9nothrow_t(
uint64_t size,
uint64_t align,
191extern void *_ZnamSt11align_val_tRKSt9nothrow_t(
uint64_t size,
uint64_t align,
193void *RPDEFVIS _ZnamSt11align_val_tRKSt9nothrow_t(
uint64_t size,
uint64_t align,
199extern void _ZdlPvm(
void *p,
uint64_t size);
200void RPDEFVIS _ZdlPvm(
void *p,
uint64_t size) {
204extern void _ZdaPvm(
void *p,
uint64_t size);
205void RPDEFVIS _ZdaPvm(
void *p,
uint64_t size) {
209extern void _ZdlPvSt11align_val_t(
void *p,
uint64_t align);
210void RPDEFVIS _ZdlPvSt11align_val_t(
void *p,
uint64_t align) {
214extern void _ZdaPvSt11align_val_t(
void *p,
uint64_t align);
215void RPDEFVIS _ZdaPvSt11align_val_t(
void *p,
uint64_t align) {
220void RPDEFVIS _ZdlPvmSt11align_val_t(
void *p,
uint64_t size,
uint64_t align) {
226void RPDEFVIS _ZdaPvmSt11align_val_t(
void *p,
uint64_t size,
uint64_t align) {
245extern void *_ZnwjSt11align_val_t(
size_t size,
size_t align);
246void *RPDEFVIS _ZnwjSt11align_val_t(
size_t size,
size_t align) {
249extern void *_ZnajSt11align_val_t(
size_t size,
size_t align);
250void *RPDEFVIS _ZnajSt11align_val_t(
size_t size,
size_t align) {
253extern void *_ZnwjRKSt9nothrow_t(
size_t size, rp_nothrow_t t);
254void *RPDEFVIS _ZnwjRKSt9nothrow_t(
size_t size, rp_nothrow_t t) {
258extern void *_ZnajRKSt9nothrow_t(
size_t size, rp_nothrow_t t);
259void *RPDEFVIS _ZnajRKSt9nothrow_t(
size_t size, rp_nothrow_t t) {
263extern void *_ZnwjSt11align_val_tRKSt9nothrow_t(
size_t size,
size_t align,
265void *RPDEFVIS _ZnwjSt11align_val_tRKSt9nothrow_t(
size_t size,
size_t align,
270extern void *_ZnajSt11align_val_tRKSt9nothrow_t(
size_t size,
size_t align,
272void *RPDEFVIS _ZnajSt11align_val_tRKSt9nothrow_t(
size_t size,
size_t align,
278extern void _ZdlPvj(
void *p,
uint64_t size);
279void RPDEFVIS _ZdlPvj(
void *p,
uint64_t size) {
283extern void _ZdaPvj(
void *p,
uint64_t size);
284void RPDEFVIS _ZdaPvj(
void *p,
uint64_t size) {
288extern void _ZdlPvSt11align_val_t(
void *p,
uint32_t align);
289void RPDEFVIS _ZdlPvSt11align_val_t(
void *p,
uint64_t a) {
293extern void _ZdaPvSt11align_val_t(
void *p,
uint32_t align);
294void RPDEFVIS _ZdaPvSt11align_val_t(
void *p,
uint64_t a) {
299void RPDEFVIS _ZdlPvjSt11align_val_t(
void *p,
uint64_t size,
uint64_t align) {
305void RPDEFVIS _ZdaPvjSt11align_val_t(
void *p,
uint64_t size,
uint64_t align) {
314#if USE_INTERPOSE || USE_ALIAS
316static void *rpmalloc_nothrow(
size_t size, rp_nothrow_t t) {
320static void *rpaligned_alloc_reverse(
size_t size,
size_t align) {
323static void *rpaligned_alloc_reverse_nothrow(
size_t size,
size_t align,
328static void rpfree_size(
void *p,
size_t size) {
332static void rpfree_aligned(
void *p,
size_t align) {
336static 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),
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),
374#if defined(__MAC_10_15) && __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_15
379 MAC_INTERPOSE_PAIR(
rpfree, free), MAC_INTERPOSE_PAIR(
rpfree, cfree),
387#define RPALIAS(fn) __attribute__((alias(#fn), used, visibility("default")));
393void _ZdlPv(
void *p) RPALIAS(
rpfree)
void _ZdaPv(
void *p) RPALIAS(
rpfree)
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)
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)
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)
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)
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)
480 RPALIAS(
rprealloc)
void *aligned_alloc(
size_t alignment,
size_t size)
484 RPALIAS(
rpmemalign)
int posix_memalign(
void **memptr,
size_t alignment,
488#if defined(__ANDROID__) || defined(__FreeBSD__)
499 static inline size_t _rpmalloc_page_size(
void) {
503extern void *
RPMALLOC_CDECL reallocarray(
void *ptr,
size_t count,
size_t size);
505extern 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)) {
524 return realloc(ptr, total);
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) {
551#if defined(BUILD_DYNAMIC_LINK) && BUILD_DYNAMIC_LINK
553extern __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE instance,
554 DWORD reason, LPVOID reserved);
556extern __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE instance,
559 (void)
sizeof(reserved);
560 (void)
sizeof(instance);
561 if (reason == DLL_PROCESS_ATTACH)
563 else if (reason == DLL_PROCESS_DETACH)
565 else if (reason == DLL_THREAD_ATTACH)
567 else if (reason == DLL_THREAD_DETACH)
575extern void _global_rpmalloc_init(
void) {
580#if defined(__clang__) || defined(__GNUC__)
582static void __attribute__((constructor)) initializer(
void) {
583 _global_rpmalloc_init();
586#elif defined(_MSC_VER)
588static 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")
618static pthread_key_t destructor_key;
620static void thread_destructor(
void *);
622static void __attribute__((constructor)) initializer(
void) {
625 pthread_key_create(&destructor_key, thread_destructor);
631 void *(*real_start)(
void *);
635static 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;
641 pthread_setspecific(destructor_key, (
void *)1);
642 return (*real_start)(real_arg);
645static void thread_destructor(
void *
value) {
652static int pthread_create_proxy(pthread_t *thread,
const pthread_attr_t *attr,
653 void *(*start_routine)(
void *),
void *arg) {
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);
661MAC_INTERPOSE_SINGLE(pthread_create_proxy, pthread_create);
667int 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);
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__)
698 RPALIAS(
rpmalloc)
void *__libc_calloc(
size_t count,
size_t size)
700 RPALIAS(
rpcalloc)
void *__libc_realloc(
void *p,
size_t size)
703 RPALIAS(
rpfree)
void __libc_cfree(
void *p)
704 RPALIAS(
rpfree)
void *__libc_memalign(
size_t align,
size_t size)
707 RPALIAS(
rpmemalign)
int __posix_memalign(
void **p,
size_t align,
711 extern
void *__libc_valloc(
size_t size);
712extern
void *__libc_pvalloc(
size_t size);
714void *__libc_valloc(
size_t size) {
return valloc(size); }
716void *__libc_pvalloc(
size_t size) {
return pvalloc(size); }
722#if (defined(__GNUC__) || defined(__clang__))
723#pragma GCC visibility pop
Given that RA is a live value
_Static_assert(sizeof(size_t)==4, "Data type size mismatch")
#define RPMALLOC_RESTRICT
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
void rpfree(void *ptr)
Free the given memory block.
RPMALLOC_ALLOCATOR void * rpmalloc(size_t size)
Allocate a memory block of at least the given size.
static size_t _memory_page_size
Memory page size.
void rpmalloc_set_main_thread(void)
Set main thread ID.
RPMALLOC_ALLOCATOR void * rpcalloc(size_t num, size_t size)
RPMALLOC_ALLOCATOR void * rpmemalign(size_t alignment, size_t size)
Allocate a memory block of at least the given size and alignment.
void rpmalloc_thread_finalize(int release_caches)
Finalize thread, orphan heap.
RPMALLOC_ALLOCATOR void * rpaligned_alloc(size_t alignment, size_t size)
Allocate a memory block of at least the given size and alignment.
size_t rpmalloc_usable_size(void *ptr)
Query the usable size of the given memory block (from given pointer to the end of block)
void rpmalloc_thread_initialize(void)
Initialize thread, assign heap.
RPMALLOC_ALLOCATOR void * rprealloc(void *ptr, size_t size)
Reallocate the given block to at least the given size.
int rpmalloc_initialize(void)
Initialize the allocator and setup global data.
int rpposix_memalign(void **memptr, size_t alignment, size_t size)
Allocate a memory block of at least the given size and alignment.
static heap_t * get_thread_heap(void)
Get the current thread heap.
void rpmalloc_finalize(void)
Finalize the allocator.
#define RPMALLOC_ATTRIB_ALLOC_SIZE2(count, size)
#define RPMALLOC_ATTRIB_ALLOC_SIZE(size)
#define RPMALLOC_ATTRIB_MALLOC