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