mirror of
https://github.com/jemalloc/jemalloc.git
synced 2026-07-13 04:07:23 +03:00
Handle jemalloc calls after TSD teardown
This only changes behavior for the tsd_generic path, where pthread_getspecific() can report no TSD after the pthread key destructor has finished. Other TSD backends keep tsd_teardown_done() as a constant false, so the added checks compile out there. Avoid recreating TSD for late deallocations. Preserve existing reincarnation behavior for late allocations and nonzero reallocations. Add Linux CI coverage for force_tls=0, with and without --enable-debug, to exercise the Android-equivalent generic TSD path.
This commit is contained in:
parent
82e379b8f2
commit
fb5499aa9c
11 changed files with 432 additions and 8 deletions
|
|
@ -4,7 +4,8 @@
|
|||
/*
|
||||
* We put the platform-specific data declarations and inlines into their own
|
||||
* header files to avoid cluttering this file. They define tsd_boot0,
|
||||
* tsd_boot1, tsd_boot, tsd_booted_get, tsd_get_allocates, tsd_get, and tsd_set.
|
||||
* tsd_boot1, tsd_boot, tsd_booted_get, tsd_get_allocates,
|
||||
* tsd_teardown_done, tsd_get, and tsd_set.
|
||||
*/
|
||||
#ifdef JEMALLOC_MALLOC_THREAD_CLEANUP
|
||||
# include "jemalloc/internal/jemalloc_preamble.h"
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ void *tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block);
|
|||
void tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block);
|
||||
|
||||
extern pthread_key_t tsd_tsd;
|
||||
extern pthread_key_t tsd_thread_initialized_tsd;
|
||||
extern tsd_init_head_t tsd_init_head;
|
||||
extern tsd_wrapper_t tsd_boot_wrapper;
|
||||
extern bool tsd_booted;
|
||||
|
|
@ -51,6 +52,12 @@ tsd_cleanup_wrapper(void *arg) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Leave tsd_thread_initialized_tsd set. It has no destructor and
|
||||
* intentionally outlives the TSD wrapper, so later jemalloc calls can
|
||||
* distinguish this fully-torn-down thread from one that has never
|
||||
* initialized TSD.
|
||||
*/
|
||||
malloc_tsd_dalloc(wrapper);
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +70,11 @@ tsd_wrapper_set(tsd_wrapper_t *wrapper) {
|
|||
malloc_write("<jemalloc>: Error setting TSD\n");
|
||||
abort();
|
||||
}
|
||||
if (pthread_setspecific(tsd_thread_initialized_tsd,
|
||||
(void *)&tsd_thread_initialized_tsd) != 0) {
|
||||
malloc_write("<jemalloc>: Error setting TSD\n");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE tsd_wrapper_t *
|
||||
|
|
@ -116,6 +128,15 @@ tsd_boot0(void) {
|
|||
if (pthread_key_create(&tsd_tsd, tsd_cleanup_wrapper) != 0) {
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
* This key has no destructor. It records that the current thread once
|
||||
* had jemalloc TSD, so a later NULL tsd_tsd value means teardown has
|
||||
* finished rather than initialization not having happened yet.
|
||||
*/
|
||||
if (pthread_key_create(&tsd_thread_initialized_tsd, NULL) != 0) {
|
||||
pthread_key_delete(tsd_tsd);
|
||||
return true;
|
||||
}
|
||||
tsd_booted = true;
|
||||
tsd_wrapper_set(&tsd_boot_wrapper);
|
||||
tsd_init_finish(&tsd_init_head, &block);
|
||||
|
|
@ -160,6 +181,12 @@ tsd_get_allocates(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE bool
|
||||
tsd_teardown_done(void) {
|
||||
return tsd_booted && pthread_getspecific(tsd_tsd) == NULL
|
||||
&& pthread_getspecific(tsd_thread_initialized_tsd) != NULL;
|
||||
}
|
||||
|
||||
/* Get/set. */
|
||||
JEMALLOC_ALWAYS_INLINE tsd_t *
|
||||
tsd_get(bool init) {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ tsd_get_allocates(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE bool
|
||||
tsd_teardown_done(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get/set. */
|
||||
JEMALLOC_ALWAYS_INLINE tsd_t *
|
||||
tsd_get(bool init) {
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ tsd_get_allocates(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE bool
|
||||
tsd_teardown_done(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get/set. */
|
||||
JEMALLOC_ALWAYS_INLINE tsd_t *
|
||||
tsd_get(bool init) {
|
||||
|
|
|
|||
|
|
@ -146,6 +146,11 @@ tsd_get_allocates(void) {
|
|||
return true;
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE bool
|
||||
tsd_teardown_done(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get/set. */
|
||||
JEMALLOC_ALWAYS_INLINE tsd_t *
|
||||
tsd_get(bool init) {
|
||||
|
|
@ -220,6 +225,11 @@ tsd_get_allocates(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
JEMALLOC_ALWAYS_INLINE bool
|
||||
tsd_teardown_done(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get/set. */
|
||||
JEMALLOC_ALWAYS_INLINE tsd_t *
|
||||
tsd_get(bool init) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue