1*8e33eff8Schristos #ifndef JEMALLOC_INTERNAL_MUTEX_POOL_H 2*8e33eff8Schristos #define JEMALLOC_INTERNAL_MUTEX_POOL_H 3*8e33eff8Schristos 4*8e33eff8Schristos #include "jemalloc/internal/hash.h" 5*8e33eff8Schristos #include "jemalloc/internal/mutex.h" 6*8e33eff8Schristos #include "jemalloc/internal/witness.h" 7*8e33eff8Schristos 8*8e33eff8Schristos /* We do mod reductions by this value, so it should be kept a power of 2. */ 9*8e33eff8Schristos #define MUTEX_POOL_SIZE 256 10*8e33eff8Schristos 11*8e33eff8Schristos typedef struct mutex_pool_s mutex_pool_t; 12*8e33eff8Schristos struct mutex_pool_s { 13*8e33eff8Schristos malloc_mutex_t mutexes[MUTEX_POOL_SIZE]; 14*8e33eff8Schristos }; 15*8e33eff8Schristos 16*8e33eff8Schristos bool mutex_pool_init(mutex_pool_t *pool, const char *name, witness_rank_t rank); 17*8e33eff8Schristos 18*8e33eff8Schristos /* Internal helper - not meant to be called outside this module. */ 19*8e33eff8Schristos static inline malloc_mutex_t * 20*8e33eff8Schristos mutex_pool_mutex(mutex_pool_t *pool, uintptr_t key) { 21*8e33eff8Schristos size_t hash_result[2]; 22*8e33eff8Schristos hash(&key, sizeof(key), 0xd50dcc1b, hash_result); 23*8e33eff8Schristos return &pool->mutexes[hash_result[0] % MUTEX_POOL_SIZE]; 24*8e33eff8Schristos } 25*8e33eff8Schristos 26*8e33eff8Schristos static inline void 27*8e33eff8Schristos mutex_pool_assert_not_held(tsdn_t *tsdn, mutex_pool_t *pool) { 28*8e33eff8Schristos for (int i = 0; i < MUTEX_POOL_SIZE; i++) { 29*8e33eff8Schristos malloc_mutex_assert_not_owner(tsdn, &pool->mutexes[i]); 30*8e33eff8Schristos } 31*8e33eff8Schristos } 32*8e33eff8Schristos 33*8e33eff8Schristos /* 34*8e33eff8Schristos * Note that a mutex pool doesn't work exactly the way an embdedded mutex would. 35*8e33eff8Schristos * You're not allowed to acquire mutexes in the pool one at a time. You have to 36*8e33eff8Schristos * acquire all the mutexes you'll need in a single function call, and then 37*8e33eff8Schristos * release them all in a single function call. 38*8e33eff8Schristos */ 39*8e33eff8Schristos 40*8e33eff8Schristos static inline void 41*8e33eff8Schristos mutex_pool_lock(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key) { 42*8e33eff8Schristos mutex_pool_assert_not_held(tsdn, pool); 43*8e33eff8Schristos 44*8e33eff8Schristos malloc_mutex_t *mutex = mutex_pool_mutex(pool, key); 45*8e33eff8Schristos malloc_mutex_lock(tsdn, mutex); 46*8e33eff8Schristos } 47*8e33eff8Schristos 48*8e33eff8Schristos static inline void 49*8e33eff8Schristos mutex_pool_unlock(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key) { 50*8e33eff8Schristos malloc_mutex_t *mutex = mutex_pool_mutex(pool, key); 51*8e33eff8Schristos malloc_mutex_unlock(tsdn, mutex); 52*8e33eff8Schristos 53*8e33eff8Schristos mutex_pool_assert_not_held(tsdn, pool); 54*8e33eff8Schristos } 55*8e33eff8Schristos 56*8e33eff8Schristos static inline void 57*8e33eff8Schristos mutex_pool_lock2(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key1, 58*8e33eff8Schristos uintptr_t key2) { 59*8e33eff8Schristos mutex_pool_assert_not_held(tsdn, pool); 60*8e33eff8Schristos 61*8e33eff8Schristos malloc_mutex_t *mutex1 = mutex_pool_mutex(pool, key1); 62*8e33eff8Schristos malloc_mutex_t *mutex2 = mutex_pool_mutex(pool, key2); 63*8e33eff8Schristos if ((uintptr_t)mutex1 < (uintptr_t)mutex2) { 64*8e33eff8Schristos malloc_mutex_lock(tsdn, mutex1); 65*8e33eff8Schristos malloc_mutex_lock(tsdn, mutex2); 66*8e33eff8Schristos } else if ((uintptr_t)mutex1 == (uintptr_t)mutex2) { 67*8e33eff8Schristos malloc_mutex_lock(tsdn, mutex1); 68*8e33eff8Schristos } else { 69*8e33eff8Schristos malloc_mutex_lock(tsdn, mutex2); 70*8e33eff8Schristos malloc_mutex_lock(tsdn, mutex1); 71*8e33eff8Schristos } 72*8e33eff8Schristos } 73*8e33eff8Schristos 74*8e33eff8Schristos static inline void 75*8e33eff8Schristos mutex_pool_unlock2(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key1, 76*8e33eff8Schristos uintptr_t key2) { 77*8e33eff8Schristos malloc_mutex_t *mutex1 = mutex_pool_mutex(pool, key1); 78*8e33eff8Schristos malloc_mutex_t *mutex2 = mutex_pool_mutex(pool, key2); 79*8e33eff8Schristos if (mutex1 == mutex2) { 80*8e33eff8Schristos malloc_mutex_unlock(tsdn, mutex1); 81*8e33eff8Schristos } else { 82*8e33eff8Schristos malloc_mutex_unlock(tsdn, mutex1); 83*8e33eff8Schristos malloc_mutex_unlock(tsdn, mutex2); 84*8e33eff8Schristos } 85*8e33eff8Schristos 86*8e33eff8Schristos mutex_pool_assert_not_held(tsdn, pool); 87*8e33eff8Schristos } 88*8e33eff8Schristos 89*8e33eff8Schristos static inline void 90*8e33eff8Schristos mutex_pool_assert_owner(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key) { 91*8e33eff8Schristos malloc_mutex_assert_owner(tsdn, mutex_pool_mutex(pool, key)); 92*8e33eff8Schristos } 93*8e33eff8Schristos 94*8e33eff8Schristos #endif /* JEMALLOC_INTERNAL_MUTEX_POOL_H */ 95