Bundle 3 branches on fast path into tsd_state.

Added tsd_state_nominal_slow, which on fast path malloc() incorporates
tcache_enabled check, and on fast path free() bundles both malloc_slow and
tcache_enabled branches.
This commit is contained in:
Qi Wang
2017-04-11 23:13:45 -07:00
committed by Qi Wang
parent ccfe68a916
commit b348ba29bb
10 changed files with 170 additions and 78 deletions

View File

@@ -3,6 +3,10 @@
#include "jemalloc/internal/atomic.h"
/* TSD checks this to set thread local slow state accordingly. */
extern bool malloc_slow;
/* Run-time options. */
extern bool opt_abort;
extern const char *opt_junk;
extern bool opt_junk_alloc;

View File

@@ -289,6 +289,7 @@ malloc_mutex_postfork_parent
malloc_mutex_prefork
malloc_mutex_unlock
malloc_printf
malloc_slow
malloc_snprintf
malloc_strtoumax
malloc_tsd_boot0
@@ -526,6 +527,7 @@ tsd_cleanup
tsd_cleanup_wrapper
tsd_fetch
tsd_fetch_impl
tsd_fetch_slow
tsd_get
tsd_get_allocates
tsd_iarena_get
@@ -541,6 +543,7 @@ tsd_narenas_tdatap_get
tsd_reentrancy_level_get
tsd_reentrancy_level_set
tsd_reentrancy_levelp_get
tsd_slow_update
tsd_wrapper_get
tsd_wrapper_set
tsd_nominal

View File

@@ -40,6 +40,7 @@ tcache_enabled_set(tsd_t *tsd, bool enabled) {
}
/* Commit the state last. Above calls check current state. */
tsd_tcache_enabled_set(tsd, enabled);
tsd_slow_update(tsd);
}
JEMALLOC_ALWAYS_INLINE void

View File

@@ -14,5 +14,7 @@ void tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block);
#endif
bool tsd_data_init(void *arg);
void tsd_cleanup(void *arg);
tsd_t *tsd_fetch_slow(tsd_t *tsd);
void tsd_slow_update(tsd_t *tsd);
#endif /* JEMALLOC_INTERNAL_TSD_EXTERNS_H */

View File

