Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
jasone committed Jul 2, 2017
2 parents 5018fe3 + 284edf0 commit 896ed3a
Show file tree
Hide file tree
Showing 23 changed files with 395 additions and 134 deletions.
35 changes: 35 additions & 0 deletions ChangeLog
Expand Up @@ -4,6 +4,41 @@ brevity. Much more detail can be found in the git revision history:

https://github.com/jemalloc/jemalloc

* 5.0.1 (July 1, 2017)

This bugfix release fixes several issues, most of which are obscure enough
that typical applications are not impacted.

Bug fixes:
- Update decay->nunpurged before purging, in order to avoid potential update
races and subsequent incorrect purging volume. (@interwq)
- Only abort on dlsym(3) error if the failure impacts an enabled feature (lazy
locking and/or background threads). This mitigates an initialization
failure bug for which we still do not have a clear reproduction test case.
(@interwq)
- Modify tsd management so that it neither crashes nor leaks if a thread's
only allocation activity is to call free() after TLS destructors have been
executed. This behavior was observed when operating with GNU libc, and is
unlikely to be an issue with other libc implementations. (@interwq)
- Mask signals during background thread creation. This prevents signals from
being inadvertently delivered to background threads. (@jasone,
@davidgoldblatt, @interwq)
- Avoid inactivity checks within background threads, in order to prevent
recursive mutex acquisition. (@interwq)
- Fix extent_grow_retained() to use the specified hooks when the
arena.<i>.extent_hooks mallctl is used to override the default hooks.
(@interwq)
- Add missing reentrancy support for custom extent hooks which allocate.
(@interwq)
- Post-fork(2), re-initialize the list of tcaches associated with each arena
to contain no tcaches except the forking thread's. (@interwq)
- Add missing post-fork(2) mutex reinitialization for extent_grow_mtx. This
fixes potential deadlocks after fork(2). (@interwq)
- Enforce minimum autoconf version (currently 2.68), since 2.63 is known to
generate corrupt configure scripts. (@jasone)
- Ensure that the configured page size (--with-lg-page) is no larger than the
configured huge page size (--with-lg-hugepage). (@jasone)

* 5.0.0 (June 13, 2017)

Unlike all previous jemalloc releases, this release does not use naturally
Expand Down
14 changes: 14 additions & 0 deletions configure.ac
@@ -1,4 +1,5 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.68)
AC_INIT([Makefile.in])

AC_CONFIG_AUX_DIR([build-aux])
Expand Down Expand Up @@ -1373,6 +1374,10 @@ if test "x${je_cv_lg_hugepage}" = "x" ; then
je_cv_lg_hugepage=21
fi
fi
if test "x${LG_PAGE}" != "xundefined" -a \
"${je_cv_lg_hugepage}" -lt "${LG_PAGE}" ; then
AC_MSG_ERROR([Huge page size (2^${je_cv_lg_hugepage}) must be at least page size (2^${LG_PAGE})])
fi
AC_DEFINE_UNQUOTED([LG_HUGEPAGE], [${je_cv_lg_hugepage}])

