mutex.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #define JEMALLOC_MUTEX_C_
  2. #include "jemalloc/internal/jemalloc_internal.h"
  3. #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
  4. #include <dlfcn.h>
  5. #endif
  6. #ifndef _CRT_SPINCOUNT
  7. #define _CRT_SPINCOUNT 4000
  8. #endif
  9. /******************************************************************************/
  10. /* Data. */
  11. #ifdef JEMALLOC_LAZY_LOCK
  12. bool isthreaded = false;
  13. #endif
  14. #ifdef JEMALLOC_MUTEX_INIT_CB
  15. static bool postpone_init = true;
  16. static malloc_mutex_t *postponed_mutexes = NULL;
  17. #endif
  18. #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
  19. static void pthread_create_once(void);
  20. #endif
  21. /******************************************************************************/
  22. /*
  23. * We intercept pthread_create() calls in order to toggle isthreaded if the
  24. * process goes multi-threaded.
  25. */
  26. #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
  27. static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *,
  28. void *(*)(void *), void *__restrict);
  29. static void
  30. pthread_create_once(void)
  31. {
  32. pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create");
  33. if (pthread_create_fptr == NULL) {
  34. malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, "
  35. "\"pthread_create\")\n");
  36. abort();
  37. }
  38. isthreaded = true;
  39. }
  40. JEMALLOC_EXPORT int
  41. pthread_create(pthread_t *__restrict thread,
  42. const pthread_attr_t *__restrict attr, void *(*start_routine)(void *),
  43. void *__restrict arg)
  44. {
  45. static pthread_once_t once_control = PTHREAD_ONCE_INIT;
  46. pthread_once(&once_control, pthread_create_once);
  47. return (pthread_create_fptr(thread, attr, start_routine, arg));
  48. }
  49. #endif
  50. /******************************************************************************/
  51. #ifdef JEMALLOC_MUTEX_INIT_CB
  52. JEMALLOC_EXPORT int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,
  53. void *(calloc_cb)(size_t, size_t));
  54. #endif
  55. bool
  56. malloc_mutex_init(malloc_mutex_t *mutex)
  57. {
  58. #ifdef _WIN32
  59. if (!InitializeCriticalSectionAndSpinCount(&mutex->lock,
  60. _CRT_SPINCOUNT))
  61. return (true);
  62. #elif (defined(JEMALLOC_OSSPIN))
  63. mutex->lock = 0;
  64. #elif (defined(JEMALLOC_MUTEX_INIT_CB))
  65. if (postpone_init) {
  66. mutex->postponed_next = postponed_mutexes;
  67. postponed_mutexes = mutex;
  68. } else {
  69. if (_pthread_mutex_init_calloc_cb(&mutex->lock, base_calloc) !=
  70. 0)
  71. return (true);
  72. }
  73. #else
  74. pthread_mutexattr_t attr;
  75. if (pthread_mutexattr_init(&attr) != 0)
  76. return (true);
  77. pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE);
  78. if (pthread_mutex_init(&mutex->lock, &attr) != 0) {
  79. pthread_mutexattr_destroy(&attr);
  80. return (true);
  81. }
  82. pthread_mutexattr_destroy(&attr);
  83. #endif
  84. return (false);
  85. }
  86. void
  87. malloc_mutex_prefork(malloc_mutex_t *mutex)
  88. {
  89. malloc_mutex_lock(mutex);
  90. }
  91. void
  92. malloc_mutex_postfork_parent(malloc_mutex_t *mutex)
  93. {
  94. malloc_mutex_unlock(mutex);
  95. }
  96. void
  97. malloc_mutex_postfork_child(malloc_mutex_t *mutex)
  98. {
  99. #ifdef JEMALLOC_MUTEX_INIT_CB
  100. malloc_mutex_unlock(mutex);
  101. #else
  102. if (malloc_mutex_init(mutex)) {
  103. malloc_printf("<jemalloc>: Error re-initializing mutex in "
  104. "child\n");
  105. if (opt_abort)
  106. abort();
  107. }
  108. #endif
  109. }
  110. bool
  111. mutex_boot(void)
  112. {
  113. #ifdef JEMALLOC_MUTEX_INIT_CB
  114. postpone_init = false;
  115. while (postponed_mutexes != NULL) {
  116. if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock,
  117. base_calloc) != 0)
  118. return (true);
  119. postponed_mutexes = postponed_mutexes->postponed_next;
  120. }
  121. #endif
  122. return (false);
  123. }