Blame jemalloc/include/jemalloc/internal/mutex_pool.h

Packit Service 724aca
#ifndef JEMALLOC_INTERNAL_MUTEX_POOL_H
Packit Service 724aca
#define JEMALLOC_INTERNAL_MUTEX_POOL_H
Packit Service 724aca
Packit Service 724aca
#include "jemalloc/internal/hash.h"
Packit Service 724aca
#include "jemalloc/internal/mutex.h"
Packit Service 724aca
#include "jemalloc/internal/witness.h"
Packit Service 724aca
Packit Service 724aca
/* We do mod reductions by this value, so it should be kept a power of 2. */
Packit Service 724aca
#define MUTEX_POOL_SIZE 256
Packit Service 724aca
Packit Service 724aca
typedef struct mutex_pool_s mutex_pool_t;
Packit Service 724aca
struct mutex_pool_s {
Packit Service 724aca
	malloc_mutex_t mutexes[MUTEX_POOL_SIZE];
Packit Service 724aca
};
Packit Service 724aca
Packit Service 724aca
bool mutex_pool_init(mutex_pool_t *pool, const char *name, witness_rank_t rank);
Packit Service 724aca
Packit Service 724aca
/* Internal helper - not meant to be called outside this module. */
Packit Service 724aca
static inline malloc_mutex_t *
Packit Service 724aca
mutex_pool_mutex(mutex_pool_t *pool, uintptr_t key) {
Packit Service 724aca
	size_t hash_result[2];
Packit Service 724aca
	hash(&key, sizeof(key), 0xd50dcc1b, hash_result);
Packit Service 724aca
	return &pool->mutexes[hash_result[0] % MUTEX_POOL_SIZE];
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
static inline void
Packit Service 724aca
mutex_pool_assert_not_held(tsdn_t *tsdn, mutex_pool_t *pool) {
Packit Service 724aca
	for (int i = 0; i < MUTEX_POOL_SIZE; i++) {
Packit Service 724aca
		malloc_mutex_assert_not_owner(tsdn, &pool->mutexes[i]);
Packit Service 724aca
	}
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
/*
Packit Service 724aca
 * Note that a mutex pool doesn't work exactly the way an embdedded mutex would.
Packit Service 724aca
 * You're not allowed to acquire mutexes in the pool one at a time.  You have to
Packit Service 724aca
 * acquire all the mutexes you'll need in a single function call, and then
Packit Service 724aca
 * release them all in a single function call.
Packit Service 724aca
 */
Packit Service 724aca
Packit Service 724aca
static inline void
Packit Service 724aca
mutex_pool_lock(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key) {
Packit Service 724aca
	mutex_pool_assert_not_held(tsdn, pool);
Packit Service 724aca
Packit Service 724aca
	malloc_mutex_t *mutex = mutex_pool_mutex(pool, key);
Packit Service 724aca
	malloc_mutex_lock(tsdn, mutex);
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
static inline void
Packit Service 724aca
mutex_pool_unlock(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key) {
Packit Service 724aca
	malloc_mutex_t *mutex = mutex_pool_mutex(pool, key);
Packit Service 724aca
	malloc_mutex_unlock(tsdn, mutex);
Packit Service 724aca
Packit Service 724aca
	mutex_pool_assert_not_held(tsdn, pool);
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
static inline void
Packit Service 724aca
mutex_pool_lock2(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key1,
Packit Service 724aca
    uintptr_t key2) {
Packit Service 724aca
	mutex_pool_assert_not_held(tsdn, pool);
Packit Service 724aca
Packit Service 724aca
	malloc_mutex_t *mutex1 = mutex_pool_mutex(pool, key1);
Packit Service 724aca
	malloc_mutex_t *mutex2 = mutex_pool_mutex(pool, key2);
Packit Service 724aca
	if ((uintptr_t)mutex1 < (uintptr_t)mutex2) {
Packit Service 724aca
		malloc_mutex_lock(tsdn, mutex1);
Packit Service 724aca
		malloc_mutex_lock(tsdn, mutex2);
Packit Service 724aca
	} else if ((uintptr_t)mutex1 == (uintptr_t)mutex2) {
Packit Service 724aca
		malloc_mutex_lock(tsdn, mutex1);
Packit Service 724aca
	} else {
Packit Service 724aca
		malloc_mutex_lock(tsdn, mutex2);
Packit Service 724aca
		malloc_mutex_lock(tsdn, mutex1);
Packit Service 724aca
	}
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
static inline void
Packit Service 724aca
mutex_pool_unlock2(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key1,
Packit Service 724aca
    uintptr_t key2) {
Packit Service 724aca
	malloc_mutex_t *mutex1 = mutex_pool_mutex(pool, key1);
Packit Service 724aca
	malloc_mutex_t *mutex2 = mutex_pool_mutex(pool, key2);
Packit Service 724aca
	if (mutex1 == mutex2) {
Packit Service 724aca
		malloc_mutex_unlock(tsdn, mutex1);
Packit Service 724aca
	} else {
Packit Service 724aca
		malloc_mutex_unlock(tsdn, mutex1);
Packit Service 724aca
		malloc_mutex_unlock(tsdn, mutex2);
Packit Service 724aca
	}
Packit Service 724aca
Packit Service 724aca
	mutex_pool_assert_not_held(tsdn, pool);
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
static inline void
Packit Service 724aca
mutex_pool_assert_owner(tsdn_t *tsdn, mutex_pool_t *pool, uintptr_t key) {
Packit Service 724aca
	malloc_mutex_assert_owner(tsdn, mutex_pool_mutex(pool, key));
Packit Service 724aca
}
Packit Service 724aca
Packit Service 724aca
#endif /* JEMALLOC_INTERNAL_MUTEX_POOL_H */