use apr_pool_mutex_set to make pools thread safe

git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@12675 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Anthony Minessale 2009-03-20 01:51:50 +00:00
parent a9223882fc
commit bb45a16552
1 changed files with 105 additions and 13 deletions

View File

@ -39,13 +39,17 @@
//#define DEBUG_ALLOC2 //#define DEBUG_ALLOC2
//#define DESTROY_POOLS //#define DESTROY_POOLS
//#define INSTANTLY_DESTROY_POOLS //#define INSTANTLY_DESTROY_POOLS
/*#define LOCK_MORE*/ //#define LOCK_MORE
//#define USE_MEM_LOCK
//#define SWITCH_POOL_RECYCLE
#ifndef SWITCH_POOL_RECYCLE #ifndef SWITCH_POOL_RECYCLE
#define PER_POOL_LOCK 1 #define PER_POOL_LOCK 1
#endif #endif
static struct { static struct {
#ifdef USE_MEM_LOCK
switch_mutex_t *mem_lock; switch_mutex_t *mem_lock;
#endif
switch_queue_t *pool_queue; /* 8 ball break */ switch_queue_t *pool_queue; /* 8 ball break */
switch_queue_t *pool_recycle_queue; switch_queue_t *pool_recycle_queue;
switch_memory_pool_t *memory_pool; switch_memory_pool_t *memory_pool;
@ -69,8 +73,10 @@ SWITCH_DECLARE(void *) switch_core_perform_session_alloc(switch_core_session_t *
switch_assert(session->pool != NULL); switch_assert(session->pool != NULL);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif #endif
#endif
#ifdef DEBUG_ALLOC #ifdef DEBUG_ALLOC
if (memory > 500) if (memory > 500)
@ -83,7 +89,9 @@ SWITCH_DECLARE(void *) switch_core_perform_session_alloc(switch_core_session_t *
memset(ptr, 0, memory); memset(ptr, 0, memory);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
#endif #endif
return ptr; return ptr;
@ -98,8 +106,10 @@ SWITCH_DECLARE(void *) switch_core_perform_permanent_alloc(switch_size_t memory,
switch_assert(memory_manager.memory_pool != NULL); switch_assert(memory_manager.memory_pool != NULL);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif #endif
#endif
#ifdef DEBUG_ALLOC #ifdef DEBUG_ALLOC
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_CONSOLE, "Perm Allocate %d\n", (int) memory); switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_CONSOLE, "Perm Allocate %d\n", (int) memory);
@ -111,7 +121,9 @@ SWITCH_DECLARE(void *) switch_core_perform_permanent_alloc(switch_size_t memory,
memset(ptr, 0, memory); memset(ptr, 0, memory);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
#endif #endif
return ptr; return ptr;
@ -127,7 +139,9 @@ SWITCH_DECLARE(char *) switch_core_perform_permanent_strdup(const char *todup, c
return NULL; return NULL;
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif
#endif #endif
len = strlen(todup) + 1; len = strlen(todup) + 1;
@ -139,7 +153,9 @@ SWITCH_DECLARE(char *) switch_core_perform_permanent_strdup(const char *todup, c
#endif #endif
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
#endif #endif
return duped; return duped;
@ -151,7 +167,9 @@ SWITCH_DECLARE(char *) switch_core_session_sprintf(switch_core_session_t *sessio
char *result = NULL; char *result = NULL;
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif
#endif #endif
switch_assert(session != NULL); switch_assert(session != NULL);
@ -163,7 +181,9 @@ SWITCH_DECLARE(char *) switch_core_session_sprintf(switch_core_session_t *sessio
va_end(ap); va_end(ap);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
#endif #endif
return result; return result;
@ -177,7 +197,9 @@ SWITCH_DECLARE(char *) switch_core_sprintf(switch_memory_pool_t *pool, const cha
switch_assert(pool != NULL); switch_assert(pool != NULL);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif
#endif #endif
va_start(ap, fmt); va_start(ap, fmt);
@ -187,7 +209,9 @@ SWITCH_DECLARE(char *) switch_core_sprintf(switch_memory_pool_t *pool, const cha
va_end(ap); va_end(ap);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
#endif #endif
return result; return result;
@ -196,30 +220,36 @@ SWITCH_DECLARE(char *) switch_core_sprintf(switch_memory_pool_t *pool, const cha
SWITCH_DECLARE(char *) switch_core_perform_session_strdup(switch_core_session_t *session, const char *todup, const char *file, const char *func, int line) SWITCH_DECLARE(char *) switch_core_perform_session_strdup(switch_core_session_t *session, const char *todup, const char *file, const char *func, int line)
{ {
char *duped = NULL; char *duped = NULL;
switch_size_t len;
switch_assert(session != NULL); switch_assert(session != NULL);
switch_assert(session->pool != NULL); switch_assert(session->pool != NULL);
#ifdef DEBUG_ALLOC
switch_size_t len;
#endif
if (!todup) { if (!todup) {
return NULL; return NULL;
} }
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif #endif
#endif
len = strlen(todup) + 1;
#ifdef DEBUG_ALLOC #ifdef DEBUG_ALLOC
len = strlen(todup);
if (len > 500) if (len > 500)
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_CONSOLE, "Sess Strdup Allocate %d\n", (int) len); switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_CONSOLE, "Sess Strdup Allocate %d\n", (int) len);
#endif #endif
duped = apr_pstrmemdup(session->pool, todup, len); duped = strdup(todup);
switch_assert(duped != NULL); switch_assert(duped != NULL);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
#endif #endif
return duped; return duped;
@ -235,7 +265,9 @@ SWITCH_DECLARE(char *) switch_core_perform_strdup(switch_memory_pool_t *pool, co
return NULL; return NULL;
} }
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif
#endif #endif
len = strlen(todup) + 1; len = strlen(todup) + 1;
@ -249,7 +281,9 @@ SWITCH_DECLARE(char *) switch_core_perform_strdup(switch_memory_pool_t *pool, co
switch_assert(duped != NULL); switch_assert(duped != NULL);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
#endif #endif
return duped; return duped;
@ -275,7 +309,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(switch_memor
void *pop = NULL; void *pop = NULL;
#endif #endif
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif
switch_assert(pool != NULL); switch_assert(pool != NULL);
#ifndef PER_POOL_LOCK #ifndef PER_POOL_LOCK
@ -286,21 +322,22 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(switch_memor
#ifdef PER_POOL_LOCK #ifdef PER_POOL_LOCK
if ((apr_allocator_create(&my_allocator)) != APR_SUCCESS) { if ((apr_allocator_create(&my_allocator)) != APR_SUCCESS) {
return SWITCH_STATUS_MEMERR; abort();
} }
if ((apr_pool_create_ex(pool, NULL, NULL, my_allocator)) != APR_SUCCESS) { if ((apr_pool_create_ex(pool, NULL, NULL, my_allocator)) != APR_SUCCESS) {
apr_allocator_destroy(my_allocator); abort();
my_allocator = NULL;
return SWITCH_STATUS_MEMERR;
} }
if ((apr_thread_mutex_create(&my_mutex, APR_THREAD_MUTEX_DEFAULT, *pool)) != APR_SUCCESS) { if ((apr_thread_mutex_create(&my_mutex, APR_THREAD_MUTEX_NESTED, *pool)) != APR_SUCCESS) {
return SWITCH_STATUS_MEMERR; abort();
} }
apr_allocator_mutex_set(my_allocator, my_mutex); apr_allocator_mutex_set(my_allocator, my_mutex);
apr_allocator_owner_set(my_allocator, *pool); apr_allocator_owner_set(my_allocator, *pool);
apr_pool_mutex_set(*pool, my_mutex);
#else #else
apr_pool_create(pool, NULL); apr_pool_create(pool, NULL);
switch_assert(*pool != NULL); switch_assert(*pool != NULL);
@ -313,7 +350,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_new_memory_pool(switch_memor
#endif #endif
tmp = switch_core_sprintf(*pool, "%s:%d", func, line); tmp = switch_core_sprintf(*pool, "%s:%d", func, line);
apr_pool_tag(*pool, tmp); apr_pool_tag(*pool, tmp);
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -327,10 +368,22 @@ SWITCH_DECLARE(switch_status_t) switch_core_perform_destroy_memory_pool(switch_m
#endif #endif
#ifdef INSTANTLY_DESTROY_POOLS #ifdef INSTANTLY_DESTROY_POOLS
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock);
#endif
apr_pool_destroy(*pool); apr_pool_destroy(*pool);
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock);
#endif
#else #else
if ((memory_manager.pool_thread_running != 1) || (switch_queue_push(memory_manager.pool_queue, *pool) != SWITCH_STATUS_SUCCESS)) { if ((memory_manager.pool_thread_running != 1) || (switch_queue_push(memory_manager.pool_queue, *pool) != SWITCH_STATUS_SUCCESS)) {
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock);
#endif
apr_pool_destroy(*pool); apr_pool_destroy(*pool);
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock);
#endif
} }
#endif #endif
@ -346,8 +399,10 @@ SWITCH_DECLARE(void *) switch_core_perform_alloc(switch_memory_pool_t *pool, swi
switch_assert(pool != NULL); switch_assert(pool != NULL);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif #endif
#endif
#ifdef DEBUG_ALLOC #ifdef DEBUG_ALLOC
if (memory > 500) if (memory > 500)
@ -360,7 +415,9 @@ SWITCH_DECLARE(void *) switch_core_perform_alloc(switch_memory_pool_t *pool, swi
memset(ptr, 0, memory); memset(ptr, 0, memory);
#ifdef LOCK_MORE #ifdef LOCK_MORE
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
#endif #endif
return ptr; return ptr;
@ -379,7 +436,13 @@ SWITCH_DECLARE(void) switch_core_memory_reclaim(void)
if (!pool) { if (!pool) {
break; break;
} }
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock);
#endif
apr_pool_destroy(pool); apr_pool_destroy(pool);
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock);
#endif
} }
#endif #endif
return; return;
@ -396,7 +459,9 @@ static void *SWITCH_THREAD_FUNC pool_thread(switch_thread_t *thread, void *obj)
int x = len, done = 0; int x = len, done = 0;
switch_yield(1000000); switch_yield(1000000);
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock); switch_mutex_lock(memory_manager.mem_lock);
#endif
while (x > 0) { while (x > 0) {
void *pop = NULL; void *pop = NULL;
if (switch_queue_pop(memory_manager.pool_queue, &pop) != SWITCH_STATUS_SUCCESS || !pop) { if (switch_queue_pop(memory_manager.pool_queue, &pop) != SWITCH_STATUS_SUCCESS || !pop) {
@ -405,16 +470,31 @@ static void *SWITCH_THREAD_FUNC pool_thread(switch_thread_t *thread, void *obj)
} }
#if defined(PER_POOL_LOCK) || defined(DESTROY_POOLS) #if defined(PER_POOL_LOCK) || defined(DESTROY_POOLS)
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock);
#endif
apr_pool_destroy(pop); apr_pool_destroy(pop);
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock);
#endif
#else #else
apr_pool_clear(pop); apr_pool_clear(pop);
if (switch_queue_trypush(memory_manager.pool_recycle_queue, pop) != SWITCH_STATUS_SUCCESS) { if (switch_queue_trypush(memory_manager.pool_recycle_queue, pop) != SWITCH_STATUS_SUCCESS) {
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock);
#endif
apr_pool_destroy(pop); apr_pool_destroy(pop);
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock);
#endif
} }
#endif #endif
x--; x--;
} }
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock); switch_mutex_unlock(memory_manager.mem_lock);
#endif
if (done) { if (done) {
goto done; goto done;
} }
@ -429,8 +509,15 @@ static void *SWITCH_THREAD_FUNC pool_thread(switch_thread_t *thread, void *obj)
{ {
void *pop = NULL; void *pop = NULL;
while (switch_queue_trypop(memory_manager.pool_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) { while (switch_queue_trypop(memory_manager.pool_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
#ifdef USE_MEM_LOCK
switch_mutex_lock(memory_manager.mem_lock);
#endif
apr_pool_destroy(pop); apr_pool_destroy(pop);
pop = NULL; pop = NULL;
#ifdef USE_MEM_LOCK
switch_mutex_unlock(memory_manager.mem_lock);
#endif
} }
} }
@ -439,14 +526,17 @@ static void *SWITCH_THREAD_FUNC pool_thread(switch_thread_t *thread, void *obj)
return NULL; return NULL;
} }
#ifndef INSTANTLY_DESTROY_POOLS
static switch_thread_t *pool_thread_p = NULL; static switch_thread_t *pool_thread_p = NULL;
#endif
void switch_core_memory_stop(void) void switch_core_memory_stop(void)
{ {
#ifndef INSTANTLY_DESTROY_POOLS
switch_status_t st; switch_status_t st;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping memory pool queue.\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CONSOLE, "Stopping memory pool queue.\n");
#ifndef INSTANTLY_DESTROY_POOLS
memory_manager.pool_thread_running = -1; memory_manager.pool_thread_running = -1;
switch_thread_join(&st, pool_thread_p); switch_thread_join(&st, pool_thread_p);
@ -490,7 +580,9 @@ switch_memory_pool_t *switch_core_memory_init(void)
switch_assert(memory_manager.memory_pool != NULL); switch_assert(memory_manager.memory_pool != NULL);
#endif #endif
#ifdef USE_MEM_LOCK
switch_mutex_init(&memory_manager.mem_lock, SWITCH_MUTEX_NESTED, memory_manager.memory_pool); switch_mutex_init(&memory_manager.mem_lock, SWITCH_MUTEX_NESTED, memory_manager.memory_pool);
#endif
#ifdef INSTANTLY_DESTROY_POOLS #ifdef INSTANTLY_DESTROY_POOLS
{ {