4785a7636c6ba18abf46620524b2d594c819505d
[asterisk/asterisk.git] / include / asterisk / lock.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  * \brief Asterisk locking-related definitions:
21  * - ast_mutext_t, ast_rwlock_t and related functions;
22  * - atomic arithmetic instructions;
23  * - wrappers for channel locking.
24  *
25  * - See \ref LockDef
26  */
27
28 /*! \page LockDef Asterisk thread locking models
29  *
30  * This file provides different implementation of the functions,
31  * depending on the platform, the use of DEBUG_THREADS, and the way
32  * module-level mutexes are initialized.
33  *
34  *  - \b static: the mutex is assigned the value AST_MUTEX_INIT_VALUE
35  *        this is done at compile time, and is the way used on Linux.
36  *        This method is not applicable to all platforms e.g. when the
37  *        initialization needs that some code is run.
38  *
39  *  - \b through constructors: for each mutex, a constructor function is
40  *        defined, which then runs when the program (or the module)
41  *        starts. The problem with this approach is that there is a
42  *        lot of code duplication (a new block of code is created for
43  *        each mutex). Also, it does not prevent a user from declaring
44  *        a global mutex without going through the wrapper macros,
45  *        so sane programming practices are still required.
46  */
47
48 #ifndef _ASTERISK_LOCK_H
49 #define _ASTERISK_LOCK_H
50
51 #include <pthread.h>
52 #include <time.h>
53 #include <sys/param.h>
54 #ifdef HAVE_BKTR
55 #include <execinfo.h>
56 #endif
57
58 #ifndef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
59 #include "asterisk/time.h"
60 #endif
61
62 #include "asterisk/logger.h"
63
64 /* internal macro to profile mutexes. Only computes the delay on
65  * non-blocking calls.
66  */
67 #ifndef HAVE_MTX_PROFILE
68 #define __MTX_PROF(a)   return pthread_mutex_lock((a))
69 #else
70 #define __MTX_PROF(a)   do {                    \
71         int i;                                  \
72         /* profile only non-blocking events */  \
73         ast_mark(mtx_prof, 1);                  \
74         i = pthread_mutex_trylock((a));         \
75         ast_mark(mtx_prof, 0);                  \
76         if (!i)                                 \
77                 return i;                       \
78         else                                    \
79                 return pthread_mutex_lock((a)); \
80         } while (0)
81 #endif  /* HAVE_MTX_PROFILE */
82
83 #define AST_PTHREADT_NULL (pthread_t) -1
84 #define AST_PTHREADT_STOP (pthread_t) -2
85
86 #if defined(SOLARIS) || defined(BSD)
87 #define AST_MUTEX_INIT_W_CONSTRUCTORS
88 #endif /* SOLARIS || BSD */
89
90 /* Asterisk REQUIRES recursive (not error checking) mutexes
91    and will not run without them. */
92 #if defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(HAVE_PTHREAD_MUTEX_RECURSIVE_NP)
93 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
94 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE_NP
95 #else
96 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_MUTEX_INITIALIZER
97 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE
98 #endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
99
100 /*
101  * Definition of ast_mutex_t, ast_cont_d and related functions with/without debugging
102  * (search for DEBUG_THREADS to find the start/end of the sections).
103  *
104  * The non-debug code contains just wrappers for the corresponding pthread functions.
105  * The debug code tracks usage and tries to identify deadlock situations.
106  */
107 #ifdef DEBUG_THREADS
108
109 #define __ast_mutex_logger(...)  do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
110
111 #ifdef THREAD_CRASH
112 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
113 #else
114 #define DO_THREAD_CRASH do { } while (0)
115 #endif
116
117 #include <errno.h>
118
119 #ifdef HAVE_BKTR
120 #define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
121
122 #else
123 #define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
124 #endif
125
126 #define AST_MUTEX_INIT_VALUE { AST_LOCK_TRACK_INIT_VALUE, 1, PTHREAD_MUTEX_INIT_VALUE }
127 #define AST_MUTEX_INIT_VALUE_NOTRACKING { AST_LOCK_TRACK_INIT_VALUE, 0, PTHREAD_MUTEX_INIT_VALUE }
128
129 #define AST_MAX_REENTRANCY 10
130
131 struct ast_channel;
132
133 struct ast_lock_track {
134         const char *file[AST_MAX_REENTRANCY];
135         int lineno[AST_MAX_REENTRANCY];
136         int reentrancy;
137         const char *func[AST_MAX_REENTRANCY];
138         pthread_t thread[AST_MAX_REENTRANCY];
139 #ifdef HAVE_BKTR
140         struct ast_bt backtrace[AST_MAX_REENTRANCY];
141 #endif
142         pthread_mutex_t reentr_mutex;
143 };
144
145 struct ast_mutex_info {
146         /*! Track which thread holds this mutex */
147         struct ast_lock_track track;
148         unsigned int tracking:1;
149         pthread_mutex_t mutex;
150 };
151
152 typedef struct ast_mutex_info ast_mutex_t;
153
154 typedef pthread_cond_t ast_cond_t;
155
156 enum ast_lock_type {
157         AST_MUTEX,
158         AST_RDLOCK,
159         AST_WRLOCK,
160 };
161
162 /*!
163  * \brief Store lock info for the current thread
164  *
165  * This function gets called in ast_mutex_lock() and ast_mutex_trylock() so
166  * that information about this lock can be stored in this thread's
167  * lock info struct.  The lock is marked as pending as the thread is waiting
168  * on the lock.  ast_mark_lock_acquired() will mark it as held by this thread.
169  */
170 #if !defined(LOW_MEMORY)
171 #ifdef HAVE_BKTR
172 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
173         int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt);
174 #else
175 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
176         int line_num, const char *func, const char *lock_name, void *lock_addr);
177 #endif /* HAVE_BKTR */
178
179 #else
180
181 #ifdef HAVE_BKTR
182 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS,BUD)
183 #else
184 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
185 #endif /* HAVE_BKTR */
186 #endif /* !defined(LOW_MEMORY) */
187
188 /*!
189  * \brief Mark the last lock as acquired
190  */
191 #if !defined(LOW_MEMORY)
192 void ast_mark_lock_acquired(void *lock_addr);
193 #else
194 #define ast_mark_lock_acquired(ignore)
195 #endif
196
197 /*!
198  * \brief Mark the last lock as failed (trylock)
199  */
200 #if !defined(LOW_MEMORY)
201 void ast_mark_lock_failed(void *lock_addr);
202 #else
203 #define ast_mark_lock_failed(ignore)
204 #endif
205
206 /*!
207  * \brief remove lock info for the current thread
208  *
209  * this gets called by ast_mutex_unlock so that information on the lock can
210  * be removed from the current thread's lock info struct.
211  */
212 #if !defined(LOW_MEMORY)
213 #ifdef HAVE_BKTR
214 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt);
215 #else
216 void ast_remove_lock_info(void *lock_addr);
217 #endif /* HAVE_BKTR */
218 #else
219 #ifdef HAVE_BKTR
220 #define ast_remove_lock_info(ignore,me)
221 #else
222 #define ast_remove_lock_info(ignore)
223 #endif /* HAVE_BKTR */
224 #endif /* !defined(LOW_MEMORY) */
225
226 #ifdef HAVE_BKTR
227 static inline void __dump_backtrace(struct ast_bt *bt, int canlog)
228 {
229         char **strings;
230
231         ssize_t i;
232
233         strings = backtrace_symbols(bt->addresses, bt->num_frames);
234
235         for (i = 0; i < bt->num_frames; i++)
236                 __ast_mutex_logger("%s\n", strings[i]);
237
238         free(strings);
239 }
240 #endif
241
242 /*!
243  * \brief log info for the current lock with ast_log().
244  *
245  * this function would be mostly for debug. If you come across a lock
246  * that is unexpectedly but momentarily locked, and you wonder who
247  * are fighting with for the lock, this routine could be called, IF
248  * you have the thread debugging stuff turned on.
249  * \param this_lock_addr lock address to return lock information
250  * \since 1.6.1
251  */
252 void log_show_lock(void *this_lock_addr);
253
254 /*!
255  * \brief retrieve lock info for the specified mutex
256  *
257  * this gets called during deadlock avoidance, so that the information may
258  * be preserved as to what location originally acquired the lock.
259  */
260 #if !defined(LOW_MEMORY)
261 int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, int *lineno, char *func, size_t func_size, char *mutex_name, size_t mutex_name_size);
262 #else
263 #define ast_find_lock_info(a,b,c,d,e,f,g,h) -1
264 #endif
265
266 /*!
267  * \brief Unlock a lock briefly
268  *
269  * used during deadlock avoidance, to preserve the original location where
270  * a lock was originally acquired.
271  */
272 #define CHANNEL_DEADLOCK_AVOIDANCE(chan) \
273         do { \
274                 char __filename[80], __func[80], __mutex_name[80]; \
275                 int __lineno; \
276                 int __res = ast_find_lock_info(ao2_object_get_lockaddr(chan), __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
277                 ast_channel_unlock(chan); \
278                 usleep(1); \
279                 if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
280                         ast_channel_lock(chan); \
281                 } else { \
282                         __ao2_lock(chan, __filename, __func, __lineno, __mutex_name); \
283                 } \
284         } while (0)
285
286 #define DEADLOCK_AVOIDANCE(lock) \
287         do { \
288                 char __filename[80], __func[80], __mutex_name[80]; \
289                 int __lineno; \
290                 int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
291                 ast_mutex_unlock(lock); \
292                 usleep(1); \
293                 if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
294                         ast_mutex_lock(lock); \
295                 } else { \
296                         __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
297                 } \
298         } while (0)
299
300 /*!
301  * \brief Deadlock avoidance unlock
302  *
303  * In certain deadlock avoidance scenarios, there is more than one lock to be
304  * unlocked and relocked.  Therefore, this pair of macros is provided for that
305  * purpose.  Note that every DLA_UNLOCK _MUST_ be paired with a matching
306  * DLA_LOCK.  The intent of this pair of macros is to be used around another
307  * set of deadlock avoidance code, mainly CHANNEL_DEADLOCK_AVOIDANCE, as the
308  * locking order specifies that we may safely lock a channel, followed by its
309  * pvt, with no worries about a deadlock.  In any other scenario, this macro
310  * may not be safe to use.
311  */
312 #define DLA_UNLOCK(lock) \
313         do { \
314                 char __filename[80], __func[80], __mutex_name[80]; \
315                 int __lineno; \
316                 int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
317                 ast_mutex_unlock(lock);
318
319 /*!
320  * \brief Deadlock avoidance lock
321  *
322  * In certain deadlock avoidance scenarios, there is more than one lock to be
323  * unlocked and relocked.  Therefore, this pair of macros is provided for that
324  * purpose.  Note that every DLA_UNLOCK _MUST_ be paired with a matching
325  * DLA_LOCK.  The intent of this pair of macros is to be used around another
326  * set of deadlock avoidance code, mainly CHANNEL_DEADLOCK_AVOIDANCE, as the
327  * locking order specifies that we may safely lock a channel, followed by its
328  * pvt, with no worries about a deadlock.  In any other scenario, this macro
329  * may not be safe to use.
330  */
331 #define DLA_LOCK(lock) \
332                 if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
333                         ast_mutex_lock(lock); \
334                 } else { \
335                         __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
336                 } \
337         } while (0)
338
339 static inline void ast_reentrancy_lock(struct ast_lock_track *lt)
340 {
341         pthread_mutex_lock(&lt->reentr_mutex);
342 }
343
344 static inline void ast_reentrancy_unlock(struct ast_lock_track *lt)
345 {
346         pthread_mutex_unlock(&lt->reentr_mutex);
347 }
348
349 static inline void ast_reentrancy_init(struct ast_lock_track *lt)
350 {
351         int i;
352         pthread_mutexattr_t reentr_attr;
353
354         for (i = 0; i < AST_MAX_REENTRANCY; i++) {
355                 lt->file[i] = NULL;
356                 lt->lineno[i] = 0;
357                 lt->func[i] = NULL;
358                 lt->thread[i] = 0;
359 #ifdef HAVE_BKTR
360                 memset(&lt->backtrace[i], 0, sizeof(lt->backtrace[i]));
361 #endif
362         }
363
364         lt->reentrancy = 0;
365
366         pthread_mutexattr_init(&reentr_attr);
367         pthread_mutexattr_settype(&reentr_attr, AST_MUTEX_KIND);
368         pthread_mutex_init(&lt->reentr_mutex, &reentr_attr);
369         pthread_mutexattr_destroy(&reentr_attr);
370 }
371
372 static inline void delete_reentrancy_cs(struct ast_lock_track *lt)
373 {
374         pthread_mutex_destroy(&lt->reentr_mutex);
375 }
376
377 static inline int __ast_pthread_mutex_init(int tracking, const char *filename, int lineno, const char *func,
378                                                 const char *mutex_name, ast_mutex_t *t)
379 {
380         int res;
381         pthread_mutexattr_t  attr;
382
383 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
384
385         if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
386 /*
387                 int canlog = strcmp(filename, "logger.c") & track;
388                 __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n",
389                                    filename, lineno, func, mutex_name);
390                 DO_THREAD_CRASH;
391 */
392                 return 0;
393         }
394
395 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
396
397         ast_reentrancy_init(&t->track);
398         t->tracking = tracking;
399
400         pthread_mutexattr_init(&attr);
401         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
402
403         res = pthread_mutex_init(&t->mutex, &attr);
404         pthread_mutexattr_destroy(&attr);
405         return res;
406 }
407
408 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
409 #define ast_mutex_init_notracking(pmutex) \
410         __ast_pthread_mutex_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
411
412 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
413                                                 const char *mutex_name, ast_mutex_t *t)
414 {
415         int res;
416         struct ast_lock_track *lt;
417         int canlog = strcmp(filename, "logger.c") & t->tracking;
418
419 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
420         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
421                 /* Don't try to uninitialize non initialized mutex
422                  * This may no effect on linux
423                  * And always ganerate core on *BSD with
424                  * linked libpthread
425                  * This not error condition if the mutex created on the fly.
426                  */
427                 __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
428                                    filename, lineno, func, mutex_name);
429                 return 0;
430         }
431 #endif
432
433         lt = &t->track;
434
435         res = pthread_mutex_trylock(&t->mutex);
436         switch (res) {
437         case 0:
438                 pthread_mutex_unlock(&t->mutex);
439                 break;
440         case EINVAL:
441                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
442                                   filename, lineno, func, mutex_name);
443                 break;
444         case EBUSY:
445                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
446                                    filename, lineno, func, mutex_name);
447                 ast_reentrancy_lock(lt);
448                 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
449                             lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
450 #ifdef HAVE_BKTR
451                 __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
452 #endif
453                 ast_reentrancy_unlock(lt);
454                 break;
455         }
456
457
458         if ((res = pthread_mutex_destroy(&t->mutex))) {
459                 __ast_mutex_logger("%s line %d (%s): Error destroying mutex %s: %s\n",
460                                    filename, lineno, func, mutex_name, strerror(res));
461         }
462 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
463         else
464                 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
465 #endif
466         ast_reentrancy_lock(lt);
467         lt->file[0] = filename;
468         lt->lineno[0] = lineno;
469         lt->func[0] = func;
470         lt->reentrancy = 0;
471         lt->thread[0] = 0;
472 #ifdef HAVE_BKTR
473         memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
474 #endif
475         ast_reentrancy_unlock(lt);
476         delete_reentrancy_cs(lt);
477
478         return res;
479 }
480
481 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
482                                            const char* mutex_name, ast_mutex_t *t)
483 {
484         int res;
485         struct ast_lock_track *lt = &t->track;
486         int canlog = strcmp(filename, "logger.c") & t->tracking;
487 #ifdef HAVE_BKTR
488         struct ast_bt *bt = NULL;
489 #endif
490
491 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
492         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
493                 /* Don't warn abount uninitialized mutex.
494                  * Simple try to initialize it.
495                  * May be not needed in linux system.
496                  */
497                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
498                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
499                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
500                                          filename, lineno, func, mutex_name);
501                         return res;
502                 }
503         }
504 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
505
506         if (t->tracking) {
507 #ifdef HAVE_BKTR
508                 ast_reentrancy_lock(lt);
509                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
510                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
511                         bt = &lt->backtrace[lt->reentrancy];
512                 }
513                 ast_reentrancy_unlock(lt);
514                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
515 #else
516                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
517 #endif
518         }
519
520 #ifdef DETECT_DEADLOCKS
521         {
522                 time_t seconds = time(NULL);
523                 time_t wait_time, reported_wait = 0;
524                 do {
525 #ifdef  HAVE_MTX_PROFILE
526                         ast_mark(mtx_prof, 1);
527 #endif
528                         res = pthread_mutex_trylock(&t->mutex);
529 #ifdef  HAVE_MTX_PROFILE
530                         ast_mark(mtx_prof, 0);
531 #endif
532                         if (res == EBUSY) {
533                                 wait_time = time(NULL) - seconds;
534                                 if (wait_time > reported_wait && (wait_time % 5) == 0) {
535                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
536                                                            filename, lineno, func, (int) wait_time, mutex_name);
537                                         ast_reentrancy_lock(lt);
538 #ifdef HAVE_BKTR
539                                         __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
540 #endif
541                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
542                                                            lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
543                                                            lt->func[lt->reentrancy-1], mutex_name);
544 #ifdef HAVE_BKTR
545                                         __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
546 #endif
547                                         ast_reentrancy_unlock(lt);
548                                         reported_wait = wait_time;
549                                 }
550                                 usleep(200);
551                         }
552                 } while (res == EBUSY);
553         }
554 #else
555 #ifdef  HAVE_MTX_PROFILE
556         ast_mark(mtx_prof, 1);
557         res = pthread_mutex_trylock(&t->mutex);
558         ast_mark(mtx_prof, 0);
559         if (res)
560 #endif
561         res = pthread_mutex_lock(&t->mutex);
562 #endif /* DETECT_DEADLOCKS */
563
564         if (!res) {
565                 ast_reentrancy_lock(lt);
566                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
567                         lt->file[lt->reentrancy] = filename;
568                         lt->lineno[lt->reentrancy] = lineno;
569                         lt->func[lt->reentrancy] = func;
570                         lt->thread[lt->reentrancy] = pthread_self();
571                         lt->reentrancy++;
572                 } else {
573                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
574                                                            filename, lineno, func, mutex_name);
575                 }
576                 ast_reentrancy_unlock(lt);
577                 if (t->tracking) {
578                         ast_mark_lock_acquired(t);
579                 }
580         } else {
581 #ifdef HAVE_BKTR
582                 if (lt->reentrancy) {
583                         ast_reentrancy_lock(lt);
584                         bt = &lt->backtrace[lt->reentrancy-1];
585                         ast_reentrancy_unlock(lt);
586                 } else {
587                         bt = NULL;
588                 }
589                 if (t->tracking) {
590                         ast_remove_lock_info(t, bt);
591                 }
592 #else
593                 if (t->tracking) {
594                         ast_remove_lock_info(t);
595                 }
596 #endif
597                 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
598                                    filename, lineno, func, strerror(res));
599                 DO_THREAD_CRASH;
600         }
601
602         return res;
603 }
604
605 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
606                                               const char* mutex_name, ast_mutex_t *t)
607 {
608         int res;
609         struct ast_lock_track *lt= &t->track;
610         int canlog = strcmp(filename, "logger.c") & t->tracking;
611 #ifdef HAVE_BKTR
612         struct ast_bt *bt = NULL;
613 #endif
614
615 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
616         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
617                 /* Don't warn abount uninitialized mutex.
618                  * Simple try to initialize it.
619                  * May be not needed in linux system.
620                  */
621                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
622                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
623                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
624                                          filename, lineno, func, mutex_name);
625                         return res;
626                 }
627         }
628 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
629
630         if (t->tracking) {
631 #ifdef HAVE_BKTR
632                 ast_reentrancy_lock(lt);
633                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
634                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
635                         bt = &lt->backtrace[lt->reentrancy];
636                 }
637                 ast_reentrancy_unlock(lt);
638                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
639 #else
640                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
641 #endif
642         }
643
644         if (!(res = pthread_mutex_trylock(&t->mutex))) {
645                 ast_reentrancy_lock(lt);
646                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
647                         lt->file[lt->reentrancy] = filename;
648                         lt->lineno[lt->reentrancy] = lineno;
649                         lt->func[lt->reentrancy] = func;
650                         lt->thread[lt->reentrancy] = pthread_self();
651                         lt->reentrancy++;
652                 } else {
653                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
654                                            filename, lineno, func, mutex_name);
655                 }
656                 ast_reentrancy_unlock(lt);
657                 if (t->tracking) {
658                         ast_mark_lock_acquired(t);
659                 }
660         } else if (t->tracking) {
661                 ast_mark_lock_failed(t);
662         }
663
664         return res;
665 }
666
667 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
668                                              const char *mutex_name, ast_mutex_t *t)
669 {
670         int res;
671         struct ast_lock_track *lt = &t->track;
672         int canlog = strcmp(filename, "logger.c") & t->tracking;
673 #ifdef HAVE_BKTR
674         struct ast_bt *bt = NULL;
675 #endif
676
677 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
678         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
679                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
680                                    filename, lineno, func, mutex_name);
681                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
682                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
683                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
684                                          filename, lineno, func, mutex_name);
685                 }
686                 return res;
687         }
688 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
689
690         ast_reentrancy_lock(lt);
691         if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
692                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
693                                    filename, lineno, func, mutex_name);
694                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
695                                    lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
696 #ifdef HAVE_BKTR
697                 __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
698 #endif
699                 DO_THREAD_CRASH;
700         }
701
702         if (--lt->reentrancy < 0) {
703                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
704                                    filename, lineno, func, mutex_name);
705                 lt->reentrancy = 0;
706         }
707
708         if (lt->reentrancy < AST_MAX_REENTRANCY) {
709                 lt->file[lt->reentrancy] = NULL;
710                 lt->lineno[lt->reentrancy] = 0;
711                 lt->func[lt->reentrancy] = NULL;
712                 lt->thread[lt->reentrancy] = 0;
713         }
714
715 #ifdef HAVE_BKTR
716         if (lt->reentrancy) {
717                 bt = &lt->backtrace[lt->reentrancy - 1];
718         }
719 #endif
720         ast_reentrancy_unlock(lt);
721
722         if (t->tracking) {
723 #ifdef HAVE_BKTR
724                 ast_remove_lock_info(t, bt);
725 #else
726                 ast_remove_lock_info(t);
727 #endif
728         }
729
730         if ((res = pthread_mutex_unlock(&t->mutex))) {
731                 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
732                                    filename, lineno, func, strerror(res));
733                 DO_THREAD_CRASH;
734         }
735
736         return res;
737 }
738
739 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
740                                   const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
741 {
742         return pthread_cond_init(cond, cond_attr);
743 }
744
745 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
746                                     const char *cond_name, ast_cond_t *cond)
747 {
748         return pthread_cond_signal(cond);
749 }
750
751 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
752                                        const char *cond_name, ast_cond_t *cond)
753 {
754         return pthread_cond_broadcast(cond);
755 }
756
757 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
758                                      const char *cond_name, ast_cond_t *cond)
759 {
760         return pthread_cond_destroy(cond);
761 }
762
763 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
764                                   const char *cond_name, const char *mutex_name,
765                                   ast_cond_t *cond, ast_mutex_t *t)
766 {
767         int res;
768         struct ast_lock_track *lt= &t->track;
769         int canlog = strcmp(filename, "logger.c") & t->tracking;
770 #ifdef HAVE_BKTR
771         struct ast_bt *bt = NULL;
772 #endif
773
774 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
775         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
776                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
777                                    filename, lineno, func, mutex_name);
778                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
779                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
780                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
781                                          filename, lineno, func, mutex_name);
782                 }
783                 return res;
784         }
785 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
786
787         ast_reentrancy_lock(lt);
788         if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
789                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
790                                    filename, lineno, func, mutex_name);
791                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
792                                    lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
793 #ifdef HAVE_BKTR
794                 __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
795 #endif
796                 DO_THREAD_CRASH;
797         }
798
799         if (--lt->reentrancy < 0) {
800                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
801                                    filename, lineno, func, mutex_name);
802                 lt->reentrancy = 0;
803         }
804
805         if (lt->reentrancy < AST_MAX_REENTRANCY) {
806                 lt->file[lt->reentrancy] = NULL;
807                 lt->lineno[lt->reentrancy] = 0;
808                 lt->func[lt->reentrancy] = NULL;
809                 lt->thread[lt->reentrancy] = 0;
810         }
811
812 #ifdef HAVE_BKTR
813         if (lt->reentrancy) {
814                 bt = &lt->backtrace[lt->reentrancy - 1];
815         }
816 #endif
817         ast_reentrancy_unlock(lt);
818
819         if (t->tracking) {
820 #ifdef HAVE_BKTR
821                 ast_remove_lock_info(t, bt);
822 #else
823                 ast_remove_lock_info(t);
824 #endif
825         }
826
827         if ((res = pthread_cond_wait(cond, &t->mutex))) {
828                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
829                                    filename, lineno, func, strerror(res));
830                 DO_THREAD_CRASH;
831         } else {
832                 ast_reentrancy_lock(lt);
833                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
834                         lt->file[lt->reentrancy] = filename;
835                         lt->lineno[lt->reentrancy] = lineno;
836                         lt->func[lt->reentrancy] = func;
837                         lt->thread[lt->reentrancy] = pthread_self();
838 #ifdef HAVE_BKTR
839                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
840                         bt = &lt->backtrace[lt->reentrancy];
841 #endif
842                         lt->reentrancy++;
843                 } else {
844                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
845                                                            filename, lineno, func, mutex_name);
846                 }
847                 ast_reentrancy_unlock(lt);
848
849                 if (t->tracking) {
850 #ifdef HAVE_BKTR
851                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
852 #else
853                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
854 #endif
855                 }
856         }
857
858         return res;
859 }
860
861 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
862                                        const char *cond_name, const char *mutex_name, ast_cond_t *cond,
863                                        ast_mutex_t *t, const struct timespec *abstime)
864 {
865         int res;
866         struct ast_lock_track *lt = &t->track;
867         int canlog = strcmp(filename, "logger.c") & t->tracking;
868 #ifdef HAVE_BKTR
869         struct ast_bt *bt = NULL;
870 #endif
871
872 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
873         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
874                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
875                                    filename, lineno, func, mutex_name);
876                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
877                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
878                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
879                                          filename, lineno, func, mutex_name);
880                 }
881                 return res;
882         }
883 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
884
885         ast_reentrancy_lock(lt);
886         if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
887                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
888                                    filename, lineno, func, mutex_name);
889                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
890                                    lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
891 #ifdef HAVE_BKTR
892                 __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
893 #endif
894                 DO_THREAD_CRASH;
895         }
896
897         if (--lt->reentrancy < 0) {
898                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
899                                    filename, lineno, func, mutex_name);
900                 lt->reentrancy = 0;
901         }
902
903         if (lt->reentrancy < AST_MAX_REENTRANCY) {
904                 lt->file[lt->reentrancy] = NULL;
905                 lt->lineno[lt->reentrancy] = 0;
906                 lt->func[lt->reentrancy] = NULL;
907                 lt->thread[lt->reentrancy] = 0;
908         }
909 #ifdef HAVE_BKTR
910         if (lt->reentrancy) {
911                 bt = &lt->backtrace[lt->reentrancy - 1];
912         }
913 #endif
914         ast_reentrancy_unlock(lt);
915
916         if (t->tracking) {
917 #ifdef HAVE_BKTR
918                 ast_remove_lock_info(t, bt);
919 #else
920                 ast_remove_lock_info(t);
921 #endif
922         }
923
924         if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
925                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
926                                    filename, lineno, func, strerror(res));
927                 DO_THREAD_CRASH;
928         } else {
929                 ast_reentrancy_lock(lt);
930                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
931                         lt->file[lt->reentrancy] = filename;
932                         lt->lineno[lt->reentrancy] = lineno;
933                         lt->func[lt->reentrancy] = func;
934                         lt->thread[lt->reentrancy] = pthread_self();
935 #ifdef HAVE_BKTR
936                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
937                         bt = &lt->backtrace[lt->reentrancy];
938 #endif
939                         lt->reentrancy++;
940                 } else {
941                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
942                                                            filename, lineno, func, mutex_name);
943                 }
944                 ast_reentrancy_unlock(lt);
945
946                 if (t->tracking) {
947 #ifdef HAVE_BKTR
948                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
949 #else
950                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
951 #endif
952                 }
953         }
954
955         return res;
956 }
957
958 #define ast_mutex_destroy(a)                    __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
959 #define ast_mutex_lock(a)                       __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
960 #define ast_mutex_unlock(a)                     __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
961 #define ast_mutex_trylock(a)                    __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
962 #define ast_cond_init(cond, attr)               __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
963 #define ast_cond_destroy(cond)                  __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
964 #define ast_cond_signal(cond)                   __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
965 #define ast_cond_broadcast(cond)                __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
966 #define ast_cond_wait(cond, mutex)              __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
967 #define ast_cond_timedwait(cond, mutex, time)   __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
968
969 struct ast_rwlock_info {
970         /*! Track which thread holds this lock */
971         struct ast_lock_track track;
972         unsigned int tracking:1;
973         pthread_rwlock_t lock;
974 };
975
976 typedef struct ast_rwlock_info ast_rwlock_t;
977
978 /*!
979  * \brief wrapper for rwlock with tracking enabled
980  * \return 0 on success, non zero for error
981  * \since 1.6.1
982  */
983 #define ast_rwlock_init(rwlock) __ast_rwlock_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
984
985 /*!
986  * \brief wrapper for ast_rwlock_init with tracking disabled
987  * \return 0 on success, non zero for error
988  * \since 1.6.1
989  */
990 #define ast_rwlock_init_notracking(rwlock) __ast_rwlock_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
991
992 #define ast_rwlock_destroy(rwlock)      __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
993 #define ast_rwlock_unlock(a)            _ast_rwlock_unlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
994 #define ast_rwlock_rdlock(a)            _ast_rwlock_rdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
995 #define ast_rwlock_wrlock(a)            _ast_rwlock_wrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
996 #define ast_rwlock_tryrdlock(a)         _ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
997 #define ast_rwlock_trywrlock(a) _ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
998
999
1000 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
1001 #define __AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
1002 #else  /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
1003 #define __AST_RWLOCK_INIT_VALUE {0}
1004 #endif /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
1005
1006 #define AST_RWLOCK_INIT_VALUE \
1007         { AST_LOCK_TRACK_INIT_VALUE, 1, __AST_RWLOCK_INIT_VALUE }
1008 #define AST_RWLOCK_INIT_VALUE_NOTRACKING \
1009         { AST_LOCK_TRACK_INIT_VALUE, 0, __AST_RWLOCK_INIT_VALUE }
1010
1011 static inline int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
1012 {
1013         int res;
1014         struct ast_lock_track *lt= &t->track;
1015         pthread_rwlockattr_t attr;
1016
1017 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1018         int canlog = strcmp(filename, "logger.c") & t->tracking;
1019
1020         if (t->lock != ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1021                 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
1022                                 filename, lineno, func, rwlock_name);
1023                 return 0;
1024         }
1025 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1026
1027         ast_reentrancy_init(lt);
1028         t->tracking = tracking;
1029         pthread_rwlockattr_init(&attr);
1030
1031 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
1032         pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
1033 #endif
1034
1035         res = pthread_rwlock_init(&t->lock, &attr);
1036         pthread_rwlockattr_destroy(&attr);
1037         return res;
1038 }
1039
1040 static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
1041 {
1042         int res;
1043         struct ast_lock_track *lt = &t->track;
1044         int canlog = strcmp(filename, "logger.c") & t->tracking;
1045
1046 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1047         if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1048                 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
1049                                    filename, lineno, func, rwlock_name);
1050                 return 0;
1051         }
1052 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1053
1054         if ((res = pthread_rwlock_destroy(&t->lock))) {
1055                 __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
1056                                 filename, lineno, func, rwlock_name, strerror(res));
1057         }
1058         ast_reentrancy_lock(lt);
1059         lt->file[0] = filename;
1060         lt->lineno[0] = lineno;
1061         lt->func[0] = func;
1062         lt->reentrancy = 0;
1063         lt->thread[0] = 0;
1064 #ifdef HAVE_BKTR
1065         memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
1066 #endif
1067         ast_reentrancy_unlock(lt);
1068         delete_reentrancy_cs(lt);
1069
1070         return res;
1071 }
1072
1073 static inline int _ast_rwlock_unlock(ast_rwlock_t *t, const char *name,
1074         const char *filename, int line, const char *func)
1075 {
1076         int res;
1077         struct ast_lock_track *lt = &t->track;
1078         int canlog = strcmp(filename, "logger.c") & t->tracking;
1079 #ifdef HAVE_BKTR
1080         struct ast_bt *bt = NULL;
1081 #endif
1082         int lock_found = 0;
1083
1084
1085 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1086         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1087                 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
1088                                    filename, line, func, name);
1089                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1090                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1091                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1092                                         filename, line, func, name);
1093                 }
1094                 return res;
1095         }
1096 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1097
1098         ast_reentrancy_lock(lt);
1099         if (lt->reentrancy) {
1100                 int i;
1101                 pthread_t self = pthread_self();
1102                 for (i = lt->reentrancy - 1; i >= 0; --i) {
1103                         if (lt->thread[i] == self) {
1104                                 lock_found = 1;
1105                                 if (i != lt->reentrancy - 1) {
1106                                         lt->file[i] = lt->file[lt->reentrancy - 1];
1107                                         lt->lineno[i] = lt->lineno[lt->reentrancy - 1];
1108                                         lt->func[i] = lt->func[lt->reentrancy - 1];
1109                                         lt->thread[i] = lt->thread[lt->reentrancy - 1];
1110                                 }
1111 #ifdef HAVE_BKTR
1112                                 bt = &lt->backtrace[i];
1113 #endif
1114                                 lt->file[lt->reentrancy - 1] = NULL;
1115                                 lt->lineno[lt->reentrancy - 1] = 0;
1116                                 lt->func[lt->reentrancy - 1] = NULL;
1117                                 lt->thread[lt->reentrancy - 1] = AST_PTHREADT_NULL;
1118                                 break;
1119                         }
1120                 }
1121         }
1122
1123         if (lock_found && --lt->reentrancy < 0) {
1124                 __ast_mutex_logger("%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
1125                                 filename, line, func, name);
1126                 lt->reentrancy = 0;
1127         }
1128
1129         ast_reentrancy_unlock(lt);
1130
1131         if (t->tracking) {
1132 #ifdef HAVE_BKTR
1133                 ast_remove_lock_info(t, bt);
1134 #else
1135                 ast_remove_lock_info(t);
1136 #endif
1137         }
1138
1139         if ((res = pthread_rwlock_unlock(&t->lock))) {
1140                 __ast_mutex_logger("%s line %d (%s): Error releasing rwlock: %s\n",
1141                                 filename, line, func, strerror(res));
1142                 DO_THREAD_CRASH;
1143         }
1144
1145         return res;
1146 }
1147
1148 static inline int _ast_rwlock_rdlock(ast_rwlock_t *t, const char *name,
1149         const char *filename, int line, const char *func)
1150 {
1151         int res;
1152         struct ast_lock_track *lt = &t->track;
1153         int canlog = strcmp(filename, "logger.c") & t->tracking;
1154 #ifdef HAVE_BKTR
1155         struct ast_bt *bt = NULL;
1156 #endif
1157
1158 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1159         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1160                  /* Don't warn abount uninitialized lock.
1161                   * Simple try to initialize it.
1162                   * May be not needed in linux system.
1163                   */
1164                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1165                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1166                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1167                                         filename, line, func, name);
1168                         return res;
1169                 }
1170         }
1171 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1172
1173         if (t->tracking) {
1174 #ifdef HAVE_BKTR
1175                 ast_reentrancy_lock(lt);
1176                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1177                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1178                         bt = &lt->backtrace[lt->reentrancy];
1179                 }
1180                 ast_reentrancy_unlock(lt);
1181                 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
1182 #else
1183                 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
1184 #endif
1185         }
1186
1187 #ifdef DETECT_DEADLOCKS
1188         {
1189                 time_t seconds = time(NULL);
1190                 time_t wait_time, reported_wait = 0;
1191                 do {
1192                         res = pthread_rwlock_tryrdlock(&t->lock);
1193                         if (res == EBUSY) {
1194                                 wait_time = time(NULL) - seconds;
1195                                 if (wait_time > reported_wait && (wait_time % 5) == 0) {
1196                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
1197                                                 filename, line, func, (int)wait_time, name);
1198                                         ast_reentrancy_lock(lt);
1199 #ifdef HAVE_BKTR
1200                                         __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
1201 #endif
1202                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked  here.\n",
1203                                                         lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
1204                                                         lt->func[lt->reentrancy-1], name);
1205 #ifdef HAVE_BKTR
1206                                         __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
1207 #endif
1208                                         ast_reentrancy_unlock(lt);
1209                                         reported_wait = wait_time;
1210                                 }
1211                                 usleep(200);
1212                         }
1213                 } while (res == EBUSY);
1214         }
1215 #else /* !DETECT_DEADLOCKS */
1216         res = pthread_rwlock_rdlock(&t->lock);
1217 #endif /* !DETECT_DEADLOCKS */
1218
1219         if (!res) {
1220                 ast_reentrancy_lock(lt);
1221                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1222                         lt->file[lt->reentrancy] = filename;
1223                         lt->lineno[lt->reentrancy] = line;
1224                         lt->func[lt->reentrancy] = func;
1225                         lt->thread[lt->reentrancy] = pthread_self();
1226                         lt->reentrancy++;
1227                 }
1228                 ast_reentrancy_unlock(lt);
1229                 if (t->tracking) {
1230                         ast_mark_lock_acquired(t);
1231                 }
1232         } else {
1233 #ifdef HAVE_BKTR
1234                 if (lt->reentrancy) {
1235                         ast_reentrancy_lock(lt);
1236                         bt = &lt->backtrace[lt->reentrancy-1];
1237                         ast_reentrancy_unlock(lt);
1238                 } else {
1239                         bt = NULL;
1240                 }
1241                 if (t->tracking) {
1242                         ast_remove_lock_info(t, bt);
1243                 }
1244 #else
1245                 if (t->tracking) {
1246                         ast_remove_lock_info(t);
1247                 }
1248 #endif
1249                 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
1250                                 filename, line, func, strerror(res));
1251                 DO_THREAD_CRASH;
1252         }
1253         return res;
1254 }
1255
1256 static inline int _ast_rwlock_wrlock(ast_rwlock_t *t, const char *name,
1257         const char *filename, int line, const char *func)
1258 {
1259         int res;
1260         struct ast_lock_track *lt = &t->track;
1261         int canlog = strcmp(filename, "logger.c") & t->tracking;
1262 #ifdef HAVE_BKTR
1263         struct ast_bt *bt = NULL;
1264 #endif
1265
1266 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1267         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1268                  /* Don't warn abount uninitialized lock.
1269                   * Simple try to initialize it.
1270                   * May be not needed in linux system.
1271                   */
1272                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1273                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1274                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1275                                         filename, line, func, name);
1276                         return res;
1277                 }
1278         }
1279 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1280
1281         if (t->tracking) {
1282 #ifdef HAVE_BKTR
1283                 ast_reentrancy_lock(lt);
1284                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1285                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1286                         bt = &lt->backtrace[lt->reentrancy];
1287                 }
1288                 ast_reentrancy_unlock(lt);
1289                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1290 #else
1291                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
1292 #endif
1293         }
1294 #ifdef DETECT_DEADLOCKS
1295         {
1296                 time_t seconds = time(NULL);
1297                 time_t wait_time, reported_wait = 0;
1298                 do {
1299                         res = pthread_rwlock_trywrlock(&t->lock);
1300                         if (res == EBUSY) {
1301                                 wait_time = time(NULL) - seconds;
1302                                 if (wait_time > reported_wait && (wait_time % 5) == 0) {
1303                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
1304                                                 filename, line, func, (int)wait_time, name);
1305                                         ast_reentrancy_lock(lt);
1306 #ifdef HAVE_BKTR
1307                                         __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
1308 #endif
1309                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked  here.\n",
1310                                                         lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
1311                                                         lt->func[lt->reentrancy-1], name);
1312 #ifdef HAVE_BKTR
1313                                         __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
1314 #endif
1315                                         ast_reentrancy_unlock(lt);
1316                                         reported_wait = wait_time;
1317                                 }
1318                                 usleep(200);
1319                         }
1320                 } while (res == EBUSY);
1321         }
1322 #else /* !DETECT_DEADLOCKS */
1323         res = pthread_rwlock_wrlock(&t->lock);
1324 #endif /* !DETECT_DEADLOCKS */
1325
1326         if (!res) {
1327                 ast_reentrancy_lock(lt);
1328                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1329                         lt->file[lt->reentrancy] = filename;
1330                         lt->lineno[lt->reentrancy] = line;
1331                         lt->func[lt->reentrancy] = func;
1332                         lt->thread[lt->reentrancy] = pthread_self();
1333                         lt->reentrancy++;
1334                 }
1335                 ast_reentrancy_unlock(lt);
1336                 if (t->tracking) {
1337                         ast_mark_lock_acquired(t);
1338                 }
1339         } else {
1340 #ifdef HAVE_BKTR
1341                 if (lt->reentrancy) {
1342                         ast_reentrancy_lock(lt);
1343                         bt = &lt->backtrace[lt->reentrancy-1];
1344                         ast_reentrancy_unlock(lt);
1345                 } else {
1346                         bt = NULL;
1347                 }
1348                 if (t->tracking) {
1349                         ast_remove_lock_info(t, bt);
1350                 }
1351 #else
1352                 if (t->tracking) {
1353                         ast_remove_lock_info(t);
1354                 }
1355 #endif
1356                 __ast_mutex_logger("%s line %d (%s): Error obtaining write lock: %s\n",
1357                                 filename, line, func, strerror(res));
1358                 DO_THREAD_CRASH;
1359         }
1360         return res;
1361 }
1362
1363 #define ast_rwlock_timedrdlock(a, b) \
1364         _ast_rwlock_timedrdlock(a, # a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1365
1366 static inline int _ast_rwlock_timedrdlock(ast_rwlock_t *t, const char *name,
1367         const struct timespec *abs_timeout, const char *filename, int line, const char *func)
1368 {
1369         int res;
1370         struct ast_lock_track *lt = &t->track;
1371         int canlog = strcmp(filename, "logger.c") & t->tracking;
1372 #ifdef HAVE_BKTR
1373         struct ast_bt *bt = NULL;
1374 #endif
1375
1376 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1377         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1378                  /* Don't warn abount uninitialized lock.
1379                   * Simple try to initialize it.
1380                   * May be not needed in linux system.
1381                   */
1382                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1383                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1384                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1385                                         filename, line, func, name);
1386                         return res;
1387                 }
1388         }
1389 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1390
1391         if (t->tracking) {
1392 #ifdef HAVE_BKTR
1393                 ast_reentrancy_lock(lt);
1394                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1395                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1396                         bt = &lt->backtrace[lt->reentrancy];
1397                 }
1398                 ast_reentrancy_unlock(lt);
1399                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1400 #else
1401                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
1402 #endif
1403         }
1404 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1405         res = pthread_rwlock_timedrdlock(&t->lock, abs_timeout);
1406 #else
1407         do {
1408                 struct timeval _start = ast_tvnow(), _diff;
1409                 for (;;) {
1410                         if (!(res = pthread_rwlock_tryrdlock(&t->lock))) {
1411                                 break;
1412                         }
1413                         _diff = ast_tvsub(ast_tvnow(), _start);
1414                         if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1415                                 break;
1416                         }
1417                         usleep(1);
1418                 }
1419         } while (0);
1420 #endif
1421         if (!res) {
1422                 ast_reentrancy_lock(lt);
1423                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1424                         lt->file[lt->reentrancy] = filename;
1425                         lt->lineno[lt->reentrancy] = line;
1426                         lt->func[lt->reentrancy] = func;
1427                         lt->thread[lt->reentrancy] = pthread_self();
1428                         lt->reentrancy++;
1429                 }
1430                 ast_reentrancy_unlock(lt);
1431                 if (t->tracking) {
1432                         ast_mark_lock_acquired(t);
1433                 }
1434         } else {
1435 #ifdef HAVE_BKTR
1436                 if (lt->reentrancy) {
1437                         ast_reentrancy_lock(lt);
1438                         bt = &lt->backtrace[lt->reentrancy-1];
1439                         ast_reentrancy_unlock(lt);
1440                 } else {
1441                         bt = NULL;
1442                 }
1443                 if (t->tracking) {
1444                         ast_remove_lock_info(t, bt);
1445                 }
1446 #else
1447                 if (t->tracking) {
1448                         ast_remove_lock_info(t);
1449                 }
1450 #endif
1451                 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
1452                                 filename, line, func, strerror(res));
1453                 DO_THREAD_CRASH;
1454         }
1455         return res;
1456 }
1457
1458 #define ast_rwlock_timedwrlock(a, b) \
1459         _ast_rwlock_timedwrlock(a, # a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1460
1461 static inline int _ast_rwlock_timedwrlock(ast_rwlock_t *t, const char *name,
1462         const struct timespec *abs_timeout, const char *filename, int line, const char *func)
1463 {
1464         int res;
1465         struct ast_lock_track *lt = &t->track;
1466         int canlog = strcmp(filename, "logger.c") & t->tracking;
1467 #ifdef HAVE_BKTR
1468         struct ast_bt *bt = NULL;
1469 #endif
1470
1471 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1472         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1473                  /* Don't warn abount uninitialized lock.
1474                   * Simple try to initialize it.
1475                   * May be not needed in linux system.
1476                   */
1477                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1478                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1479                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1480                                         filename, line, func, name);
1481                         return res;
1482                 }
1483         }
1484 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1485
1486         if (t->tracking) {
1487 #ifdef HAVE_BKTR
1488                 ast_reentrancy_lock(lt);
1489                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1490                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1491                         bt = &lt->backtrace[lt->reentrancy];
1492                 }
1493                 ast_reentrancy_unlock(lt);
1494                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1495 #else
1496                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
1497 #endif
1498         }
1499 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1500         res = pthread_rwlock_timedwrlock(&t->lock, abs_timeout);
1501 #else
1502         do {
1503                 struct timeval _start = ast_tvnow(), _diff;
1504                 for (;;) {
1505                         if (!(res = pthread_rwlock_trywrlock(&t->lock))) {
1506                                 break;
1507                         }
1508                         _diff = ast_tvsub(ast_tvnow(), _start);
1509                         if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1510                                 break;
1511                         }
1512                         usleep(1);
1513                 }
1514         } while (0);
1515 #endif
1516         if (!res) {
1517                 ast_reentrancy_lock(lt);
1518                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1519                         lt->file[lt->reentrancy] = filename;
1520                         lt->lineno[lt->reentrancy] = line;
1521                         lt->func[lt->reentrancy] = func;
1522                         lt->thread[lt->reentrancy] = pthread_self();
1523                         lt->reentrancy++;
1524                 }
1525                 ast_reentrancy_unlock(lt);
1526                 if (t->tracking) {
1527                         ast_mark_lock_acquired(t);
1528                 }
1529         } else {
1530 #ifdef HAVE_BKTR
1531                 if (lt->reentrancy) {
1532                         ast_reentrancy_lock(lt);
1533                         bt = &lt->backtrace[lt->reentrancy-1];
1534                         ast_reentrancy_unlock(lt);
1535                 } else {
1536                         bt = NULL;
1537                 }
1538                 if (t->tracking) {
1539                         ast_remove_lock_info(t, bt);
1540                 }
1541 #else
1542                 if (t->tracking) {
1543                         ast_remove_lock_info(t);
1544                 }
1545 #endif
1546                 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
1547                                 filename, line, func, strerror(res));
1548                 DO_THREAD_CRASH;
1549         }
1550         return res;
1551 }
1552
1553 static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *t, const char *name,
1554         const char *filename, int line, const char *func)
1555 {
1556         int res;
1557         struct ast_lock_track *lt = &t->track;
1558 #ifdef HAVE_BKTR
1559         struct ast_bt *bt = NULL;
1560 #endif
1561 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1562         int canlog = strcmp(filename, "logger.c") & t->tracking;
1563
1564         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1565                  /* Don't warn abount uninitialized lock.
1566                   * Simple try to initialize it.
1567                   * May be not needed in linux system.
1568                   */
1569                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1570                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1571                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1572                                         filename, line, func, name);
1573                         return res;
1574                 }
1575         }
1576 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1577
1578         if (t->tracking) {
1579 #ifdef HAVE_BKTR
1580                 ast_reentrancy_lock(lt);
1581                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1582                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1583                         bt = &lt->backtrace[lt->reentrancy];
1584                 }
1585                 ast_reentrancy_unlock(lt);
1586                 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
1587 #else
1588                 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
1589 #endif
1590         }
1591
1592         if (!(res = pthread_rwlock_tryrdlock(&t->lock))) {
1593                 ast_reentrancy_lock(lt);
1594                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1595                         lt->file[lt->reentrancy] = filename;
1596                         lt->lineno[lt->reentrancy] = line;
1597                         lt->func[lt->reentrancy] = func;
1598                         lt->thread[lt->reentrancy] = pthread_self();
1599                         lt->reentrancy++;
1600                 }
1601                 ast_reentrancy_unlock(lt);
1602                 if (t->tracking) {
1603                         ast_mark_lock_acquired(t);
1604                 }
1605         } else if (t->tracking) {
1606                 ast_mark_lock_failed(t);
1607         }
1608         return res;
1609 }
1610
1611 static inline int _ast_rwlock_trywrlock(ast_rwlock_t *t, const char *name,
1612         const char *filename, int line, const char *func)
1613 {
1614         int res;
1615         struct ast_lock_track *lt= &t->track;
1616 #ifdef HAVE_BKTR
1617         struct ast_bt *bt = NULL;
1618 #endif
1619 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1620         int canlog = strcmp(filename, "logger.c") & t->tracking;
1621
1622         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1623                  /* Don't warn abount uninitialized lock.
1624                   * Simple try to initialize it.
1625                   * May be not needed in linux system.
1626                   */
1627                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1628                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1629                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1630                                         filename, line, func, name);
1631                         return res;
1632                 }
1633         }
1634 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1635
1636         if (t->tracking) {
1637 #ifdef HAVE_BKTR
1638                 ast_reentrancy_lock(lt);
1639                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1640                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1641                         bt = &lt->backtrace[lt->reentrancy];
1642                 }
1643                 ast_reentrancy_unlock(lt);
1644                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1645 #else
1646                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
1647 #endif
1648         }
1649
1650         if (!(res = pthread_rwlock_trywrlock(&t->lock))) {
1651                 ast_reentrancy_lock(lt);
1652                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1653                         lt->file[lt->reentrancy] = filename;
1654                         lt->lineno[lt->reentrancy] = line;
1655                         lt->func[lt->reentrancy] = func;
1656                         lt->thread[lt->reentrancy] = pthread_self();
1657                         lt->reentrancy++;
1658                 }
1659                 ast_reentrancy_unlock(lt);
1660                 if (t->tracking) {
1661                         ast_mark_lock_acquired(t);
1662                 }
1663         } else if (t->tracking) {
1664                 ast_mark_lock_failed(t);
1665         }
1666         return res;
1667 }
1668
1669 #else /* !DEBUG_THREADS */
1670
1671 #define CHANNEL_DEADLOCK_AVOIDANCE(chan) \
1672         ast_channel_unlock(chan); \
1673         usleep(1); \
1674         ast_channel_lock(chan);
1675
1676 #define DEADLOCK_AVOIDANCE(lock) \
1677         ast_mutex_unlock(lock); \
1678         usleep(1); \
1679         ast_mutex_lock(lock);
1680
1681 #define DLA_UNLOCK(lock)        ast_mutex_unlock(lock)
1682
1683 #define DLA_LOCK(lock)  ast_mutex_lock(lock)
1684
1685 typedef pthread_mutex_t ast_mutex_t;
1686
1687 #define AST_MUTEX_INIT_VALUE                    ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
1688 #define AST_MUTEX_INIT_VALUE_NOTRACKING         ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
1689
1690 #define ast_mutex_init_notracking(m)            ast_mutex_init(m)
1691
1692 static inline int ast_mutex_init(ast_mutex_t *pmutex)
1693 {
1694         int res;
1695         pthread_mutexattr_t attr;
1696
1697         pthread_mutexattr_init(&attr);
1698         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
1699
1700         res = pthread_mutex_init(pmutex, &attr);
1701         pthread_mutexattr_destroy(&attr);
1702         return res;
1703 }
1704
1705 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
1706
1707 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
1708 {
1709         return pthread_mutex_unlock(pmutex);
1710 }
1711
1712 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
1713 {
1714         return pthread_mutex_destroy(pmutex);
1715 }
1716
1717 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
1718 {
1719         __MTX_PROF(pmutex);
1720 }
1721
1722 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
1723 {
1724         return pthread_mutex_trylock(pmutex);
1725 }
1726
1727 typedef pthread_cond_t ast_cond_t;
1728
1729 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
1730 {
1731         return pthread_cond_init(cond, cond_attr);
1732 }
1733
1734 static inline int ast_cond_signal(ast_cond_t *cond)
1735 {
1736         return pthread_cond_signal(cond);
1737 }
1738
1739 static inline int ast_cond_broadcast(ast_cond_t *cond)
1740 {
1741         return pthread_cond_broadcast(cond);
1742 }
1743
1744 static inline int ast_cond_destroy(ast_cond_t *cond)
1745 {
1746         return pthread_cond_destroy(cond);
1747 }
1748
1749 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
1750 {
1751         return pthread_cond_wait(cond, t);
1752 }
1753
1754 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
1755 {
1756         return pthread_cond_timedwait(cond, t, abstime);
1757 }
1758
1759
1760 typedef pthread_rwlock_t ast_rwlock_t;
1761
1762 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
1763 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
1764 #else
1765 #define AST_RWLOCK_INIT_VALUE { 0 }
1766 #endif
1767
1768 #define ast_rwlock_init_notracking(a) ast_rwlock_init(a)
1769
1770 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
1771 {
1772         int res;
1773         pthread_rwlockattr_t attr;
1774
1775         pthread_rwlockattr_init(&attr);
1776
1777 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
1778         pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
1779 #endif
1780
1781         res = pthread_rwlock_init(prwlock, &attr);
1782         pthread_rwlockattr_destroy(&attr);
1783         return res;
1784 }
1785
1786 static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
1787 {
1788         return pthread_rwlock_destroy(prwlock);
1789 }
1790
1791 static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
1792 {
1793         return pthread_rwlock_unlock(prwlock);
1794 }
1795
1796 static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
1797 {
1798         return pthread_rwlock_rdlock(prwlock);
1799 }
1800
1801 static inline int ast_rwlock_timedrdlock(ast_rwlock_t *prwlock, const struct timespec *abs_timeout)
1802 {
1803         int res;
1804 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1805         res = pthread_rwlock_timedrdlock(prwlock, abs_timeout);
1806 #else
1807         struct timeval _start = ast_tvnow(), _diff;
1808         for (;;) {
1809                 if (!(res = pthread_rwlock_tryrdlock(prwlock))) {
1810                         break;
1811                 }
1812                 _diff = ast_tvsub(ast_tvnow(), _start);
1813                 if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1814                         break;
1815                 }
1816                 usleep(1);
1817         }
1818 #endif
1819         return res;
1820 }
1821
1822 static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
1823 {
1824         return pthread_rwlock_tryrdlock(prwlock);
1825 }
1826
1827 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
1828 {
1829         return pthread_rwlock_wrlock(prwlock);
1830 }
1831
1832 static inline int ast_rwlock_timedwrlock(ast_rwlock_t *prwlock, const struct timespec *abs_timeout)
1833 {
1834         int res;
1835 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1836         res = pthread_rwlock_timedwrlock(prwlock, abs_timeout);
1837 #else
1838         do {
1839                 struct timeval _start = ast_tvnow(), _diff;
1840                 for (;;) {
1841                         if (!(res = pthread_rwlock_trywrlock(prwlock))) {
1842                                 break;
1843                         }
1844                         _diff = ast_tvsub(ast_tvnow(), _start);
1845                         if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1846                                 break;
1847                         }
1848                         usleep(1);
1849                 }
1850         } while (0);
1851 #endif
1852         return res;
1853 }
1854
1855 static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
1856 {
1857         return pthread_rwlock_trywrlock(prwlock);
1858 }
1859
1860 #endif /* !DEBUG_THREADS */
1861
1862 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1863 /*
1864  * If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope constructors
1865  * and destructors to create/destroy global mutexes.
1866  */
1867 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)       \
1868         scope ast_mutex_t mutex = init_val;                     \
1869 static void  __attribute__((constructor)) init_##mutex(void)    \
1870 {                                                               \
1871         if (track)                                              \
1872                 ast_mutex_init(&mutex);                         \
1873         else                                                    \
1874                 ast_mutex_init_notracking(&mutex);              \
1875 }                                                               \
1876                                                                 \
1877 static void  __attribute__((destructor)) fini_##mutex(void)     \
1878 {                                                               \
1879         ast_mutex_destroy(&mutex);                              \
1880 }
1881 #else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
1882 /* By default, use static initialization of mutexes. */
1883 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)       scope ast_mutex_t mutex = init_val
1884 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1885
1886 #ifndef __CYGWIN__      /* temporary disabled for cygwin */
1887 #define pthread_mutex_t         use_ast_mutex_t_instead_of_pthread_mutex_t
1888 #define pthread_cond_t          use_ast_cond_t_instead_of_pthread_cond_t
1889 #endif
1890 #define pthread_mutex_lock      use_ast_mutex_lock_instead_of_pthread_mutex_lock
1891 #define pthread_mutex_unlock    use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
1892 #define pthread_mutex_trylock   use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
1893 #define pthread_mutex_init      use_ast_mutex_init_instead_of_pthread_mutex_init
1894 #define pthread_mutex_destroy   use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
1895 #define pthread_cond_init       use_ast_cond_init_instead_of_pthread_cond_init
1896 #define pthread_cond_destroy    use_ast_cond_destroy_instead_of_pthread_cond_destroy
1897 #define pthread_cond_signal     use_ast_cond_signal_instead_of_pthread_cond_signal
1898 #define pthread_cond_broadcast  use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
1899 #define pthread_cond_wait       use_ast_cond_wait_instead_of_pthread_cond_wait
1900 #define pthread_cond_timedwait  use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
1901
1902 #define AST_MUTEX_DEFINE_STATIC(mutex)                  __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
1903 #define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex)       __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
1904
1905 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
1906
1907 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
1908
1909 #ifndef __linux__
1910 #define pthread_create __use_ast_pthread_create_instead__
1911 #endif
1912
1913 /* Statically declared read/write locks */
1914
1915 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1916 #define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) \
1917         scope ast_rwlock_t rwlock = init_val; \
1918 static void  __attribute__((constructor)) init_##rwlock(void) \
1919 { \
1920         if (track) \
1921                 ast_rwlock_init(&rwlock); \
1922         else \
1923                 ast_rwlock_init_notracking(&rwlock); \
1924 } \
1925 static void  __attribute__((destructor)) fini_##rwlock(void) \
1926 { \
1927         ast_rwlock_destroy(&rwlock); \
1928 }
1929 #else
1930 #define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) \
1931         scope ast_rwlock_t rwlock = init_val
1932 #endif
1933
1934 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE, 1)
1935 #define AST_RWLOCK_DEFINE_STATIC_NOTRACKING(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE_NOTRACKING, 0)
1936
1937 /*
1938  * Support for atomic instructions.
1939  * For platforms that have it, use the native cpu instruction to
1940  * implement them. For other platforms, resort to a 'slow' version
1941  * (defined in utils.c) that protects the atomic instruction with
1942  * a single lock.
1943  * The slow versions is always available, for testing purposes,
1944  * as ast_atomic_fetchadd_int_slow()
1945  */
1946
1947 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
1948
1949 #include "asterisk/inline_api.h"
1950
1951 #if defined(HAVE_OSX_ATOMICS)
1952 #include "libkern/OSAtomic.h"
1953 #endif
1954
1955 /*! \brief Atomically add v to *p and return * the previous value of *p.
1956  * This can be used to handle reference counts, and the return value
1957  * can be used to generate unique identifiers.
1958  */
1959
1960 #if defined(HAVE_GCC_ATOMICS)
1961 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1962 {
1963         return __sync_fetch_and_add(p, v);
1964 })
1965 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1966 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1967 {
1968         return OSAtomicAdd32(v, (int32_t *) p) - v;
1969 })
1970 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1971 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1972 {
1973         return OSAtomicAdd64(v, (int64_t *) p) - v;
1974 #elif defined (__i386__) || defined(__x86_64__)
1975 #ifdef sun
1976 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1977 {
1978         __asm __volatile (
1979         "       lock;  xaddl   %0, %1 ;        "
1980         : "+r" (v),                     /* 0 (result) */
1981           "=m" (*p)                     /* 1 */
1982         : "m" (*p));                    /* 2 */
1983         return (v);
1984 })
1985 #else /* ifndef sun */
1986 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1987 {
1988         __asm __volatile (
1989         "       lock   xaddl   %0, %1 ;        "
1990         : "+r" (v),                     /* 0 (result) */
1991           "=m" (*p)                     /* 1 */
1992         : "m" (*p));                    /* 2 */
1993         return (v);
1994 })
1995 #endif
1996 #else   /* low performance version in utils.c */
1997 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1998 {
1999         return ast_atomic_fetchadd_int_slow(p, v);
2000 })
2001 #endif
2002
2003 /*! \brief decrement *p by 1 and return true if the variable has reached 0.
2004  * Useful e.g. to check if a refcount has reached 0.
2005  */
2006 #if defined(HAVE_GCC_ATOMICS)
2007 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
2008 {
2009         return __sync_sub_and_fetch(p, 1) == 0;
2010 })
2011 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
2012 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
2013 {
2014         return OSAtomicAdd32( -1, (int32_t *) p) == 0;
2015 })
2016 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
2017 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
2018 {
2019         return OSAtomicAdd64( -1, (int64_t *) p) == 0;
2020 #else
2021 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
2022 {
2023         int a = ast_atomic_fetchadd_int(p, -1);
2024         return a == 1; /* true if the value is 0 now (so it was 1 previously) */
2025 })
2026 #endif
2027
2028 #endif /* _ASTERISK_LOCK_H */