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