3f685e8824
Instead of embedding a lock bit in rtree leaf elements, we associate extents with a small set of mutexes. This gets us two things: - We can use the system mutexes. This (hypothetically) protects us from priority inversion, and lets us stop doing a backoff/sleep loop, instead opting for precise wakeups from the mutex. - Cuts down on the number of mutex acquisitions we have to do (from 4 in the worst case to two). We end up simplifying most of the rtree code (which no longer has to deal with locking or concurrency at all), at the cost of additional complexity in the extent code: since the mutex protecting the rtree leaf elements is determined by reading the extent out of those elements, the initial read is racy, so that we may acquire an out of date mutex. We re-check the extent in the leaf after acquiring the mutex to protect us from this race.
57 lines
1.5 KiB
C
57 lines
1.5 KiB
C
#ifndef JEMALLOC_INTERNAL_MUTEX_STRUCTS_H
|
|
#define JEMALLOC_INTERNAL_MUTEX_STRUCTS_H
|
|
|
|
#include "jemalloc/internal/atomic.h"
|
|
#include "jemalloc/internal/mutex_prof.h"
|
|
#include "jemalloc/internal/witness_types.h"
|
|
#include "jemalloc/internal/witness_structs.h"
|
|
|
|
struct malloc_mutex_s {
|
|
union {
|
|
struct {
|
|
/*
|
|
* prof_data is defined first to reduce cacheline
|
|
* bouncing: the data is not touched by the mutex holder
|
|
* during unlocking, while might be modified by
|
|
* contenders. Having it before the mutex itself could
|
|
* avoid prefetching a modified cacheline (for the
|
|
* unlocking thread).
|
|
*/
|
|
mutex_prof_data_t prof_data;
|
|
#ifdef _WIN32
|
|
# if _WIN32_WINNT >= 0x0600
|
|
SRWLOCK lock;
|
|
# else
|
|
CRITICAL_SECTION lock;
|
|
# endif
|
|
#elif (defined(JEMALLOC_OS_UNFAIR_LOCK))
|
|
os_unfair_lock lock;
|
|
#elif (defined(JEMALLOC_OSSPIN))
|
|
OSSpinLock lock;
|
|
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
|
|
pthread_mutex_t lock;
|
|
malloc_mutex_t *postponed_next;
|
|
#else
|
|
pthread_mutex_t lock;
|
|
#endif
|
|
};
|
|
/*
|
|
* We only touch witness when configured w/ debug. However we
|
|
* keep the field in a union when !debug so that we don't have
|
|
* to pollute the code base with #ifdefs, while avoid paying the
|
|
* memory cost.
|
|
*/
|
|
#if !defined(JEMALLOC_DEBUG)
|
|
witness_t witness;
|
|
malloc_mutex_lock_order_t lock_order;
|
|
#endif
|
|
};
|
|
|
|
#if defined(JEMALLOC_DEBUG)
|
|
witness_t witness;
|
|
malloc_mutex_lock_order_t lock_order;
|
|
#endif
|
|
};
|
|
|
|
#endif /* JEMALLOC_INTERNAL_MUTEX_STRUCTS_H */
|