AC_ARG_WITH([lg_page_sizes],
Expand Down Expand Up @@ -1470,6 +1475,15 @@ if test "x$abi" != "xpecoff" ; then
if test "x${je_cv_pthread_atfork}" = "xyes" ; then
AC_DEFINE([JEMALLOC_HAVE_PTHREAD_ATFORK], [ ])
fi
dnl Check if pthread_setname_np is available with the expected API.
JE_COMPILABLE([pthread_setname_np(3)], [
#include <pthread.h>
], [
pthread_setname_np(pthread_self(), "setname_test");
], [je_cv_pthread_setname_np])
if test "x${je_cv_pthread_setname_np}" = "xyes" ; then
AC_DEFINE([JEMALLOC_HAVE_PTHREAD_SETNAME_NP], [ ])
fi
fi

JE_APPEND_VS(CPPFLAGS, -D_REENTRANT)
Expand Down
1 change: 1 addition & 0 deletions include/jemalloc/internal/arena_externs.h
Expand Up @@ -90,6 +90,7 @@ void arena_prefork3(tsdn_t *tsdn, arena_t *arena);
void arena_prefork4(tsdn_t *tsdn, arena_t *arena);
void arena_prefork5(tsdn_t *tsdn, arena_t *arena);
void arena_prefork6(tsdn_t *tsdn, arena_t *arena);
void arena_prefork7(tsdn_t *tsdn, arena_t *arena);
void arena_postfork_parent(tsdn_t *tsdn, arena_t *arena);
void arena_postfork_child(tsdn_t *tsdn, arena_t *arena);

Expand Down
1 change: 1 addition & 0 deletions include/jemalloc/internal/background_thread_externs.h
Expand Up @@ -6,6 +6,7 @@ extern malloc_mutex_t background_thread_lock;
extern atomic_b_t background_thread_enabled_state;
extern size_t n_background_threads;
extern background_thread_info_t *background_thread_info;
extern bool can_enable_background_thread;

bool background_thread_create(tsd_t *tsd, unsigned arena_ind);
bool background_threads_enable(tsd_t *tsd);
Expand Down
5 changes: 3 additions & 2 deletions include/jemalloc/internal/background_thread_inlines.h
Expand Up @@ -41,8 +41,9 @@ background_thread_indefinite_sleep(background_thread_info_t *info) {
}

JEMALLOC_ALWAYS_INLINE void
arena_background_thread_inactivity_check(tsdn_t *tsdn, arena_t *arena) {
if (!background_thread_enabled()) {
arena_background_thread_inactivity_check(tsdn_t *tsdn, arena_t *arena,
bool is_background_thread) {
if (!background_thread_enabled() || is_background_thread) {
return;
}
background_thread_info_t *info =
Expand Down
2 changes: 1 addition & 1 deletion include/jemalloc/internal/base_externs.h
Expand Up @@ -3,7 +3,7 @@

base_t *b0get(void);
base_t *base_new(tsdn_t *tsdn, unsigned ind, extent_hooks_t *extent_hooks);
void base_delete(base_t *base);
void base_delete(tsdn_t *tsdn, base_t *base);
extent_hooks_t *base_extent_hooks_get(base_t *base);
extent_hooks_t *base_extent_hooks_set(base_t *base,
extent_hooks_t *extent_hooks);
Expand Down
3 changes: 1 addition & 2 deletions include/jemalloc/internal/ctl.h
Expand Up @@ -91,8 +91,7 @@ typedef struct ctl_arenas_s {

int ctl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp,
void *newp, size_t newlen);
int ctl_nametomib(tsdn_t *tsdn, const char *name, size_t *mibp,
size_t *miblenp);
int ctl_nametomib(tsd_t *tsd, const char *name, size_t *mibp, size_t *miblenp);

int ctl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
size_t *oldlenp, void *newp, size_t newlen);
Expand Down
1 change: 1 addition & 0 deletions include/jemalloc/internal/jemalloc_internal_decls.h
Expand Up @@ -22,6 +22,7 @@
# include <sys/uio.h>
# endif
# include <pthread.h>
# include <signal.h>
# ifdef JEMALLOC_OS_UNFAIR_LOCK
# include <os/lock.h>
# endif
Expand Down
3 changes: 3 additions & 0 deletions include/jemalloc/internal/jemalloc_internal_defs.h.in
Expand Up @@ -98,6 +98,9 @@
/* Defined if pthread_atfork(3) is available. */
#undef JEMALLOC_HAVE_PTHREAD_ATFORK

/* Defined if pthread_setname_np(3) is available. */
#undef JEMALLOC_HAVE_PTHREAD_SETNAME_NP

/*
* Defined if clock_gettime(CLOCK_MONOTONIC_COARSE, ...) is available.
*/
Expand Down
5 changes: 4 additions & 1 deletion include/jemalloc/internal/jemalloc_internal_inlines_a.h
Expand Up @@ -146,7 +146,10 @@ tcache_get(tsd_t *tsd) {
}

static inline void
pre_reentrancy(tsd_t *tsd) {
pre_reentrancy(tsd_t *tsd, arena_t *arena) {
/* arena is the current context. Reentry from a0 is not allowed. */
assert(arena != arena_get(tsd_tsdn(tsd), 0, false));

bool fast = tsd_fast(tsd);
++*tsd_reentrancy_levelp_get(tsd);
if (fast) {
Expand Down
2 changes: 1 addition & 1 deletion include/jemalloc/internal/tcache_externs.h
Expand Up @@ -48,7 +48,7 @@ void tcache_arena_associate(tsdn_t *tsdn, tcache_t *tcache, arena_t *arena);
void tcache_prefork(tsdn_t *tsdn);
void tcache_postfork_parent(tsdn_t *tsdn);
void tcache_postfork_child(tsdn_t *tsdn);
void tcache_flush(void);
void tcache_flush(tsd_t *tsd);
bool tsd_tcache_data_init(tsd_t *tsd);
bool tsd_tcache_enabled_data_init(tsd_t *tsd);

Expand Down
30 changes: 22 additions & 8 deletions include/jemalloc/internal/tsd.h
Expand Up @@ -99,9 +99,10 @@ enum {
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_uninitialized = 4
tsd_state_minimal_initialized = 2,
tsd_state_purgatory = 3,
tsd_state_reincarnated = 4,
tsd_state_uninitialized = 5
};

/* Manually limit tsd_state_t to a single byte. */
Expand Down Expand Up @@ -190,7 +191,8 @@ JEMALLOC_ALWAYS_INLINE t * \
tsd_##n##p_get(tsd_t *tsd) { \
assert(tsd->state == tsd_state_nominal || \
tsd->state == tsd_state_nominal_slow || \
tsd->state == tsd_state_reincarnated); \
tsd->state == tsd_state_reincarnated || \
tsd->state == tsd_state_minimal_initialized); \
return tsd_##n##p_get_unsafe(tsd); \
}
MALLOC_TSD
Expand Down Expand Up @@ -225,7 +227,8 @@ MALLOC_TSD
#define O(n, t, nt) \
JEMALLOC_ALWAYS_INLINE void \
tsd_##n##_set(tsd_t *tsd, t val) { \
assert(tsd->state != tsd_state_reincarnated); \
assert(tsd->state != tsd_state_reincarnated && \
tsd->state != tsd_state_minimal_initialized); \
*tsd_##n##p_get(tsd) = val; \
}
MALLOC_TSD
Expand All @@ -248,7 +251,7 @@ tsd_fast(tsd_t *tsd) {
}

JEMALLOC_ALWAYS_INLINE tsd_t *
tsd_fetch_impl(bool init, bool internal) {
tsd_fetch_impl(bool init, bool minimal) {
tsd_t *tsd = tsd_get(init);

if (!init && tsd_get_allocates() && tsd == NULL) {
Expand All @@ -257,19 +260,30 @@ tsd_fetch_impl(bool init, bool internal) {
assert(tsd != NULL);

if (unlikely(tsd->state != tsd_state_nominal)) {
return tsd_fetch_slow(tsd, internal);
return tsd_fetch_slow(tsd, minimal);
}
assert(tsd_fast(tsd));
tsd_assert_fast(tsd);

return tsd;
}

/* Get a minimal TSD that requires no cleanup. See comments in free(). */
JEMALLOC_ALWAYS_INLINE tsd_t *
tsd_internal_fetch(void) {
tsd_fetch_min(void) {
return tsd_fetch_impl(true, true);
}

/* For internal background threads use only. */
JEMALLOC_ALWAYS_INLINE tsd_t *
tsd_internal_fetch(void) {
tsd_t *tsd = tsd_fetch_min();
/* Use reincarnated state to prevent full initialization. */
tsd->state = tsd_state_reincarnated;

return tsd;
}

JEMALLOC_ALWAYS_INLINE tsd_t *
tsd_fetch(void) {
return tsd_fetch_impl(true, false);
Expand Down

0 comments on commit 896ed3a

Please sign in to comment.