@@ -19,12 +19,54 @@ bool tsdn_null(const tsdn_t *tsdn);
tsd_t *tsdn_tsd(tsdn_t *tsdn);
rtree_ctx_t *tsd_rtree_ctx(tsd_t *tsd);
rtree_ctx_t *tsdn_rtree_ctx(tsdn_t *tsdn, rtree_ctx_t *fallback);
bool tsd_fast(tsd_t *tsd);
void tsd_assert_fast(tsd_t *tsd);
#endif
#if (defined(JEMALLOC_ENABLE_INLINE) || defined(JEMALLOC_TSD_C_))
malloc_tsd_externs(, tsd_t)
malloc_tsd_funcs(JEMALLOC_ALWAYS_INLINE, , tsd_t, tsd_initializer, tsd_cleanup)
#define MALLOC_TSD_getset_yes(n, t) \
JEMALLOC_ALWAYS_INLINE t \
tsd_##n##_get(tsd_t *tsd) { \
return *tsd_##n##p_get(tsd); \
} \
JEMALLOC_ALWAYS_INLINE void \
tsd_##n##_set(tsd_t *tsd, t n) { \
assert(tsd->state == tsd_state_nominal || \
tsd->state == tsd_state_nominal_slow || \
tsd->state == tsd_state_reincarnated); \
tsd->n = n; \
}
#define MALLOC_TSD_getset_no(n, t)
#define O(n, t, gs, i, c) \
JEMALLOC_ALWAYS_INLINE t * \
tsd_##n##p_get(tsd_t *tsd) { \
return &tsd->n; \
} \
\
MALLOC_TSD_getset_##gs(n, t)
MALLOC_TSD
#undef MALLOC_TSD_getset_yes
#undef MALLOC_TSD_getset_no
#undef O
JEMALLOC_ALWAYS_INLINE void
tsd_assert_fast(tsd_t *tsd) {
assert(!malloc_slow && tsd_tcache_enabled_get(tsd));
}
JEMALLOC_ALWAYS_INLINE bool
tsd_fast(tsd_t *tsd) {
bool fast = (tsd->state == tsd_state_nominal);
if (fast) {
tsd_assert_fast(tsd);
}
return fast;
}
JEMALLOC_ALWAYS_INLINE tsd_t *
tsd_fetch_impl(bool init) {
tsd_t *tsd = tsd_get(init);
@@ -35,19 +77,10 @@ tsd_fetch_impl(bool init) {
assert(tsd != NULL);
if (unlikely(tsd->state != tsd_state_nominal)) {
if (tsd->state == tsd_state_uninitialized) {
tsd->state = tsd_state_nominal;
/* Trigger cleanup handler registration. */
tsd_set(tsd);
tsd_data_init(tsd);
} else if (tsd->state == tsd_state_purgatory) {
tsd->state = tsd_state_reincarnated;
tsd_set(tsd);
tsd_data_init(tsd);
} else {
assert(tsd->state == tsd_state_reincarnated);
}
return tsd_fetch_slow(tsd);
}
assert(tsd_fast(tsd));
tsd_assert_fast(tsd);
return tsd;
}
@@ -64,33 +97,9 @@ tsd_tsdn(tsd_t *tsd) {
JEMALLOC_INLINE bool
tsd_nominal(tsd_t *tsd) {
return (tsd->state == tsd_state_nominal);
return (tsd->state <= tsd_state_nominal_max);
}
#define MALLOC_TSD_getset_yes(n, t) \
JEMALLOC_ALWAYS_INLINE t \
tsd_##n##_get(tsd_t *tsd) { \
return *tsd_##n##p_get(tsd); \
} \
JEMALLOC_ALWAYS_INLINE void \
tsd_##n##_set(tsd_t *tsd, t n) { \
assert(tsd->state == tsd_state_nominal || \
tsd->state == tsd_state_reincarnated); \
tsd->n = n; \
}
#define MALLOC_TSD_getset_no(n, t)
#define O(n, t, gs, i, c) \
JEMALLOC_ALWAYS_INLINE t * \
tsd_##n##p_get(tsd_t *tsd) { \
return &tsd->n; \
} \
\
MALLOC_TSD_getset_##gs(n, t)
MALLOC_TSD
#undef MALLOC_TSD_getset_yes
#undef MALLOC_TSD_getset_no
#undef O
JEMALLOC_ALWAYS_INLINE tsdn_t *
tsdn_fetch(void) {
if (!tsd_booted_get()) {

View File

@@ -64,7 +64,7 @@ struct tsd_init_head_s {
O(iarena, arena_t *, yes, no, yes) \
O(arena, arena_t *, yes, no, yes) \
O(arenas_tdata, arena_tdata_t *,yes, no, yes) \
O(tcache, tcache_t, yes, no, yes) \
O(tcache, tcache_t, no, no, yes) \
O(witnesses, witness_list_t, no, no, yes) \
O(rtree_leaf_elm_witnesses, rtree_leaf_elm_witness_tsd_t, \
no, no, no) \

View File

@@ -20,11 +20,15 @@ typedef struct tsdn_s tsdn_t;
#define TSDN_NULL ((tsdn_t *)0)
enum {
tsd_state_uninitialized = 0,
tsd_state_nominal = 1,
tsd_state_nominal = 0, /* Common case --> jnz. */
tsd_state_nominal_slow = 1, /* Initialized but on slow path. */
/* the above 2 nominal states should be lower values. */
tsd_state_nominal_max = 1, /* used for comparison only. */
tsd_state_purgatory = 2,
tsd_state_reincarnated = 3
tsd_state_reincarnated = 3,
tsd_state_uninitialized = 4
};
/* Manually limit tsd_state_t to a single byte. */
typedef uint8_t tsd_state_t;