diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h index 74f8f61f9985345d68aa8aa0919c6b97a328053e..03752015c3f2fa16e53674add55783c3fea3bd79 100644 --- a/include/asterisk/astobj2.h +++ b/include/asterisk/astobj2.h @@ -634,6 +634,9 @@ int __ao2_trylock(void *a, enum ao2_lock_req lock_how, const char *file, const c * lock address, this allows you to correlate against * object address, to match objects to reported locks. * + * \warning AO2 lock objects do not include tracking fields when + * DEBUG_THREADS is not enabled. + * * \since 1.6.1 */ void *ao2_object_get_lockaddr(void *obj); diff --git a/include/asterisk/lock.h b/include/asterisk/lock.h index 652ca136eaece13ab89776455638ea824f0ca917..5b596d2894b45e5d2ddc468e0a5f52c9b0d981a2 100644 --- a/include/asterisk/lock.h +++ b/include/asterisk/lock.h @@ -92,11 +92,11 @@ #define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE } #endif -#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, NULL, 1 } -#define AST_MUTEX_INIT_VALUE_NOTRACKING { PTHREAD_MUTEX_INIT_VALUE, NULL, 0 } +#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, NULL, {1, 0} } +#define AST_MUTEX_INIT_VALUE_NOTRACKING { PTHREAD_MUTEX_INIT_VALUE, NULL, {0, 0} } -#define AST_RWLOCK_INIT_VALUE { __AST_RWLOCK_INIT_VALUE, NULL, 1 } -#define AST_RWLOCK_INIT_VALUE_NOTRACKING { __AST_RWLOCK_INIT_VALUE, NULL, 0 } +#define AST_RWLOCK_INIT_VALUE { __AST_RWLOCK_INIT_VALUE, NULL, {1, 0} } +#define AST_RWLOCK_INIT_VALUE_NOTRACKING { __AST_RWLOCK_INIT_VALUE, NULL, {0, 0} } #define AST_MAX_REENTRANCY 10 @@ -120,6 +120,13 @@ struct ast_lock_track { pthread_mutex_t reentr_mutex; }; +struct ast_lock_track_flags { + /*! non-zero if lock tracking is enabled */ + unsigned int tracking:1; + /*! non-zero if track is setup */ + volatile unsigned int setup:1; +}; + /*! \brief Structure for mutex and tracking information. * * We have tracking information in this structure regardless of DEBUG_THREADS being enabled. @@ -127,9 +134,18 @@ struct ast_lock_track { */ struct ast_mutex_info { pthread_mutex_t mutex; - /*! Track which thread holds this mutex */ +#if !defined(DEBUG_THREADS) && !defined(DEBUG_THREADS_LOOSE_ABI) + /*! + * These fields are renamed to ensure they are never used when + * DEBUG_THREADS is not defined. + */ + struct ast_lock_track *_track; + struct ast_lock_track_flags _flags; +#elif defined(DEBUG_THREADS) + /*! Track which thread holds this mutex. */ struct ast_lock_track *track; - unsigned int tracking:1; + struct ast_lock_track_flags flags; +#endif }; /*! \brief Structure for rwlock and tracking information. @@ -139,9 +155,18 @@ struct ast_mutex_info { */ struct ast_rwlock_info { pthread_rwlock_t lock; +#if !defined(DEBUG_THREADS) && !defined(DEBUG_THREADS_LOOSE_ABI) + /*! + * These fields are renamed to ensure they are never used when + * DEBUG_THREADS is not defined. + */ + struct ast_lock_track *_track; + struct ast_lock_track_flags _flags; +#elif defined(DEBUG_THREADS) /*! Track which thread holds this lock */ struct ast_lock_track *track; - unsigned int tracking:1; + struct ast_lock_track_flags flags; +#endif }; typedef struct ast_mutex_info ast_mutex_t; diff --git a/main/astobj2.c b/main/astobj2.c index 825c3c8e61446aa3bbefaccc74e2e1cc3ad98dd4..95c922721634dc92a9e72d03278deee07a046087 100644 --- a/main/astobj2.c +++ b/main/astobj2.c @@ -25,6 +25,10 @@ <support_level>core</support_level> ***/ +/* This reduces the size of lock structures within astobj2 objects when + * DEBUG_THREADS is not defined. */ +#define DEBUG_THREADS_LOOSE_ABI + #include "asterisk.h" ASTERISK_FILE_VERSION(__FILE__, "$Revision$") diff --git a/main/lock.c b/main/lock.c index c196c56afde0cd110473476f0c330984848ecb58..23dff4f7375f40ed33c7a0ac7a6fc47010d39868 100644 --- a/main/lock.c +++ b/main/lock.c @@ -65,21 +65,16 @@ static void __dump_backtrace(struct ast_bt *bt, int canlog) #ifdef DEBUG_THREADS AST_MUTEX_DEFINE_STATIC(reentrancy_lock); -static inline struct ast_lock_track *ast_get_reentrancy(struct ast_lock_track **plt) +static inline struct ast_lock_track *ast_get_reentrancy(struct ast_lock_track **plt, + struct ast_lock_track_flags *flags, int no_setup) { pthread_mutexattr_t reentr_attr; struct ast_lock_track *lt; - /* It's a bit painful to lock a global mutex for every access to the - * reentrancy structure, but it's necessary to ensure that we don't - * double-allocate the structure or double-initialize the reentr_mutex. - * - * If you'd like to replace this with a double-checked lock, be sure to - * properly volatile-ize everything to avoid optimizer bugs. - * - * We also have to use the underlying pthread calls for manipulating - * the mutex, because this is called from the Asterisk mutex code. - */ + if (!flags->tracking || flags->setup) { + return *plt; + } + pthread_mutex_lock(&reentrancy_lock.mutex); if (*plt) { @@ -87,6 +82,11 @@ static inline struct ast_lock_track *ast_get_reentrancy(struct ast_lock_track ** return *plt; } + if (no_setup) { + pthread_mutex_unlock(&reentrancy_lock.mutex); + return NULL; + } + lt = *plt = ast_std_calloc(1, sizeof(*lt)); if (!lt) { fprintf(stderr, "%s: Failed to allocate lock tracking\n", __func__); @@ -103,6 +103,7 @@ static inline struct ast_lock_track *ast_get_reentrancy(struct ast_lock_track ** pthread_mutex_init(<->reentr_mutex, &reentr_attr); pthread_mutexattr_destroy(&reentr_attr); + flags->setup = 1; pthread_mutex_unlock(&reentrancy_lock.mutex); return lt; } @@ -141,7 +142,8 @@ int __ast_pthread_mutex_init(int tracking, const char *filename, int lineno, con #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ t->track = NULL; - t->tracking = tracking; + t->flags.tracking = tracking; + t->flags.setup = 0; #endif /* DEBUG_THREADS */ pthread_mutexattr_init(&attr); @@ -158,8 +160,8 @@ int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *fu int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = t->track; - int canlog = t->tracking && strcmp(filename, "logger.c"); + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 1); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { @@ -236,16 +238,12 @@ int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func, int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = NULL; - int canlog = t->tracking && strcmp(filename, "logger.c"); + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - if (lt) { #ifdef HAVE_BKTR struct ast_bt tmp; @@ -360,16 +358,12 @@ int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *fu int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = NULL; - int canlog = t->tracking && strcmp(filename, "logger.c"); + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - if (lt) { #ifdef HAVE_BKTR struct ast_bt tmp; @@ -425,7 +419,7 @@ int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *fun #ifdef DEBUG_THREADS struct ast_lock_track *lt = NULL; - int canlog = t->tracking && strcmp(filename, "logger.c"); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif @@ -439,10 +433,7 @@ int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *fun } #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - + lt = ast_get_reentrancy(&t->track, &t->flags, 0); if (lt) { ast_reentrancy_lock(lt); if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) { @@ -554,7 +545,7 @@ int __ast_cond_wait(const char *filename, int lineno, const char *func, #ifdef DEBUG_THREADS struct ast_lock_track *lt = NULL; struct ast_lock_track lt_orig; - int canlog = t->tracking && strcmp(filename, "logger.c"); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { @@ -565,10 +556,7 @@ int __ast_cond_wait(const char *filename, int lineno, const char *func, } #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - + lt = ast_get_reentrancy(&t->track, &t->flags, 0); if (lt) { ast_reentrancy_lock(lt); if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) { @@ -622,7 +610,7 @@ int __ast_cond_timedwait(const char *filename, int lineno, const char *func, #ifdef DEBUG_THREADS struct ast_lock_track *lt = NULL; struct ast_lock_track lt_orig; - int canlog = t->tracking && strcmp(filename, "logger.c"); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { @@ -633,10 +621,7 @@ int __ast_cond_timedwait(const char *filename, int lineno, const char *func, } #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - + lt = ast_get_reentrancy(&t->track, &t->flags, 0); if (lt) { ast_reentrancy_lock(lt); if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) { @@ -699,7 +684,8 @@ int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ t->track = NULL; - t->tracking = tracking; + t->flags.tracking = tracking; + t->flags.setup = 0; #endif /* DEBUG_THREADS */ pthread_rwlockattr_init(&attr); @@ -717,8 +703,8 @@ int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, con int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = t->track; - int canlog = t->tracking && strcmp(filename, "logger.c"); + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 1); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { @@ -765,7 +751,7 @@ int __ast_rwlock_unlock(const char *filename, int line, const char *func, ast_rw #ifdef DEBUG_THREADS struct ast_lock_track *lt = NULL; - int canlog = t->tracking && strcmp(filename, "logger.c"); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif @@ -780,10 +766,7 @@ int __ast_rwlock_unlock(const char *filename, int line, const char *func, ast_rw } #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - + lt = ast_get_reentrancy(&t->track, &t->flags, 0); if (lt) { ast_reentrancy_lock(lt); if (lt->reentrancy) { @@ -844,16 +827,12 @@ int __ast_rwlock_rdlock(const char *filename, int line, const char *func, ast_rw int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = NULL; - int canlog = t->tracking && strcmp(filename, "logger.c"); + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - if (lt) { #ifdef HAVE_BKTR struct ast_bt tmp; @@ -953,16 +932,12 @@ int __ast_rwlock_wrlock(const char *filename, int line, const char *func, ast_rw int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = NULL; - int canlog = t->tracking && strcmp(filename, "logger.c"); + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - if (lt) { #ifdef HAVE_BKTR struct ast_bt tmp; @@ -1062,16 +1037,12 @@ int __ast_rwlock_timedrdlock(const char *filename, int line, const char *func, a int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = NULL; - int canlog = t->tracking && strcmp(filename, "logger.c"); + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - if (lt) { #ifdef HAVE_BKTR struct ast_bt tmp; @@ -1155,16 +1126,12 @@ int __ast_rwlock_timedwrlock(const char *filename, int line, const char *func, a int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = NULL; - int canlog = t->tracking && strcmp(filename, "logger.c"); + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0); + int canlog = t->flags.tracking && strcmp(filename, "logger.c"); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - if (lt) { #ifdef HAVE_BKTR struct ast_bt tmp; @@ -1247,15 +1214,11 @@ int __ast_rwlock_tryrdlock(const char *filename, int line, const char *func, ast int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = NULL; + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - if (lt) { #ifdef HAVE_BKTR struct ast_bt tmp; @@ -1306,15 +1269,11 @@ int __ast_rwlock_trywrlock(const char *filename, int line, const char *func, ast int res; #ifdef DEBUG_THREADS - struct ast_lock_track *lt = NULL; + struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0); #ifdef HAVE_BKTR struct ast_bt *bt = NULL; #endif - if (t->tracking) { - lt = ast_get_reentrancy(&t->track); - } - if (lt) { #ifdef HAVE_BKTR struct ast_bt tmp;