[arch-commits] Commit in jemalloc/repos (10 files)
Christian Hesse
eworm at archlinux.org
Sun Jul 2 18:37:52 UTC 2017
Date: Sunday, July 2, 2017 @ 18:37:52
Author: eworm
Revision: 299554
archrelease: copy trunk to testing-i686, testing-x86_64
Added:
jemalloc/repos/testing-i686/
jemalloc/repos/testing-i686/0001-only-abort-on-dlsym-when-necessary.patch
(from rev 299553, jemalloc/trunk/0001-only-abort-on-dlsym-when-necessary.patch)
jemalloc/repos/testing-i686/0002-clear-tcache_ql-after-fork-in-child.patch
(from rev 299553, jemalloc/trunk/0002-clear-tcache_ql-after-fork-in-child.patch)
jemalloc/repos/testing-i686/0003-Add-minimal-initialized-tsd.patch
(from rev 299553, jemalloc/trunk/0003-Add-minimal-initialized-tsd.patch)
jemalloc/repos/testing-i686/PKGBUILD
(from rev 299553, jemalloc/trunk/PKGBUILD)
jemalloc/repos/testing-x86_64/
jemalloc/repos/testing-x86_64/0001-only-abort-on-dlsym-when-necessary.patch
(from rev 299553, jemalloc/trunk/0001-only-abort-on-dlsym-when-necessary.patch)
jemalloc/repos/testing-x86_64/0002-clear-tcache_ql-after-fork-in-child.patch
(from rev 299553, jemalloc/trunk/0002-clear-tcache_ql-after-fork-in-child.patch)
jemalloc/repos/testing-x86_64/0003-Add-minimal-initialized-tsd.patch
(from rev 299553, jemalloc/trunk/0003-Add-minimal-initialized-tsd.patch)
jemalloc/repos/testing-x86_64/PKGBUILD
(from rev 299553, jemalloc/trunk/PKGBUILD)
---------------------------------------------------------------+
testing-i686/0001-only-abort-on-dlsym-when-necessary.patch | 75 +++
testing-i686/0002-clear-tcache_ql-after-fork-in-child.patch | 194 ++++++++++
testing-i686/0003-Add-minimal-initialized-tsd.patch | 37 +
testing-i686/PKGBUILD | 31 +
testing-x86_64/0001-only-abort-on-dlsym-when-necessary.patch | 75 +++
testing-x86_64/0002-clear-tcache_ql-after-fork-in-child.patch | 194 ++++++++++
testing-x86_64/0003-Add-minimal-initialized-tsd.patch | 37 +
testing-x86_64/PKGBUILD | 31 +
8 files changed, 674 insertions(+)
Copied: jemalloc/repos/testing-i686/0001-only-abort-on-dlsym-when-necessary.patch (from rev 299553, jemalloc/trunk/0001-only-abort-on-dlsym-when-necessary.patch)
===================================================================
--- testing-i686/0001-only-abort-on-dlsym-when-necessary.patch (rev 0)
+++ testing-i686/0001-only-abort-on-dlsym-when-necessary.patch 2017-07-02 18:37:52 UTC (rev 299554)
@@ -0,0 +1,75 @@
+From a4d6fe73cf07b3be3af6b7811cfc5950320bb37f Mon Sep 17 00:00:00 2001
+From: Qi Wang <interwq at gwu.edu>
+Date: Wed, 14 Jun 2017 12:12:23 -0700
+Subject: [PATCH] Only abort on dlsym when necessary.
+
+If neither background_thread nor lazy_lock is in use, do not abort on dlsym
+errors.
+---
+ include/jemalloc/internal/background_thread_externs.h | 1 +
+ src/background_thread.c | 14 +++++++++++---
+ src/ctl.c | 7 +++++++
+ 3 files changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/include/jemalloc/internal/background_thread_externs.h b/include/jemalloc/internal/background_thread_externs.h
+index 7c883697..8b4b8471 100644
+--- a/include/jemalloc/internal/background_thread_externs.h
++++ b/include/jemalloc/internal/background_thread_externs.h
+@@ -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);
+diff --git a/src/background_thread.c b/src/background_thread.c
+index a7403b85..1ff59447 100644
+--- a/src/background_thread.c
++++ b/src/background_thread.c
+@@ -20,6 +20,9 @@ size_t n_background_threads;
+ /* Thread info per-index. */
+ background_thread_info_t *background_thread_info;
+
++/* False if no necessary runtime support. */
++bool can_enable_background_thread;
++
+ /******************************************************************************/
+
+ #ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER
+@@ -785,9 +788,14 @@ background_thread_boot0(void) {
+ #ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER
+ pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create");
+ if (pthread_create_fptr == NULL) {
+- malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, "
+- "\"pthread_create\")\n");
+- abort();
++ can_enable_background_thread = false;
++ if (config_lazy_lock || opt_background_thread) {
++ malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, "
++ "\"pthread_create\")\n");
++ abort();
++ }
++ } else {
++ can_enable_background_thread = true;
+ }
+ #endif
+ return false;
+diff --git a/src/ctl.c b/src/ctl.c
+index b3ae4aab..f1310cdf 100644
+--- a/src/ctl.c
++++ b/src/ctl.c
+@@ -1522,6 +1522,13 @@ background_thread_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
+
+ background_thread_enabled_set(tsd_tsdn(tsd), newval);
+ if (newval) {
++ if (!can_enable_background_thread) {
++ malloc_printf("<jemalloc>: Error in dlsym("
++ "RTLD_NEXT, \"pthread_create\"). Cannot "
++ "enable background_thread\n");
++ ret = EFAULT;
++ goto label_return;
++ }
+ if (background_threads_enable(tsd)) {
+ ret = EFAULT;
+ goto label_return;
Copied: jemalloc/repos/testing-i686/0002-clear-tcache_ql-after-fork-in-child.patch (from rev 299553, jemalloc/trunk/0002-clear-tcache_ql-after-fork-in-child.patch)
===================================================================
--- testing-i686/0002-clear-tcache_ql-after-fork-in-child.patch (rev 0)
+++ testing-i686/0002-clear-tcache_ql-after-fork-in-child.patch 2017-07-02 18:37:52 UTC (rev 299554)
@@ -0,0 +1,194 @@
+From 9b1befabbb7a7105501d27843873d14e1c2de54b Mon Sep 17 00:00:00 2001
+From: Qi Wang <interwq at gwu.edu>
+Date: Thu, 15 Jun 2017 16:53:22 -0700
+Subject: [PATCH] Add minimal initialized TSD.
+
+We use the minimal_initilized tsd (which requires no cleanup) for free()
+specifically, if tsd hasn't been initialized yet.
+
+Any other activity will transit the state from minimal to normal. This is to
+workaround the case where a thread has no malloc calls in its lifetime until
+during thread termination, free() happens after tls destructors.
+---
+ include/jemalloc/internal/tsd.h | 30 ++++++++++++++++++++--------
+ src/jemalloc.c | 10 +++++++++-
+ src/tsd.c | 44 +++++++++++++++++++++++++++--------------
+ 3 files changed, 60 insertions(+), 24 deletions(-)
+
+diff --git a/include/jemalloc/internal/tsd.h b/include/jemalloc/internal/tsd.h
+index 631fbf1f..155a2ec6 100644
+--- a/include/jemalloc/internal/tsd.h
++++ b/include/jemalloc/internal/tsd.h
+@@ -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. */
+@@ -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
+@@ -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
+@@ -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) {
+@@ -257,7 +260,7 @@ 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);
+@@ -265,11 +268,22 @@ tsd_fetch_impl(bool init, bool internal) {
+ 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);
+diff --git a/src/jemalloc.c b/src/jemalloc.c
+index 52c86aa6..c773cc44 100644
+--- a/src/jemalloc.c
++++ b/src/jemalloc.c
+@@ -2264,7 +2264,15 @@ JEMALLOC_EXPORT void JEMALLOC_NOTHROW
+ je_free(void *ptr) {
+ UTRACE(ptr, 0, 0);
+ if (likely(ptr != NULL)) {
+- tsd_t *tsd = tsd_fetch();
++ /*
++ * We avoid setting up tsd fully (e.g. tcache, arena binding)
++ * based on only free() calls -- other activities trigger the
++ * minimal to full transition. This is because free() may
++ * happen during thread shutdown after tls deallocation: if a
++ * thread never had any malloc activities until then, a
++ * fully-setup tsd won't be destructed properly.
++ */
++ tsd_t *tsd = tsd_fetch_min();
+ check_entry_exit_locking(tsd_tsdn(tsd));
+
+ tcache_t *tcache;
+diff --git a/src/tsd.c b/src/tsd.c
+index 97330332..f968992f 100644
+--- a/src/tsd.c
++++ b/src/tsd.c
+@@ -87,7 +87,8 @@ assert_tsd_data_cleanup_done(tsd_t *tsd) {
+
+ static bool
+ tsd_data_init_nocleanup(tsd_t *tsd) {
+- assert(tsd->state == tsd_state_reincarnated);
++ assert(tsd->state == tsd_state_reincarnated ||
++ tsd->state == tsd_state_minimal_initialized);
+ /*
+ * During reincarnation, there is no guarantee that the cleanup function
+ * will be called (deallocation may happen after all tsd destructors).
+@@ -103,15 +104,8 @@ tsd_data_init_nocleanup(tsd_t *tsd) {
+ }
+
+ tsd_t *
+-tsd_fetch_slow(tsd_t *tsd, bool internal) {
+- if (internal) {
+- /* For internal background threads use only. */
+- assert(tsd->state == tsd_state_uninitialized);
+- tsd->state = tsd_state_reincarnated;
+- tsd_set(tsd);
+- tsd_data_init_nocleanup(tsd);
+- return tsd;
+- }
++tsd_fetch_slow(tsd_t *tsd, bool minimal) {
++ assert(!tsd_fast(tsd));
+
+ if (tsd->state == tsd_state_nominal_slow) {
+ /* On slow path but no work needed. */
+@@ -119,11 +113,28 @@ tsd_fetch_slow(tsd_t *tsd, bool internal) {
+ tsd_reentrancy_level_get(tsd) > 0 ||
+ *tsd_arenas_tdata_bypassp_get(tsd));
+ } else if (tsd->state == tsd_state_uninitialized) {
+- tsd->state = tsd_state_nominal;
+- tsd_slow_update(tsd);
+- /* Trigger cleanup handler registration. */
+- tsd_set(tsd);
+- tsd_data_init(tsd);
++ if (!minimal) {
++ tsd->state = tsd_state_nominal;
++ tsd_slow_update(tsd);
++ /* Trigger cleanup handler registration. */
++ tsd_set(tsd);
++ tsd_data_init(tsd);
++ } else {
++ tsd->state = tsd_state_minimal_initialized;
++ tsd_set(tsd);
++ tsd_data_init_nocleanup(tsd);
++ }
++ } else if (tsd->state == tsd_state_minimal_initialized) {
++ if (!minimal) {
++ /* Switch to fully initialized. */
++ tsd->state = tsd_state_nominal;
++ assert(*tsd_reentrancy_levelp_get(tsd) >= 1);
++ (*tsd_reentrancy_levelp_get(tsd))--;
++ tsd_slow_update(tsd);
++ tsd_data_init(tsd);
++ } else {
++ assert_tsd_data_cleanup_done(tsd);
++ }
+ } else if (tsd->state == tsd_state_purgatory) {
+ tsd->state = tsd_state_reincarnated;
+ tsd_set(tsd);
+@@ -197,6 +208,9 @@ tsd_cleanup(void *arg) {
+ case tsd_state_uninitialized:
+ /* Do nothing. */
+ break;
++ case tsd_state_minimal_initialized:
++ /* This implies the thread only did free() in its life time. */
++ /* Fall through. */
+ case tsd_state_reincarnated:
+ /*
+ * Reincarnated means another destructor deallocated memory
Copied: jemalloc/repos/testing-i686/0003-Add-minimal-initialized-tsd.patch (from rev 299553, jemalloc/trunk/0003-Add-minimal-initialized-tsd.patch)
===================================================================
--- testing-i686/0003-Add-minimal-initialized-tsd.patch (rev 0)
+++ testing-i686/0003-Add-minimal-initialized-tsd.patch 2017-07-02 18:37:52 UTC (rev 299554)
@@ -0,0 +1,37 @@
+From d35c037e03e1450794dcf595e49a1e1f97f87ac4 Mon Sep 17 00:00:00 2001
+From: Qi Wang <interwq at gwu.edu>
+Date: Mon, 19 Jun 2017 21:19:15 -0700
+Subject: [PATCH] Clear tcache_ql after fork in child.
+
+---
+ src/arena.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/src/arena.c b/src/arena.c
+index 019dd877..d401808b 100644
+--- a/src/arena.c
++++ b/src/arena.c
+@@ -2133,6 +2133,23 @@ void
+ arena_postfork_child(tsdn_t *tsdn, arena_t *arena) {
+ unsigned i;
+
++ atomic_store_u(&arena->nthreads[0], 0, ATOMIC_RELAXED);
++ atomic_store_u(&arena->nthreads[1], 0, ATOMIC_RELAXED);
++ if (tsd_arena_get(tsdn_tsd(tsdn)) == arena) {
++ arena_nthreads_inc(arena, false);
++ }
++ if (tsd_iarena_get(tsdn_tsd(tsdn)) == arena) {
++ arena_nthreads_inc(arena, true);
++ }
++ if (config_stats) {
++ ql_new(&arena->tcache_ql);
++ tcache_t *tcache = tcache_get(tsdn_tsd(tsdn));
++ if (tcache != NULL && tcache->arena == arena) {
++ ql_elm_new(tcache, link);
++ ql_tail_insert(&arena->tcache_ql, tcache, link);
++ }
++ }
++
+ for (i = 0; i < NBINS; i++) {
+ malloc_mutex_postfork_child(tsdn, &arena->bins[i].lock);
+ }
Copied: jemalloc/repos/testing-i686/PKGBUILD (from rev 299553, jemalloc/trunk/PKGBUILD)
===================================================================
--- testing-i686/PKGBUILD (rev 0)
+++ testing-i686/PKGBUILD 2017-07-02 18:37:52 UTC (rev 299554)
@@ -0,0 +1,31 @@
+# $Id$
+# Maintainer: Bartłomiej Piotrowski <bpiotrowski at archlinux.org>
+# Contributor: Massimiliano Torromeo <massimiliano.torromeo at gmail.com>
+# Contributor: Kovivchak Evgen <oneonfire at gmail.com>
+
+pkgname=jemalloc
+epoch=1
+pkgver=5.0.1
+pkgrel=1
+pkgdesc='General-purpose scalable concurrent malloc implementation'
+arch=('i686' 'x86_64')
+license=('BSD')
+url='http://www.canonware.com/jemalloc/'
+depends=('glibc')
+provides=('libjemalloc.so')
+optdepends=('perl: for jeprof')
+source=("https://github.com/jemalloc/jemalloc/releases/download/${pkgver}/${pkgname}-${pkgver}.tar.bz2")
+sha256sums=('4814781d395b0ef093b21a08e8e6e0bd3dab8762f9935bbfb71679b0dea7c3e9')
+
+build() {
+ cd $pkgname-$pkgver
+ ./configure --prefix=/usr
+ make
+}
+
+package() {
+ cd $pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ find "$pkgdir" -name \*.a -type f -exec chmod 644 '{}' \;
+ install -Dm644 COPYING "$pkgdir/usr/share/licenses/$pkgname/COPYING"
+}
Copied: jemalloc/repos/testing-x86_64/0001-only-abort-on-dlsym-when-necessary.patch (from rev 299553, jemalloc/trunk/0001-only-abort-on-dlsym-when-necessary.patch)
===================================================================
--- testing-x86_64/0001-only-abort-on-dlsym-when-necessary.patch (rev 0)
+++ testing-x86_64/0001-only-abort-on-dlsym-when-necessary.patch 2017-07-02 18:37:52 UTC (rev 299554)
@@ -0,0 +1,75 @@
+From a4d6fe73cf07b3be3af6b7811cfc5950320bb37f Mon Sep 17 00:00:00 2001
+From: Qi Wang <interwq at gwu.edu>
+Date: Wed, 14 Jun 2017 12:12:23 -0700
+Subject: [PATCH] Only abort on dlsym when necessary.
+
+If neither background_thread nor lazy_lock is in use, do not abort on dlsym
+errors.
+---
+ include/jemalloc/internal/background_thread_externs.h | 1 +
+ src/background_thread.c | 14 +++++++++++---
+ src/ctl.c | 7 +++++++
+ 3 files changed, 19 insertions(+), 3 deletions(-)
+
+diff --git a/include/jemalloc/internal/background_thread_externs.h b/include/jemalloc/internal/background_thread_externs.h
+index 7c883697..8b4b8471 100644
+--- a/include/jemalloc/internal/background_thread_externs.h
++++ b/include/jemalloc/internal/background_thread_externs.h
+@@ -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);
+diff --git a/src/background_thread.c b/src/background_thread.c
+index a7403b85..1ff59447 100644
+--- a/src/background_thread.c
++++ b/src/background_thread.c
+@@ -20,6 +20,9 @@ size_t n_background_threads;
+ /* Thread info per-index. */
+ background_thread_info_t *background_thread_info;
+
++/* False if no necessary runtime support. */
++bool can_enable_background_thread;
++
+ /******************************************************************************/
+
+ #ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER
+@@ -785,9 +788,14 @@ background_thread_boot0(void) {
+ #ifdef JEMALLOC_PTHREAD_CREATE_WRAPPER
+ pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create");
+ if (pthread_create_fptr == NULL) {
+- malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, "
+- "\"pthread_create\")\n");
+- abort();
++ can_enable_background_thread = false;
++ if (config_lazy_lock || opt_background_thread) {
++ malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, "
++ "\"pthread_create\")\n");
++ abort();
++ }
++ } else {
++ can_enable_background_thread = true;
+ }
+ #endif
+ return false;
+diff --git a/src/ctl.c b/src/ctl.c
+index b3ae4aab..f1310cdf 100644
+--- a/src/ctl.c
++++ b/src/ctl.c
+@@ -1522,6 +1522,13 @@ background_thread_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
+
+ background_thread_enabled_set(tsd_tsdn(tsd), newval);
+ if (newval) {
++ if (!can_enable_background_thread) {
++ malloc_printf("<jemalloc>: Error in dlsym("
++ "RTLD_NEXT, \"pthread_create\"). Cannot "
++ "enable background_thread\n");
++ ret = EFAULT;
++ goto label_return;
++ }
+ if (background_threads_enable(tsd)) {
+ ret = EFAULT;
+ goto label_return;
Copied: jemalloc/repos/testing-x86_64/0002-clear-tcache_ql-after-fork-in-child.patch (from rev 299553, jemalloc/trunk/0002-clear-tcache_ql-after-fork-in-child.patch)
===================================================================
--- testing-x86_64/0002-clear-tcache_ql-after-fork-in-child.patch (rev 0)
+++ testing-x86_64/0002-clear-tcache_ql-after-fork-in-child.patch 2017-07-02 18:37:52 UTC (rev 299554)
@@ -0,0 +1,194 @@
+From 9b1befabbb7a7105501d27843873d14e1c2de54b Mon Sep 17 00:00:00 2001
+From: Qi Wang <interwq at gwu.edu>
+Date: Thu, 15 Jun 2017 16:53:22 -0700
+Subject: [PATCH] Add minimal initialized TSD.
+
+We use the minimal_initilized tsd (which requires no cleanup) for free()
+specifically, if tsd hasn't been initialized yet.
+
+Any other activity will transit the state from minimal to normal. This is to
+workaround the case where a thread has no malloc calls in its lifetime until
+during thread termination, free() happens after tls destructors.
+---
+ include/jemalloc/internal/tsd.h | 30 ++++++++++++++++++++--------
+ src/jemalloc.c | 10 +++++++++-
+ src/tsd.c | 44 +++++++++++++++++++++++++++--------------
+ 3 files changed, 60 insertions(+), 24 deletions(-)
+
+diff --git a/include/jemalloc/internal/tsd.h b/include/jemalloc/internal/tsd.h
+index 631fbf1f..155a2ec6 100644
+--- a/include/jemalloc/internal/tsd.h
++++ b/include/jemalloc/internal/tsd.h
+@@ -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. */
+@@ -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
+@@ -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
+@@ -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) {
+@@ -257,7 +260,7 @@ 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);
+@@ -265,11 +268,22 @@ tsd_fetch_impl(bool init, bool internal) {
+ 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);
+diff --git a/src/jemalloc.c b/src/jemalloc.c
+index 52c86aa6..c773cc44 100644
+--- a/src/jemalloc.c
++++ b/src/jemalloc.c
+@@ -2264,7 +2264,15 @@ JEMALLOC_EXPORT void JEMALLOC_NOTHROW
+ je_free(void *ptr) {
+ UTRACE(ptr, 0, 0);
+ if (likely(ptr != NULL)) {
+- tsd_t *tsd = tsd_fetch();
++ /*
++ * We avoid setting up tsd fully (e.g. tcache, arena binding)
++ * based on only free() calls -- other activities trigger the
++ * minimal to full transition. This is because free() may
++ * happen during thread shutdown after tls deallocation: if a
++ * thread never had any malloc activities until then, a
++ * fully-setup tsd won't be destructed properly.
++ */
++ tsd_t *tsd = tsd_fetch_min();
+ check_entry_exit_locking(tsd_tsdn(tsd));
+
+ tcache_t *tcache;
+diff --git a/src/tsd.c b/src/tsd.c
+index 97330332..f968992f 100644
+--- a/src/tsd.c
++++ b/src/tsd.c
+@@ -87,7 +87,8 @@ assert_tsd_data_cleanup_done(tsd_t *tsd) {
+
+ static bool
+ tsd_data_init_nocleanup(tsd_t *tsd) {
+- assert(tsd->state == tsd_state_reincarnated);
++ assert(tsd->state == tsd_state_reincarnated ||
++ tsd->state == tsd_state_minimal_initialized);
+ /*
+ * During reincarnation, there is no guarantee that the cleanup function
+ * will be called (deallocation may happen after all tsd destructors).
+@@ -103,15 +104,8 @@ tsd_data_init_nocleanup(tsd_t *tsd) {
+ }
+
+ tsd_t *
+-tsd_fetch_slow(tsd_t *tsd, bool internal) {
+- if (internal) {
+- /* For internal background threads use only. */
+- assert(tsd->state == tsd_state_uninitialized);
+- tsd->state = tsd_state_reincarnated;
+- tsd_set(tsd);
+- tsd_data_init_nocleanup(tsd);
+- return tsd;
+- }
++tsd_fetch_slow(tsd_t *tsd, bool minimal) {
++ assert(!tsd_fast(tsd));
+
+ if (tsd->state == tsd_state_nominal_slow) {
+ /* On slow path but no work needed. */
+@@ -119,11 +113,28 @@ tsd_fetch_slow(tsd_t *tsd, bool internal) {
+ tsd_reentrancy_level_get(tsd) > 0 ||
+ *tsd_arenas_tdata_bypassp_get(tsd));
+ } else if (tsd->state == tsd_state_uninitialized) {
+- tsd->state = tsd_state_nominal;
+- tsd_slow_update(tsd);
+- /* Trigger cleanup handler registration. */
+- tsd_set(tsd);
+- tsd_data_init(tsd);
++ if (!minimal) {
++ tsd->state = tsd_state_nominal;
++ tsd_slow_update(tsd);
++ /* Trigger cleanup handler registration. */
++ tsd_set(tsd);
++ tsd_data_init(tsd);
++ } else {
++ tsd->state = tsd_state_minimal_initialized;
++ tsd_set(tsd);
++ tsd_data_init_nocleanup(tsd);
++ }
++ } else if (tsd->state == tsd_state_minimal_initialized) {
++ if (!minimal) {
++ /* Switch to fully initialized. */
++ tsd->state = tsd_state_nominal;
++ assert(*tsd_reentrancy_levelp_get(tsd) >= 1);
++ (*tsd_reentrancy_levelp_get(tsd))--;
++ tsd_slow_update(tsd);
++ tsd_data_init(tsd);
++ } else {
++ assert_tsd_data_cleanup_done(tsd);
++ }
+ } else if (tsd->state == tsd_state_purgatory) {
+ tsd->state = tsd_state_reincarnated;
+ tsd_set(tsd);
+@@ -197,6 +208,9 @@ tsd_cleanup(void *arg) {
+ case tsd_state_uninitialized:
+ /* Do nothing. */
+ break;
++ case tsd_state_minimal_initialized:
++ /* This implies the thread only did free() in its life time. */
++ /* Fall through. */
+ case tsd_state_reincarnated:
+ /*
+ * Reincarnated means another destructor deallocated memory
Copied: jemalloc/repos/testing-x86_64/0003-Add-minimal-initialized-tsd.patch (from rev 299553, jemalloc/trunk/0003-Add-minimal-initialized-tsd.patch)
===================================================================
--- testing-x86_64/0003-Add-minimal-initialized-tsd.patch (rev 0)
+++ testing-x86_64/0003-Add-minimal-initialized-tsd.patch 2017-07-02 18:37:52 UTC (rev 299554)
@@ -0,0 +1,37 @@
+From d35c037e03e1450794dcf595e49a1e1f97f87ac4 Mon Sep 17 00:00:00 2001
+From: Qi Wang <interwq at gwu.edu>
+Date: Mon, 19 Jun 2017 21:19:15 -0700
+Subject: [PATCH] Clear tcache_ql after fork in child.
+
+---
+ src/arena.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/src/arena.c b/src/arena.c
+index 019dd877..d401808b 100644
+--- a/src/arena.c
++++ b/src/arena.c
+@@ -2133,6 +2133,23 @@ void
+ arena_postfork_child(tsdn_t *tsdn, arena_t *arena) {
+ unsigned i;
+
++ atomic_store_u(&arena->nthreads[0], 0, ATOMIC_RELAXED);
++ atomic_store_u(&arena->nthreads[1], 0, ATOMIC_RELAXED);
++ if (tsd_arena_get(tsdn_tsd(tsdn)) == arena) {
++ arena_nthreads_inc(arena, false);
++ }
++ if (tsd_iarena_get(tsdn_tsd(tsdn)) == arena) {
++ arena_nthreads_inc(arena, true);
++ }
++ if (config_stats) {
++ ql_new(&arena->tcache_ql);
++ tcache_t *tcache = tcache_get(tsdn_tsd(tsdn));
++ if (tcache != NULL && tcache->arena == arena) {
++ ql_elm_new(tcache, link);
++ ql_tail_insert(&arena->tcache_ql, tcache, link);
++ }
++ }
++
+ for (i = 0; i < NBINS; i++) {
+ malloc_mutex_postfork_child(tsdn, &arena->bins[i].lock);
+ }
Copied: jemalloc/repos/testing-x86_64/PKGBUILD (from rev 299553, jemalloc/trunk/PKGBUILD)
===================================================================
--- testing-x86_64/PKGBUILD (rev 0)
+++ testing-x86_64/PKGBUILD 2017-07-02 18:37:52 UTC (rev 299554)
@@ -0,0 +1,31 @@
+# $Id$
+# Maintainer: Bartłomiej Piotrowski <bpiotrowski at archlinux.org>
+# Contributor: Massimiliano Torromeo <massimiliano.torromeo at gmail.com>
+# Contributor: Kovivchak Evgen <oneonfire at gmail.com>
+
+pkgname=jemalloc
+epoch=1
+pkgver=5.0.1
+pkgrel=1
+pkgdesc='General-purpose scalable concurrent malloc implementation'
+arch=('i686' 'x86_64')
+license=('BSD')
+url='http://www.canonware.com/jemalloc/'
+depends=('glibc')
+provides=('libjemalloc.so')
+optdepends=('perl: for jeprof')
+source=("https://github.com/jemalloc/jemalloc/releases/download/${pkgver}/${pkgname}-${pkgver}.tar.bz2")
+sha256sums=('4814781d395b0ef093b21a08e8e6e0bd3dab8762f9935bbfb71679b0dea7c3e9')
+
+build() {
+ cd $pkgname-$pkgver
+ ./configure --prefix=/usr
+ make
+}
+
+package() {
+ cd $pkgname-$pkgver
+ make DESTDIR="$pkgdir" install
+ find "$pkgdir" -name \*.a -type f -exec chmod 644 '{}' \;
+ install -Dm644 COPYING "$pkgdir/usr/share/licenses/$pkgname/COPYING"
+}
More information about the arch-commits
mailing list