Make TSD state non-atomic

This commit is contained in:
Slobodan Predolac
2026-05-12 16:16:37 -07:00
parent cec4e84c02
commit 639e70fcfb
2 changed files with 8 additions and 29 deletions

View File

@@ -126,7 +126,7 @@ typedef void (*test_callback_t)(int *);
#define TSD_INITIALIZER \ #define TSD_INITIALIZER \
{ \ { \
TSD_DATA_SLOW_INITIALIZER \ TSD_DATA_SLOW_INITIALIZER \
/* state */ ATOMIC_INIT(tsd_state_uninitialized), \ /* state */ tsd_state_uninitialized, \
TSD_DATA_FAST_INITIALIZER TSD_DATA_SLOWER_INITIALIZER \ TSD_DATA_FAST_INITIALIZER TSD_DATA_SLOWER_INITIALIZER \
} }
@@ -182,16 +182,6 @@ enum {
*/ */
#define TSD_MANGLE(n) cant_access_tsd_items_directly_use_a_getter_or_setter_##n #define TSD_MANGLE(n) cant_access_tsd_items_directly_use_a_getter_or_setter_##n
#ifdef JEMALLOC_U8_ATOMICS
# define tsd_state_t atomic_u8_t
# define tsd_atomic_load atomic_load_u8
# define tsd_atomic_store atomic_store_u8
#else
# define tsd_state_t atomic_u32_t
# define tsd_atomic_load atomic_load_u32
# define tsd_atomic_store atomic_store_u32
#endif
/* The actual tsd. */ /* The actual tsd. */
struct tsd_s { struct tsd_s {
/* /*
@@ -203,11 +193,8 @@ struct tsd_s {
#define O(n, t, nt) t TSD_MANGLE(n); #define O(n, t, nt) t TSD_MANGLE(n);
TSD_DATA_SLOW TSD_DATA_SLOW
/* /* Encodes one of tsd_state_*; mutated only by the owning thread. */
* We manually limit the state to just a single byte. Unless the 8-bit uint8_t state;
* atomics are unavailable (which is rare).
*/
tsd_state_t state;
TSD_DATA_FAST TSD_DATA_FAST
TSD_DATA_SLOWER TSD_DATA_SLOWER
#undef O #undef O
@@ -215,13 +202,7 @@ struct tsd_s {
JEMALLOC_ALWAYS_INLINE uint8_t JEMALLOC_ALWAYS_INLINE uint8_t
tsd_state_get(tsd_t *tsd) { tsd_state_get(tsd_t *tsd) {
/* return tsd->state;
* This should be atomic. Unfortunately, compilers right now can't tell
* that this can be done as a memory comparison, and forces a load into
* a register that hurts fast-path performance.
*/
/* return atomic_load_u8(&tsd->state, ATOMIC_RELAXED); */
return *(uint8_t *)&tsd->state;
} }
/* /*

View File

@@ -81,7 +81,7 @@ void
tsd_slow_update(tsd_t *tsd) { tsd_slow_update(tsd_t *tsd) {
assert(!tsd_booted_get() || tsd_get(false) == tsd assert(!tsd_booted_get() || tsd_get(false) == tsd
|| (tsd_get_allocates() && tsd_get(false) == NULL)); || (tsd_get_allocates() && tsd_get(false) == NULL));
tsd_atomic_store(&tsd->state, tsd_state_compute(tsd), ATOMIC_RELAXED); tsd->state = tsd_state_compute(tsd);
te_recompute_fast_threshold(tsd); te_recompute_fast_threshold(tsd);
} }
@@ -90,8 +90,7 @@ void
tsd_state_set(tsd_t *tsd, uint8_t new_state) { tsd_state_set(tsd_t *tsd, uint8_t new_state) {
assert(!tsd_booted_get() || tsd_get(false) == tsd assert(!tsd_booted_get() || tsd_get(false) == tsd
|| (tsd_get_allocates() && tsd_get(false) == NULL)); || (tsd_get_allocates() && tsd_get(false) == NULL));
uint8_t old_state = tsd_atomic_load(&tsd->state, ATOMIC_RELAXED); if (tsd->state <= tsd_state_nominal_max
if (old_state <= tsd_state_nominal_max
&& new_state <= tsd_state_nominal_max) { && new_state <= tsd_state_nominal_max) {
/* /*
* We're transitioning from one nominal state to another. * We're transitioning from one nominal state to another.
@@ -99,11 +98,10 @@ tsd_state_set(tsd_t *tsd, uint8_t new_state) {
* than trusting the caller's requested nominal state. * than trusting the caller's requested nominal state.
*/ */
tsd_slow_update(tsd); tsd_slow_update(tsd);
return;
} else { } else {
tsd_atomic_store(&tsd->state, new_state, ATOMIC_RELAXED); tsd->state = new_state;
}
te_recompute_fast_threshold(tsd); te_recompute_fast_threshold(tsd);
}
} }
static void static void