diff options
Diffstat (limited to 'libglusterfs/src/mem-pool.c')
-rw-r--r-- | libglusterfs/src/mem-pool.c | 98 |
1 files changed, 31 insertions, 67 deletions
diff --git a/libglusterfs/src/mem-pool.c b/libglusterfs/src/mem-pool.c index 9b4ea520b84..ab78804012f 100644 --- a/libglusterfs/src/mem-pool.c +++ b/libglusterfs/src/mem-pool.c @@ -353,7 +353,6 @@ free: FREE(ptr); } -static pthread_key_t pool_key; static pthread_mutex_t pool_lock = PTHREAD_MUTEX_INITIALIZER; static struct list_head pool_threads; static pthread_mutex_t pool_free_lock = PTHREAD_MUTEX_INITIALIZER; @@ -361,6 +360,8 @@ static struct list_head pool_free_threads; static struct mem_pool_shared pools[NPOOLS]; static size_t pool_list_size; +static __thread per_thread_pool_list_t *thread_pool_list = NULL; + #if !defined(GF_DISABLE_MEMPOOL) #define N_COLD_LISTS 1024 #define POOL_SWEEP_SECS 30 @@ -373,7 +374,6 @@ typedef struct { enum init_state { GF_MEMPOOL_INIT_NONE = 0, - GF_MEMPOOL_INIT_PREINIT, GF_MEMPOOL_INIT_EARLY, GF_MEMPOOL_INIT_LATE, GF_MEMPOOL_INIT_DESTROY @@ -486,9 +486,9 @@ pool_sweeper(void *arg) } void -pool_destructor(void *arg) +mem_pool_thread_destructor(void) { - per_thread_pool_list_t *pool_list = arg; + per_thread_pool_list_t *pool_list = thread_pool_list; /* The pool-sweeper thread will take it from here. * @@ -499,7 +499,10 @@ pool_destructor(void *arg) * This change can modify what mem_put() does, but both possibilities are * fine until the sweeper thread kicks in. The real synchronization must be * between mem_put() and the sweeper thread. */ - pool_list->poison = 1; + if (pool_list != NULL) { + pool_list->poison = 1; + thread_pool_list = NULL; + } } static __attribute__((constructor)) void @@ -522,46 +525,14 @@ mem_pools_preinit(void) pool_list_size = sizeof(per_thread_pool_list_t) + sizeof(per_thread_pool_t) * (NPOOLS - 1); - init_done = GF_MEMPOOL_INIT_PREINIT; + init_done = GF_MEMPOOL_INIT_EARLY; } -/* Use mem_pools_init_early() function for basic initialization. There will be - * no cleanup done by the pool_sweeper thread until mem_pools_init_late() has - * been called. Calling mem_get() will be possible after this function has - * setup the basic structures. */ +/* Call mem_pools_init() once threading has been configured completely. This + * prevent the pool_sweeper thread from getting killed once the main() thread + * exits during deamonizing. */ void -mem_pools_init_early(void) -{ - pthread_mutex_lock(&init_mutex); - /* Use a pthread_key destructor to clean up when a thread exits. - * - * We won't increase init_count here, that is only done when the - * pool_sweeper thread is started too. - */ - if (init_done == GF_MEMPOOL_INIT_PREINIT || - init_done == GF_MEMPOOL_INIT_DESTROY) { - /* key has not been created yet */ - if (pthread_key_create(&pool_key, pool_destructor) != 0) { - gf_log("mem-pool", GF_LOG_CRITICAL, - "failed to initialize mem-pool key"); - } - - init_done = GF_MEMPOOL_INIT_EARLY; - } else { - gf_log("mem-pool", GF_LOG_CRITICAL, - "incorrect order of mem-pool initialization " - "(init_done=%d)", - init_done); - } - - pthread_mutex_unlock(&init_mutex); -} - -/* Call mem_pools_init_late() once threading has been configured completely. - * This prevent the pool_sweeper thread from getting killed once the main() - * thread exits during deamonizing. */ -void -mem_pools_init_late(void) +mem_pools_init(void) { pthread_mutex_lock(&init_mutex); if ((init_count++) == 0) { @@ -580,13 +551,12 @@ mem_pools_fini(void) switch (init_count) { case 0: /* - * If init_count is already zero (as e.g. if somebody called - * this before mem_pools_init_late) then the sweeper was - * probably never even started so we don't need to stop it. - * Even if there's some crazy circumstance where there is a - * sweeper but init_count is still zero, that just means we'll - * leave it running. Not perfect, but far better than any - * known alternative. + * If init_count is already zero (as e.g. if somebody called this + * before mem_pools_init) then the sweeper was probably never even + * started so we don't need to stop it. Even if there's some crazy + * circumstance where there is a sweeper but init_count is still + * zero, that just means we'll leave it running. Not perfect, but + * far better than any known alternative. */ break; case 1: { @@ -594,20 +564,17 @@ mem_pools_fini(void) per_thread_pool_list_t *next_pl; unsigned int i; - /* if only mem_pools_init_early() was called, sweeper_tid will - * be invalid and the functions will error out. That is not - * critical. In all other cases, the sweeper_tid will be valid - * and the thread gets stopped. */ + /* if mem_pools_init() was not called, sweeper_tid will be invalid + * and the functions will error out. That is not critical. In all + * other cases, the sweeper_tid will be valid and the thread gets + * stopped. */ (void)pthread_cancel(sweeper_tid); (void)pthread_join(sweeper_tid, NULL); - /* Need to clean the pool_key to prevent further usage of the - * per_thread_pool_list_t structure that is stored for each - * thread. - * This also prevents calling pool_destructor() when a thread - * exits, so there is no chance on a use-after-free of the - * per_thread_pool_list_t structure. */ - (void)pthread_key_delete(pool_key); + /* At this point all threads should have already terminated, so + * it should be safe to destroy all pending per_thread_pool_list_t + * structures that are stored for each thread. */ + mem_pool_thread_destructor(); /* free all objects from all pools */ list_for_each_entry_safe(pool_list, next_pl, &pool_threads, @@ -642,11 +609,7 @@ mem_pools_fini(void) #else void -mem_pools_init_early(void) -{ -} -void -mem_pools_init_late(void) +mem_pools_init(void) { } void @@ -734,7 +697,7 @@ mem_get_pool_list(void) per_thread_pool_list_t *pool_list; unsigned int i; - pool_list = pthread_getspecific(pool_key); + pool_list = thread_pool_list; if (pool_list) { return pool_list; } @@ -767,7 +730,8 @@ mem_get_pool_list(void) list_add(&pool_list->thr_list, &pool_threads); (void)pthread_mutex_unlock(&pool_lock); - (void)pthread_setspecific(pool_key, pool_list); + thread_pool_list = pool_list; + return pool_list; } |