30 #ifdef HAVE_MTX_PROFILE 32 static int mtx_prof = -1;
33 static void __attribute__((constructor)) __mtx_init(
void)
43 #undef pthread_mutex_init 44 #undef pthread_mutex_destroy 45 #undef pthread_mutex_lock 46 #undef pthread_mutex_trylock 47 #undef pthread_mutex_t 48 #undef pthread_mutex_unlock 49 #undef pthread_cond_init 50 #undef pthread_cond_signal 51 #undef pthread_cond_broadcast 52 #undef pthread_cond_destroy 53 #undef pthread_cond_wait 54 #undef pthread_cond_timedwait 56 #if defined(DEBUG_THREADS) 57 #define log_mutex_error(canlog, ...) \ 60 ast_log(LOG_ERROR, __VA_ARGS__); \ 62 fprintf(stderr, __VA_ARGS__); \ 67 #if defined(DEBUG_THREADS) && defined(HAVE_BKTR) 89 pthread_mutexattr_t reentr_attr;
110 fprintf(stderr,
"%s: Failed to allocate lock tracking\n", __func__);
111 #if defined(DO_CRASH) || defined(THREAD_CRASH) 119 pthread_mutexattr_init(&reentr_attr);
122 pthread_mutexattr_destroy(&reentr_attr);
148 pthread_mutexattr_t attr;
151 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 153 int canlog = tracking && strcmp(filename,
"logger.c");
155 log_mutex_error(canlog,
"%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n",
156 filename, lineno, func, mutex_name);
167 pthread_mutexattr_init(&attr);
170 pthread_mutexattr_destroy(&attr);
182 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
184 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 192 log_mutex_error(canlog,
"%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
193 filename, lineno, func, mutex_name);
206 log_mutex_error(canlog,
"%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
207 filename, lineno, func, mutex_name);
210 log_mutex_error(canlog,
"%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
211 filename, lineno, func, mutex_name);
214 log_mutex_error(canlog,
"%s line %d (%s): Error: '%s' was locked here.\n",
229 log_mutex_error(canlog,
"%s line %d (%s): Error destroying mutex %s: %s\n",
230 filename, lineno, func, mutex_name, strerror(res));
232 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 237 lt->
file[0] = filename;
260 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
283 #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS) 285 time_t seconds = time(
NULL);
286 time_t wait_time, reported_wait = 0;
288 #ifdef HAVE_MTX_PROFILE 292 #ifdef HAVE_MTX_PROFILE 296 wait_time = time(
NULL) - seconds;
297 if (wait_time > reported_wait && (wait_time % 5) == 0) {
298 log_mutex_error(canlog,
"%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
299 filename, lineno, func, (
int) wait_time, mutex_name);
313 reported_wait = wait_time;
317 }
while (res == EBUSY);
320 #ifdef HAVE_MTX_PROFILE 339 log_mutex_error(canlog,
"%s line %d (%s): '%s' really deep reentrancy!\n",
340 filename, lineno, func, mutex_name);
357 log_mutex_error(canlog,
"%s line %d (%s): Error obtaining mutex: %s\n",
358 filename, lineno, func, strerror(res));
373 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
408 log_mutex_error(canlog,
"%s line %d (%s): '%s' really deep reentrancy!\n",
409 filename, lineno, func, mutex_name);
428 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
431 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 433 log_mutex_error(canlog,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
434 filename, lineno, func, mutex_name);
444 log_mutex_error(canlog,
"%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
445 filename, lineno, func, mutex_name);
455 log_mutex_error(canlog,
"%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
456 filename, lineno, func, mutex_name);
482 log_mutex_error(canlog,
"%s line %d (%s): Error releasing mutex: %s\n",
483 filename, lineno, func, strerror(res));
493 const char *cond_name,
ast_cond_t *
cond, pthread_condattr_t *cond_attr)
540 const char *cond_name,
const char *mutex_name,
548 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
550 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 552 log_mutex_error(canlog,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
553 filename, lineno, func, mutex_name);
563 log_mutex_error(canlog,
"%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
564 filename, lineno, func, mutex_name);
572 log_mutex_error(canlog,
"%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
573 filename, lineno, func, mutex_name);
592 log_mutex_error(canlog,
"%s line %d (%s): Error waiting on condition mutex '%s'\n",
593 filename, lineno, func, strerror(res));
613 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
615 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 617 log_mutex_error(canlog,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
618 filename, lineno, func, mutex_name);
628 log_mutex_error(canlog,
"%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
629 filename, lineno, func, mutex_name);
637 log_mutex_error(canlog,
"%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
638 filename, lineno, func, mutex_name);
656 if (res && (res != ETIMEDOUT)) {
657 log_mutex_error(canlog,
"%s line %d (%s): Error waiting on condition mutex '%s'\n",
658 filename, lineno, func, strerror(res));
672 pthread_rwlockattr_t attr;
675 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 677 int canlog = tracking && strcmp(filename,
"logger.c");
679 log_mutex_error(canlog,
"%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
680 filename, lineno, func, rwlock_name);
691 pthread_rwlockattr_init(&attr);
692 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP 693 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
695 res = pthread_rwlock_init(&t->
lock, &attr);
696 pthread_rwlockattr_destroy(&attr);
707 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
709 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 711 log_mutex_error(canlog,
"%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
712 filename, lineno, func, rwlock_name);
720 res = pthread_rwlock_destroy(&t->
lock);
724 log_mutex_error(canlog,
"%s line %d (%s): Error destroying rwlock %s: %s\n",
725 filename, lineno, func, rwlock_name, strerror(res));
727 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 732 lt->
file[0] = filename;
754 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
758 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 760 log_mutex_error(canlog,
"%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
761 filename, line, func, name);
772 pthread_t
self = pthread_self();
795 log_mutex_error(canlog,
"%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
796 filename, line, func, name);
806 res = pthread_rwlock_unlock(&t->
lock);
810 log_mutex_error(canlog,
"%s line %d (%s): Error releasing rwlock: %s\n",
811 filename, line, func, strerror(res));
825 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
848 #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS) 850 time_t seconds = time(
NULL);
851 time_t wait_time, reported_wait = 0;
853 res = pthread_rwlock_tryrdlock(&t->
lock);
855 wait_time = time(
NULL) - seconds;
856 if (wait_time > reported_wait && (wait_time % 5) == 0) {
857 log_mutex_error(canlog,
"%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
858 filename, line, func, (
int)wait_time, name);
872 reported_wait = wait_time;
876 }
while (res == EBUSY);
879 res = pthread_rwlock_rdlock(&t->
lock);
908 log_mutex_error(canlog,
"%s line %d (%s): Error obtaining read lock: %s\n",
909 filename, line, func, strerror(res));
923 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
946 #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS) 948 time_t seconds = time(
NULL);
949 time_t wait_time, reported_wait = 0;
951 res = pthread_rwlock_trywrlock(&t->
lock);
953 wait_time = time(
NULL) - seconds;
954 if (wait_time > reported_wait && (wait_time % 5) == 0) {
955 log_mutex_error(canlog,
"%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
956 filename, line, func, (
int)wait_time, name);
970 reported_wait = wait_time;
974 }
while (res == EBUSY);
977 res = pthread_rwlock_wrlock(&t->
lock);
1005 log_mutex_error(canlog,
"%s line %d (%s): Error obtaining write lock: %s\n",
1006 filename, line, func, strerror(res));
1015 const struct timespec *abs_timeout)
1019 #ifdef DEBUG_THREADS 1021 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
1044 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK 1045 res = pthread_rwlock_timedrdlock(&t->
lock, abs_timeout);
1048 struct timeval _now;
1050 if (!(res = pthread_rwlock_tryrdlock(&t->
lock))) {
1054 if (_now.tv_sec > abs_timeout->tv_sec || (_now.tv_sec == abs_timeout->tv_sec && _now.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1062 #ifdef DEBUG_THREADS 1087 log_mutex_error(canlog,
"%s line %d (%s): Error obtaining read lock: %s\n",
1088 filename, line, func, strerror(res));
1097 const struct timespec *abs_timeout)
1101 #ifdef DEBUG_THREADS 1103 int canlog = t->
flags.
tracking && strcmp(filename,
"logger.c");
1126 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK 1127 res = pthread_rwlock_timedwrlock(&t->
lock, abs_timeout);
1130 struct timeval _now;
1132 if (!(res = pthread_rwlock_trywrlock(&t->
lock))) {
1136 if (_now.tv_sec > abs_timeout->tv_sec || (_now.tv_sec == abs_timeout->tv_sec && _now.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1144 #ifdef DEBUG_THREADS 1169 log_mutex_error(canlog,
"%s line %d (%s): Error obtaining read lock: %s\n",
1170 filename, line, func, strerror(res));
1182 #ifdef DEBUG_THREADS 1206 res = pthread_rwlock_tryrdlock(&t->
lock);
1208 #ifdef DEBUG_THREADS 1232 #ifdef DEBUG_THREADS 1256 res = pthread_rwlock_trywrlock(&t->
lock);
1258 #ifdef DEBUG_THREADS void ast_std_free(void *ptr)
#define pthread_mutex_init
int64_t ast_mark(int, int start1_stop0)
struct ast_lock_track_flags flags
int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
const char * file[AST_MAX_REENTRANCY]
static struct ast_lock_track * ast_get_reentrancy(struct ast_lock_track **plt, struct ast_lock_track_flags *flags, int no_setup)
int __ast_rwlock_timedrdlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout)
#define pthread_cond_init
void ast_mark_lock_failed(void *lock_addr)
Mark the last lock as failed (trylock)
#define __AST_RWLOCK_INIT_VALUE
int __ast_rwlock_timedwrlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout)
int __ast_rwlock_rdlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
int __ast_cond_destroy(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond)
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int __ast_rwlock_wrlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
#define log_mutex_error(canlog,...)
int lineno[AST_MAX_REENTRANCY]
struct ast_bt backtrace[AST_MAX_REENTRANCY]
struct ast_lock_track * track
int __ast_cond_broadcast(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond)
pthread_cond_t ast_cond_t
int __ast_rwlock_tryrdlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
#define pthread_mutex_destroy
int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
int __ast_cond_init(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
Lock tracking information.
#define pthread_cond_wait
#define pthread_mutex_lock
#define pthread_cond_broadcast
volatile unsigned int setup
#define AST_PTHREADT_NULL
void ast_store_lock_info(enum ast_lock_type type, const char *filename, int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt)
Store lock info for the current thread.
static void delete_reentrancy_cs(struct ast_lock_track **plt)
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
static void ast_reentrancy_lock(struct ast_lock_track *lt)
struct ast_lock_track_flags flags
void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt)
remove lock info for the current thread
int __ast_rwlock_trywrlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
int __ast_cond_signal(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond)
void ast_suspend_lock_info(void *lock_addr)
int __ast_rwlock_unlock(const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
const char * func[AST_MAX_REENTRANCY]
static void ast_reentrancy_unlock(struct ast_lock_track *lt)
int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
void ast_mark_lock_acquired(void *lock_addr)
Mark the last lock as acquired.
static void restore_lock_tracking(struct ast_lock_track *lt, struct ast_lock_track *lt_saved)
void * ast_std_calloc(size_t nmemb, size_t size) attribute_malloc
void * addresses[AST_MAX_BT_FRAMES]
#define AST_MAX_REENTRANCY
#define pthread_cond_signal
Structure for rwlock and tracking information.
int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
pthread_t thread_id[AST_MAX_REENTRANCY]
int __ast_cond_timedwait(const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
static void __dump_backtrace(struct ast_bt *bt, int canlog)
int __ast_cond_wait(const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t)
pthread_mutex_t reentr_mutex
#define pthread_mutex_unlock
int __ast_pthread_mutex_init(int tracking, const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
#define pthread_cond_timedwait
void ast_restore_lock_info(void *lock_addr)
#define pthread_mutex_trylock
#define pthread_cond_destroy
int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
static ast_mutex_t reentrancy_lock
#define AST_MUTEX_DEFINE_STATIC(mutex)
Structure for mutex and tracking information.
#define ast_bt_get_addresses(bt)
struct ast_lock_track * track