[arch-commits] Commit in jemalloc/trunk (3 files)

Christian Hesse eworm at archlinux.org
Wed Jun 21 07:08:49 UTC 2017


    Date: Wednesday, June 21, 2017 @ 07:08:48
  Author: eworm
Revision: 299098

upgpkg: jemalloc 1:5.0.0-3

Back to 5.0.0, include some extra patches (FS#54483: [jemalloc] Crashes QEMU)

https://bugs.archlinux.org/task/54483
https://github.com/jemalloc/jemalloc/issues/915

Added:
  jemalloc/trunk/0002-clear-tcache_ql-after-fork-in-child.patch
  jemalloc/trunk/0003-Add-minimal-initialized-tsd.patch
Modified:
  jemalloc/trunk/PKGBUILD

------------------------------------------------+
 0002-clear-tcache_ql-after-fork-in-child.patch |  194 +++++++++++++++++++++++
 0003-Add-minimal-initialized-tsd.patch         |   37 ++++
 PKGBUILD                                       |   21 ++
 3 files changed, 248 insertions(+), 4 deletions(-)

Added: 0002-clear-tcache_ql-after-fork-in-child.patch
===================================================================
--- 0002-clear-tcache_ql-after-fork-in-child.patch	                        (rev 0)
+++ 0002-clear-tcache_ql-after-fork-in-child.patch	2017-06-21 07:08:48 UTC (rev 299098)
@@ -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

Added: 0003-Add-minimal-initialized-tsd.patch
===================================================================
--- 0003-Add-minimal-initialized-tsd.patch	                        (rev 0)
+++ 0003-Add-minimal-initialized-tsd.patch	2017-06-21 07:08:48 UTC (rev 299098)
@@ -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);
+ 	}

Modified: PKGBUILD
===================================================================
--- PKGBUILD	2017-06-21 06:36:57 UTC (rev 299097)
+++ PKGBUILD	2017-06-21 07:08:48 UTC (rev 299098)
@@ -5,8 +5,8 @@
 
 pkgname=jemalloc
 epoch=1
-pkgver=4.5.0
-pkgrel=1
+pkgver=5.0.0
+pkgrel=3
 pkgdesc='General-purpose scalable concurrent malloc implementation'
 arch=('i686' 'x86_64')
 license=('BSD')
@@ -14,9 +14,22 @@
 depends=('glibc')
 provides=('libjemalloc.so')
 optdepends=('perl: for jeprof')
-source=("https://github.com/jemalloc/jemalloc/releases/download/${pkgver}/${pkgname}-${pkgver}.tar.bz2")
-sha256sums=('9409d85664b4f135b77518b0b118c549009dc10f6cba14557d170476611f6780')
+source=("https://github.com/jemalloc/jemalloc/releases/download/${pkgver}/${pkgname}-${pkgver}.tar.bz2"
+        '0001-only-abort-on-dlsym-when-necessary.patch'
+        '0002-clear-tcache_ql-after-fork-in-child.patch'
+        '0003-Add-minimal-initialized-tsd.patch')
+sha256sums=('9e4a9efba7dc4a7696f247c90c3fe89696de5f910f7deacf7e22ec521b1fa810'
+            'ef8b3afd9f7e8ee871bf6b228b0f9288881f6cc0243478bab727ba02eb2776e0'
+            'd627e0cf2b540bdeea3a4cd15c28b949faa30064eb7f53da11aa9a428732bb63'
+            'bb36a2802e5f78fc0a1f3c0ddf334d01bb04116ba712f1fd05eb47231af094c6')
 
+prepare() {
+  cd $pkgname-$pkgver
+  patch -Np1 < "$srcdir"/0001-only-abort-on-dlsym-when-necessary.patch
+  patch -Np1 < "$srcdir"/0002-clear-tcache_ql-after-fork-in-child.patch
+  patch -Np1 < "$srcdir"/0003-Add-minimal-initialized-tsd.patch
+}
+
 build() {
   cd $pkgname-$pkgver
   ./configure --prefix=/usr



More information about the arch-commits mailing list