aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQi Wang <interwq@gwu.edu>2018-03-30 15:09:05 -0700
committerQi Wang <interwq@gmail.com>2018-04-02 10:03:47 -0700
commit21eb0d15a6cfdaee3aa78f724838b503053d7f00 (patch)
tree814e91a833c4240bd38e03cff2b86d11ea686a0c
parent956c4ad6b57318bc7b6cd02bf9bfeb45afc4e3e2 (diff)
downloadplatform_external_jemalloc_new-21eb0d15a6cfdaee3aa78f724838b503053d7f00.tar.gz
platform_external_jemalloc_new-21eb0d15a6cfdaee3aa78f724838b503053d7f00.tar.bz2
platform_external_jemalloc_new-21eb0d15a6cfdaee3aa78f724838b503053d7f00.zip
Fix a background_thread shutdown issue.
1) make sure background thread 0 is always created; and 2) fix synchronization between thread 0 and the control thread.
-rw-r--r--src/background_thread.c47
-rw-r--r--test/unit/background_thread_enable.c3
2 files changed, 29 insertions, 21 deletions
diff --git a/src/background_thread.c b/src/background_thread.c
index a8a5a052..c16f0063 100644
--- a/src/background_thread.c
+++ b/src/background_thread.c
@@ -380,35 +380,29 @@ background_thread_create_signals_masked(pthread_t *thread,
return create_err;
}
-static void
+static bool
check_background_thread_creation(tsd_t *tsd, unsigned *n_created,
bool *created_threads) {
+ bool ret = false;
if (likely(*n_created == n_background_threads)) {
- return;
+ return ret;
}
- malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_info[0].mtx);
-label_restart:
- malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock);
+ tsdn_t *tsdn = tsd_tsdn(tsd);
+ malloc_mutex_unlock(tsdn, &background_thread_info[0].mtx);
for (unsigned i = 1; i < ncpus; i++) {
if (created_threads[i]) {
continue;
}
background_thread_info_t *info = &background_thread_info[i];
- malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
+ malloc_mutex_lock(tsdn, &info->mtx);
assert(info->state != background_thread_paused);
bool create = (info->state == background_thread_started);
- malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
+ malloc_mutex_unlock(tsdn, &info->mtx);
if (!create) {
continue;
}
- /*
- * To avoid deadlock with prefork handlers (which waits for the
- * mutex held here), unlock before calling pthread_create().
- */
- malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
-
pre_reentrancy(tsd, NULL);
int err = background_thread_create_signals_masked(&info->thread,
NULL, background_thread_entry, (void *)(uintptr_t)i);
@@ -424,11 +418,13 @@ label_restart:
abort();
}
}
- /* Restart since we unlocked. */
- goto label_restart;
+ /* Return to restart the loop since we unlocked. */
+ ret = true;
+ break;
}
- malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_info[0].mtx);
- malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
+ malloc_mutex_lock(tsdn, &background_thread_info[0].mtx);
+
+ return ret;
}
static void
@@ -446,8 +442,10 @@ background_thread0_work(tsd_t *tsd) {
&background_thread_info[0])) {
continue;
}
- check_background_thread_creation(tsd, &n_created,
- (bool *)&created_threads);
+ if (check_background_thread_creation(tsd, &n_created,
+ (bool *)&created_threads)) {
+ continue;
+ }
background_work_sleep_once(tsd_tsdn(tsd),
&background_thread_info[0], 0);
}
@@ -464,8 +462,13 @@ background_thread0_work(tsd_t *tsd) {
background_threads_disable_single(tsd, info);
} else {
malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
- /* Clear in case the thread wasn't created. */
- info->state = background_thread_stopped;
+ if (info->state != background_thread_stopped) {
+ /* The thread was not created. */
+ assert(info->state ==
+ background_thread_started);
+ n_background_threads--;
+ info->state = background_thread_stopped;
+ }
malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
}
}
@@ -593,6 +596,8 @@ background_threads_enable(tsd_t *tsd) {
marked[i] = false;
}
nmarked = 0;
+ /* Thread 0 is required and created at the end. */
+ marked[0] = true;
/* Mark the threads we need to create for thread 0. */
unsigned n = narenas_total_get();
for (i = 1; i < n; i++) {
diff --git a/test/unit/background_thread_enable.c b/test/unit/background_thread_enable.c
index 9bb58652..7e4f6ed7 100644
--- a/test/unit/background_thread_enable.c
+++ b/test/unit/background_thread_enable.c
@@ -24,6 +24,9 @@ TEST_BEGIN(test_deferred) {
size_t sz_b = sizeof(bool);
assert_d_eq(mallctl("background_thread", NULL, NULL, &enable, sz_b), 0,
"Failed to enable background threads");
+ enable = false;
+ assert_d_eq(mallctl("background_thread", NULL, NULL, &enable, sz_b), 0,
+ "Failed to disable background threads");
}
TEST_END