Merged revisions 228827 via svnmerge from
[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 #define ROFFSET ((lt->reentrancy > 0) ? (lt->reentrancy-1) : 0)
413 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
414                                                 const char *mutex_name, ast_mutex_t *t)
415 {
416         int res;
417         struct ast_lock_track *lt;
418         int canlog = strcmp(filename, "logger.c") & t->tracking;
419
420 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
421         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
422                 /* Don't try to uninitialize non initialized mutex
423                  * This may no effect on linux
424                  * And always ganerate core on *BSD with
425                  * linked libpthread
426                  * This not error condition if the mutex created on the fly.
427                  */
428                 __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
429                                    filename, lineno, func, mutex_name);
430                 return 0;
431         }
432 #endif
433
434         lt = &t->track;
435
436         res = pthread_mutex_trylock(&t->mutex);
437         switch (res) {
438         case 0:
439                 pthread_mutex_unlock(&t->mutex);
440                 break;
441         case EINVAL:
442                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
443                                   filename, lineno, func, mutex_name);
444                 break;
445         case EBUSY:
446                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
447                                    filename, lineno, func, mutex_name);
448                 ast_reentrancy_lock(lt);
449                 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
450                             lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
451 #ifdef HAVE_BKTR
452                 __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
453 #endif
454                 ast_reentrancy_unlock(lt);
455                 break;
456         }
457
458
459         if ((res = pthread_mutex_destroy(&t->mutex))) {
460                 __ast_mutex_logger("%s line %d (%s): Error destroying mutex %s: %s\n",
461                                    filename, lineno, func, mutex_name, strerror(res));
462         }
463 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
464         else
465                 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
466 #endif
467         ast_reentrancy_lock(lt);
468         lt->file[0] = filename;
469         lt->lineno[0] = lineno;
470         lt->func[0] = func;
471         lt->reentrancy = 0;
472         lt->thread[0] = 0;
473 #ifdef HAVE_BKTR
474         memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
475 #endif
476         ast_reentrancy_unlock(lt);
477         delete_reentrancy_cs(lt);
478
479         return res;
480 }
481
482 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
483                                            const char* mutex_name, ast_mutex_t *t)
484 {
485         int res;
486         struct ast_lock_track *lt = &t->track;
487         int canlog = strcmp(filename, "logger.c") & t->tracking;
488 #ifdef HAVE_BKTR
489         struct ast_bt *bt = NULL;
490 #endif
491
492 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
493         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
494                 /* Don't warn abount uninitialized mutex.
495                  * Simple try to initialize it.
496                  * May be not needed in linux system.
497                  */
498                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
499                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
500                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
501                                          filename, lineno, func, mutex_name);
502                         return res;
503                 }
504         }
505 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
506
507         if (t->tracking) {
508 #ifdef HAVE_BKTR
509                 ast_reentrancy_lock(lt);
510                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
511                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
512                         bt = &lt->backtrace[lt->reentrancy];
513                 }
514                 ast_reentrancy_unlock(lt);
515                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
516 #else
517                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
518 #endif
519         }
520
521 #ifdef DETECT_DEADLOCKS
522         {
523                 time_t seconds = time(NULL);
524                 time_t wait_time, reported_wait = 0;
525                 do {
526 #ifdef  HAVE_MTX_PROFILE
527                         ast_mark(mtx_prof, 1);
528 #endif
529                         res = pthread_mutex_trylock(&t->mutex);
530 #ifdef  HAVE_MTX_PROFILE
531                         ast_mark(mtx_prof, 0);
532 #endif
533                         if (res == EBUSY) {
534                                 wait_time = time(NULL) - seconds;
535                                 if (wait_time > reported_wait && (wait_time % 5) == 0) {
536                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
537                                                            filename, lineno, func, (int) wait_time, mutex_name);
538                                         ast_reentrancy_lock(lt);
539 #ifdef HAVE_BKTR
540                                         __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
541 #endif
542                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
543                                                            lt->file[ROFFSET], lt->lineno[ROFFSET],
544                                                            lt->func[ROFFSET], mutex_name);
545 #ifdef HAVE_BKTR
546                                         __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
547 #endif
548                                         ast_reentrancy_unlock(lt);
549                                         reported_wait = wait_time;
550                                 }
551                                 usleep(200);
552                         }
553                 } while (res == EBUSY);
554         }
555 #else
556 #ifdef  HAVE_MTX_PROFILE
557         ast_mark(mtx_prof, 1);
558         res = pthread_mutex_trylock(&t->mutex);
559         ast_mark(mtx_prof, 0);
560         if (res)
561 #endif
562         res = pthread_mutex_lock(&t->mutex);
563 #endif /* DETECT_DEADLOCKS */
564
565         if (!res) {
566                 ast_reentrancy_lock(lt);
567                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
568                         lt->file[lt->reentrancy] = filename;
569                         lt->lineno[lt->reentrancy] = lineno;
570                         lt->func[lt->reentrancy] = func;
571                         lt->thread[lt->reentrancy] = pthread_self();
572                         lt->reentrancy++;
573                 } else {
574                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
575                                                            filename, lineno, func, mutex_name);
576                 }
577                 ast_reentrancy_unlock(lt);
578                 if (t->tracking) {
579                         ast_mark_lock_acquired(t);
580                 }
581         } else {
582 #ifdef HAVE_BKTR
583                 if (lt->reentrancy) {
584                         ast_reentrancy_lock(lt);
585                         bt = &lt->backtrace[lt->reentrancy-1];
586                         ast_reentrancy_unlock(lt);
587                 } else {
588                         bt = NULL;
589                 }
590                 if (t->tracking) {
591                         ast_remove_lock_info(t, bt);
592                 }
593 #else
594                 if (t->tracking) {
595                         ast_remove_lock_info(t);
596                 }
597 #endif
598                 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
599                                    filename, lineno, func, strerror(res));
600                 DO_THREAD_CRASH;
601         }
602
603         return res;
604 }
605
606 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
607                                               const char* mutex_name, ast_mutex_t *t)
608 {
609         int res;
610         struct ast_lock_track *lt= &t->track;
611         int canlog = strcmp(filename, "logger.c") & t->tracking;
612 #ifdef HAVE_BKTR
613         struct ast_bt *bt = NULL;
614 #endif
615
616 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
617         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
618                 /* Don't warn abount uninitialized mutex.
619                  * Simple try to initialize it.
620                  * May be not needed in linux system.
621                  */
622                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
623                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
624                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
625                                          filename, lineno, func, mutex_name);
626                         return res;
627                 }
628         }
629 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
630
631         if (t->tracking) {
632 #ifdef HAVE_BKTR
633                 ast_reentrancy_lock(lt);
634                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
635                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
636                         bt = &lt->backtrace[lt->reentrancy];
637                 }
638                 ast_reentrancy_unlock(lt);
639                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
640 #else
641                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
642 #endif
643         }
644
645         if (!(res = pthread_mutex_trylock(&t->mutex))) {
646                 ast_reentrancy_lock(lt);
647                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
648                         lt->file[lt->reentrancy] = filename;
649                         lt->lineno[lt->reentrancy] = lineno;
650                         lt->func[lt->reentrancy] = func;
651                         lt->thread[lt->reentrancy] = pthread_self();
652                         lt->reentrancy++;
653                 } else {
654                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
655                                            filename, lineno, func, mutex_name);
656                 }
657                 ast_reentrancy_unlock(lt);
658                 if (t->tracking) {
659                         ast_mark_lock_acquired(t);
660                 }
661         } else if (t->tracking) {
662                 ast_mark_lock_failed(t);
663         }
664
665         return res;
666 }
667
668 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
669                                              const char *mutex_name, ast_mutex_t *t)
670 {
671         int res;
672         struct ast_lock_track *lt = &t->track;
673         int canlog = strcmp(filename, "logger.c") & t->tracking;
674 #ifdef HAVE_BKTR
675         struct ast_bt *bt = NULL;
676 #endif
677
678 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
679         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
680                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
681                                    filename, lineno, func, mutex_name);
682                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
683                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
684                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
685                                          filename, lineno, func, mutex_name);
686                 }
687                 return res;
688         }
689 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
690
691         ast_reentrancy_lock(lt);
692         if (lt->reentrancy && (lt->thread[ROFFSET] != pthread_self())) {
693                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
694                                    filename, lineno, func, mutex_name);
695                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
696                                    lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
697 #ifdef HAVE_BKTR
698                 __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
699 #endif
700                 DO_THREAD_CRASH;
701         }
702
703         if (--lt->reentrancy < 0) {
704                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
705                                    filename, lineno, func, mutex_name);
706                 lt->reentrancy = 0;
707         }
708
709         if (lt->reentrancy < AST_MAX_REENTRANCY) {
710                 lt->file[lt->reentrancy] = NULL;
711                 lt->lineno[lt->reentrancy] = 0;
712                 lt->func[lt->reentrancy] = NULL;
713                 lt->thread[lt->reentrancy] = 0;
714         }
715
716 #ifdef HAVE_BKTR
717         if (lt->reentrancy) {
718                 bt = &lt->backtrace[lt->reentrancy - 1];
719         }
720 #endif
721         ast_reentrancy_unlock(lt);
722
723         if (t->tracking) {
724 #ifdef HAVE_BKTR
725                 ast_remove_lock_info(t, bt);
726 #else
727                 ast_remove_lock_info(t);
728 #endif
729         }
730
731         if ((res = pthread_mutex_unlock(&t->mutex))) {
732                 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
733                                    filename, lineno, func, strerror(res));
734                 DO_THREAD_CRASH;
735         }
736
737         return res;
738 }
739
740 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
741                                   const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
742 {
743         return pthread_cond_init(cond, cond_attr);
744 }
745
746 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
747                                     const char *cond_name, ast_cond_t *cond)
748 {
749         return pthread_cond_signal(cond);
750 }
751
752 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
753                                        const char *cond_name, ast_cond_t *cond)
754 {
755         return pthread_cond_broadcast(cond);
756 }
757
758 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
759                                      const char *cond_name, ast_cond_t *cond)
760 {
761         return pthread_cond_destroy(cond);
762 }
763
764 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
765                                   const char *cond_name, const char *mutex_name,
766                                   ast_cond_t *cond, ast_mutex_t *t)
767 {
768         int res;
769         struct ast_lock_track *lt= &t->track;
770         int canlog = strcmp(filename, "logger.c") & t->tracking;
771 #ifdef HAVE_BKTR
772         struct ast_bt *bt = NULL;
773 #endif
774
775 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
776         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
777                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
778                                    filename, lineno, func, mutex_name);
779                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
780                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
781                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
782                                          filename, lineno, func, mutex_name);
783                 }
784                 return res;
785         }
786 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
787
788         ast_reentrancy_lock(lt);
789         if (lt->reentrancy && (lt->thread[ROFFSET] != pthread_self())) {
790                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
791                                    filename, lineno, func, mutex_name);
792                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
793                                    lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
794 #ifdef HAVE_BKTR
795                 __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
796 #endif
797                 DO_THREAD_CRASH;
798         }
799
800         if (--lt->reentrancy < 0) {
801                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
802                                    filename, lineno, func, mutex_name);
803                 lt->reentrancy = 0;
804         }
805
806         if (lt->reentrancy < AST_MAX_REENTRANCY) {
807                 lt->file[lt->reentrancy] = NULL;
808                 lt->lineno[lt->reentrancy] = 0;
809                 lt->func[lt->reentrancy] = NULL;
810                 lt->thread[lt->reentrancy] = 0;
811         }
812
813 #ifdef HAVE_BKTR
814         if (lt->reentrancy) {
815                 bt = &lt->backtrace[lt->reentrancy - 1];
816         }
817 #endif
818         ast_reentrancy_unlock(lt);
819
820         if (t->tracking) {
821 #ifdef HAVE_BKTR
822                 ast_remove_lock_info(t, bt);
823 #else
824                 ast_remove_lock_info(t);
825 #endif
826         }
827
828         if ((res = pthread_cond_wait(cond, &t->mutex))) {
829                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
830                                    filename, lineno, func, strerror(res));
831                 DO_THREAD_CRASH;
832         } else {
833                 ast_reentrancy_lock(lt);
834                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
835                         lt->file[lt->reentrancy] = filename;
836                         lt->lineno[lt->reentrancy] = lineno;
837                         lt->func[lt->reentrancy] = func;
838                         lt->thread[lt->reentrancy] = pthread_self();
839 #ifdef HAVE_BKTR
840                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
841                         bt = &lt->backtrace[lt->reentrancy];
842 #endif
843                         lt->reentrancy++;
844                 } else {
845                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
846                                                            filename, lineno, func, mutex_name);
847                 }
848                 ast_reentrancy_unlock(lt);
849
850                 if (t->tracking) {
851 #ifdef HAVE_BKTR
852                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
853 #else
854                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
855 #endif
856                 }
857         }
858
859         return res;
860 }
861
862 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
863                                        const char *cond_name, const char *mutex_name, ast_cond_t *cond,
864                                        ast_mutex_t *t, const struct timespec *abstime)
865 {
866         int res;
867         struct ast_lock_track *lt = &t->track;
868         int canlog = strcmp(filename, "logger.c") & t->tracking;
869 #ifdef HAVE_BKTR
870         struct ast_bt *bt = NULL;
871 #endif
872
873 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
874         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
875                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
876                                    filename, lineno, func, mutex_name);
877                 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
878                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
879                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
880                                          filename, lineno, func, mutex_name);
881                 }
882                 return res;
883         }
884 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
885
886         ast_reentrancy_lock(lt);
887         if (lt->reentrancy && (lt->thread[ROFFSET] != pthread_self())) {
888                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
889                                    filename, lineno, func, mutex_name);
890                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
891                                    lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
892 #ifdef HAVE_BKTR
893                 __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
894 #endif
895                 DO_THREAD_CRASH;
896         }
897
898         if (--lt->reentrancy < 0) {
899                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
900                                    filename, lineno, func, mutex_name);
901                 lt->reentrancy = 0;
902         }
903
904         if (lt->reentrancy < AST_MAX_REENTRANCY) {
905                 lt->file[lt->reentrancy] = NULL;
906                 lt->lineno[lt->reentrancy] = 0;
907                 lt->func[lt->reentrancy] = NULL;
908                 lt->thread[lt->reentrancy] = 0;
909         }
910 #ifdef HAVE_BKTR
911         if (lt->reentrancy) {
912                 bt = &lt->backtrace[lt->reentrancy - 1];
913         }
914 #endif
915         ast_reentrancy_unlock(lt);
916
917         if (t->tracking) {
918 #ifdef HAVE_BKTR
919                 ast_remove_lock_info(t, bt);
920 #else
921                 ast_remove_lock_info(t);
922 #endif
923         }
924
925         if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
926                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
927                                    filename, lineno, func, strerror(res));
928                 DO_THREAD_CRASH;
929         } else {
930                 ast_reentrancy_lock(lt);
931                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
932                         lt->file[lt->reentrancy] = filename;
933                         lt->lineno[lt->reentrancy] = lineno;
934                         lt->func[lt->reentrancy] = func;
935                         lt->thread[lt->reentrancy] = pthread_self();
936 #ifdef HAVE_BKTR
937                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
938                         bt = &lt->backtrace[lt->reentrancy];
939 #endif
940                         lt->reentrancy++;
941                 } else {
942                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
943                                                            filename, lineno, func, mutex_name);
944                 }
945                 ast_reentrancy_unlock(lt);
946
947                 if (t->tracking) {
948 #ifdef HAVE_BKTR
949                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
950 #else
951                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
952 #endif
953                 }
954         }
955
956         return res;
957 }
958
959 #define ast_mutex_destroy(a)                    __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
960 #define ast_mutex_lock(a)                       __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
961 #define ast_mutex_unlock(a)                     __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
962 #define ast_mutex_trylock(a)                    __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
963 #define ast_cond_init(cond, attr)               __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
964 #define ast_cond_destroy(cond)                  __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
965 #define ast_cond_signal(cond)                   __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
966 #define ast_cond_broadcast(cond)                __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
967 #define ast_cond_wait(cond, mutex)              __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
968 #define ast_cond_timedwait(cond, mutex, time)   __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
969
970 struct ast_rwlock_info {
971         /*! Track which thread holds this lock */
972         struct ast_lock_track track;
973         unsigned int tracking:1;
974         pthread_rwlock_t lock;
975 };
976
977 typedef struct ast_rwlock_info ast_rwlock_t;
978
979 /*!
980  * \brief wrapper for rwlock with tracking enabled
981  * \return 0 on success, non zero for error
982  * \since 1.6.1
983  */
984 #define ast_rwlock_init(rwlock) __ast_rwlock_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
985
986 /*!
987  * \brief wrapper for ast_rwlock_init with tracking disabled
988  * \return 0 on success, non zero for error
989  * \since 1.6.1
990  */
991 #define ast_rwlock_init_notracking(rwlock) __ast_rwlock_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
992
993 #define ast_rwlock_destroy(rwlock)      __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
994 #define ast_rwlock_unlock(a)            _ast_rwlock_unlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
995 #define ast_rwlock_rdlock(a)            _ast_rwlock_rdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
996 #define ast_rwlock_wrlock(a)            _ast_rwlock_wrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
997 #define ast_rwlock_tryrdlock(a)         _ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
998 #define ast_rwlock_trywrlock(a) _ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
999
1000
1001 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
1002 #define __AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
1003 #else  /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
1004 #define __AST_RWLOCK_INIT_VALUE {0}
1005 #endif /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
1006
1007 #define AST_RWLOCK_INIT_VALUE \
1008         { AST_LOCK_TRACK_INIT_VALUE, 1, __AST_RWLOCK_INIT_VALUE }
1009 #define AST_RWLOCK_INIT_VALUE_NOTRACKING \
1010         { AST_LOCK_TRACK_INIT_VALUE, 0, __AST_RWLOCK_INIT_VALUE }
1011
1012 static inline int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
1013 {
1014         int res;
1015         struct ast_lock_track *lt= &t->track;
1016         pthread_rwlockattr_t attr;
1017
1018 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1019         int canlog = strcmp(filename, "logger.c") & t->tracking;
1020
1021         if (t->lock != ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1022                 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
1023                                 filename, lineno, func, rwlock_name);
1024                 return 0;
1025         }
1026 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1027
1028         ast_reentrancy_init(lt);
1029         t->tracking = tracking;
1030         pthread_rwlockattr_init(&attr);
1031
1032 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
1033         pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
1034 #endif
1035
1036         res = pthread_rwlock_init(&t->lock, &attr);
1037         pthread_rwlockattr_destroy(&attr);
1038         return res;
1039 }
1040
1041 static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
1042 {
1043         int res;
1044         struct ast_lock_track *lt = &t->track;
1045         int canlog = strcmp(filename, "logger.c") & t->tracking;
1046
1047 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1048         if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1049                 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
1050                                    filename, lineno, func, rwlock_name);
1051                 return 0;
1052         }
1053 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1054
1055         if ((res = pthread_rwlock_destroy(&t->lock))) {
1056                 __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
1057                                 filename, lineno, func, rwlock_name, strerror(res));
1058         }
1059         ast_reentrancy_lock(lt);
1060         lt->file[0] = filename;
1061         lt->lineno[0] = lineno;
1062         lt->func[0] = func;
1063         lt->reentrancy = 0;
1064         lt->thread[0] = 0;
1065 #ifdef HAVE_BKTR
1066         memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
1067 #endif
1068         ast_reentrancy_unlock(lt);
1069         delete_reentrancy_cs(lt);
1070
1071         return res;
1072 }
1073
1074 static inline int _ast_rwlock_unlock(ast_rwlock_t *t, const char *name,
1075         const char *filename, int line, const char *func)
1076 {
1077         int res;
1078         struct ast_lock_track *lt = &t->track;
1079         int canlog = strcmp(filename, "logger.c") & t->tracking;
1080 #ifdef HAVE_BKTR
1081         struct ast_bt *bt = NULL;
1082 #endif
1083         int lock_found = 0;
1084
1085
1086 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1087         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1088                 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
1089                                    filename, line, func, name);
1090                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1091                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1092                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1093                                         filename, line, func, name);
1094                 }
1095                 return res;
1096         }
1097 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1098
1099         ast_reentrancy_lock(lt);
1100         if (lt->reentrancy) {
1101                 int i;
1102                 pthread_t self = pthread_self();
1103                 for (i = lt->reentrancy - 1; i >= 0; --i) {
1104                         if (lt->thread[i] == self) {
1105                                 lock_found = 1;
1106                                 if (i != lt->reentrancy - 1) {
1107                                         lt->file[i] = lt->file[lt->reentrancy - 1];
1108                                         lt->lineno[i] = lt->lineno[lt->reentrancy - 1];
1109                                         lt->func[i] = lt->func[lt->reentrancy - 1];
1110                                         lt->thread[i] = lt->thread[lt->reentrancy - 1];
1111                                 }
1112 #ifdef HAVE_BKTR
1113                                 bt = &lt->backtrace[i];
1114 #endif
1115                                 lt->file[lt->reentrancy - 1] = NULL;
1116                                 lt->lineno[lt->reentrancy - 1] = 0;
1117                                 lt->func[lt->reentrancy - 1] = NULL;
1118                                 lt->thread[lt->reentrancy - 1] = AST_PTHREADT_NULL;
1119                                 break;
1120                         }
1121                 }
1122         }
1123
1124         if (lock_found && --lt->reentrancy < 0) {
1125                 __ast_mutex_logger("%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
1126                                 filename, line, func, name);
1127                 lt->reentrancy = 0;
1128         }
1129
1130         ast_reentrancy_unlock(lt);
1131
1132         if (t->tracking) {
1133 #ifdef HAVE_BKTR
1134                 ast_remove_lock_info(t, bt);
1135 #else
1136                 ast_remove_lock_info(t);
1137 #endif
1138         }
1139
1140         if ((res = pthread_rwlock_unlock(&t->lock))) {
1141                 __ast_mutex_logger("%s line %d (%s): Error releasing rwlock: %s\n",
1142                                 filename, line, func, strerror(res));
1143                 DO_THREAD_CRASH;
1144         }
1145
1146         return res;
1147 }
1148
1149 static inline int _ast_rwlock_rdlock(ast_rwlock_t *t, const char *name,
1150         const char *filename, int line, const char *func)
1151 {
1152         int res;
1153         struct ast_lock_track *lt = &t->track;
1154         int canlog = strcmp(filename, "logger.c") & t->tracking;
1155 #ifdef HAVE_BKTR
1156         struct ast_bt *bt = NULL;
1157 #endif
1158
1159 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1160         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1161                  /* Don't warn abount uninitialized lock.
1162                   * Simple try to initialize it.
1163                   * May be not needed in linux system.
1164                   */
1165                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1166                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1167                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1168                                         filename, line, func, name);
1169                         return res;
1170                 }
1171         }
1172 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1173
1174         if (t->tracking) {
1175 #ifdef HAVE_BKTR
1176                 ast_reentrancy_lock(lt);
1177                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1178                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1179                         bt = &lt->backtrace[lt->reentrancy];
1180                 }
1181                 ast_reentrancy_unlock(lt);
1182                 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
1183 #else
1184                 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
1185 #endif
1186         }
1187
1188 #ifdef DETECT_DEADLOCKS
1189         {
1190                 time_t seconds = time(NULL);
1191                 time_t wait_time, reported_wait = 0;
1192                 do {
1193                         res = pthread_rwlock_tryrdlock(&t->lock);
1194                         if (res == EBUSY) {
1195                                 wait_time = time(NULL) - seconds;
1196                                 if (wait_time > reported_wait && (wait_time % 5) == 0) {
1197                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
1198                                                 filename, line, func, (int)wait_time, name);
1199                                         ast_reentrancy_lock(lt);
1200 #ifdef HAVE_BKTR
1201                                         __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
1202 #endif
1203                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked  here.\n",
1204                                                         lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
1205                                                         lt->func[lt->reentrancy-1], name);
1206 #ifdef HAVE_BKTR
1207                                         __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
1208 #endif
1209                                         ast_reentrancy_unlock(lt);
1210                                         reported_wait = wait_time;
1211                                 }
1212                                 usleep(200);
1213                         }
1214                 } while (res == EBUSY);
1215         }
1216 #else /* !DETECT_DEADLOCKS */
1217         res = pthread_rwlock_rdlock(&t->lock);
1218 #endif /* !DETECT_DEADLOCKS */
1219
1220         if (!res) {
1221                 ast_reentrancy_lock(lt);
1222                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1223                         lt->file[lt->reentrancy] = filename;
1224                         lt->lineno[lt->reentrancy] = line;
1225                         lt->func[lt->reentrancy] = func;
1226                         lt->thread[lt->reentrancy] = pthread_self();
1227                         lt->reentrancy++;
1228                 }
1229                 ast_reentrancy_unlock(lt);
1230                 if (t->tracking) {
1231                         ast_mark_lock_acquired(t);
1232                 }
1233         } else {
1234 #ifdef HAVE_BKTR
1235                 if (lt->reentrancy) {
1236                         ast_reentrancy_lock(lt);
1237                         bt = &lt->backtrace[lt->reentrancy-1];
1238                         ast_reentrancy_unlock(lt);
1239                 } else {
1240                         bt = NULL;
1241                 }
1242                 if (t->tracking) {
1243                         ast_remove_lock_info(t, bt);
1244                 }
1245 #else
1246                 if (t->tracking) {
1247                         ast_remove_lock_info(t);
1248                 }
1249 #endif
1250                 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
1251                                 filename, line, func, strerror(res));
1252                 DO_THREAD_CRASH;
1253         }
1254         return res;
1255 }
1256
1257 static inline int _ast_rwlock_wrlock(ast_rwlock_t *t, const char *name,
1258         const char *filename, int line, const char *func)
1259 {
1260         int res;
1261         struct ast_lock_track *lt = &t->track;
1262         int canlog = strcmp(filename, "logger.c") & t->tracking;
1263 #ifdef HAVE_BKTR
1264         struct ast_bt *bt = NULL;
1265 #endif
1266
1267 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1268         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1269                  /* Don't warn abount uninitialized lock.
1270                   * Simple try to initialize it.
1271                   * May be not needed in linux system.
1272                   */
1273                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1274                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1275                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1276                                         filename, line, func, name);
1277                         return res;
1278                 }
1279         }
1280 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1281
1282         if (t->tracking) {
1283 #ifdef HAVE_BKTR
1284                 ast_reentrancy_lock(lt);
1285                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1286                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1287                         bt = &lt->backtrace[lt->reentrancy];
1288                 }
1289                 ast_reentrancy_unlock(lt);
1290                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1291 #else
1292                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
1293 #endif
1294         }
1295 #ifdef DETECT_DEADLOCKS
1296         {
1297                 time_t seconds = time(NULL);
1298                 time_t wait_time, reported_wait = 0;
1299                 do {
1300                         res = pthread_rwlock_trywrlock(&t->lock);
1301                         if (res == EBUSY) {
1302                                 wait_time = time(NULL) - seconds;
1303                                 if (wait_time > reported_wait && (wait_time % 5) == 0) {
1304                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
1305                                                 filename, line, func, (int)wait_time, name);
1306                                         ast_reentrancy_lock(lt);
1307 #ifdef HAVE_BKTR
1308                                         __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
1309 #endif
1310                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked  here.\n",
1311                                                         lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
1312                                                         lt->func[lt->reentrancy-1], name);
1313 #ifdef HAVE_BKTR
1314                                         __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
1315 #endif
1316                                         ast_reentrancy_unlock(lt);
1317                                         reported_wait = wait_time;
1318                                 }
1319                                 usleep(200);
1320                         }
1321                 } while (res == EBUSY);
1322         }
1323 #else /* !DETECT_DEADLOCKS */
1324         res = pthread_rwlock_wrlock(&t->lock);
1325 #endif /* !DETECT_DEADLOCKS */
1326
1327         if (!res) {
1328                 ast_reentrancy_lock(lt);
1329                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1330                         lt->file[lt->reentrancy] = filename;
1331                         lt->lineno[lt->reentrancy] = line;
1332                         lt->func[lt->reentrancy] = func;
1333                         lt->thread[lt->reentrancy] = pthread_self();
1334                         lt->reentrancy++;
1335                 }
1336                 ast_reentrancy_unlock(lt);
1337                 if (t->tracking) {
1338                         ast_mark_lock_acquired(t);
1339                 }
1340         } else {
1341 #ifdef HAVE_BKTR
1342                 if (lt->reentrancy) {
1343                         ast_reentrancy_lock(lt);
1344                         bt = &lt->backtrace[lt->reentrancy-1];
1345                         ast_reentrancy_unlock(lt);
1346                 } else {
1347                         bt = NULL;
1348                 }
1349                 if (t->tracking) {
1350                         ast_remove_lock_info(t, bt);
1351                 }
1352 #else
1353                 if (t->tracking) {
1354                         ast_remove_lock_info(t);
1355                 }
1356 #endif
1357                 __ast_mutex_logger("%s line %d (%s): Error obtaining write lock: %s\n",
1358                                 filename, line, func, strerror(res));
1359                 DO_THREAD_CRASH;
1360         }
1361         return res;
1362 }
1363
1364 #define ast_rwlock_timedrdlock(a, b) \
1365         _ast_rwlock_timedrdlock(a, # a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1366
1367 static inline int _ast_rwlock_timedrdlock(ast_rwlock_t *t, const char *name,
1368         const struct timespec *abs_timeout, const char *filename, int line, const char *func)
1369 {
1370         int res;
1371         struct ast_lock_track *lt = &t->track;
1372         int canlog = strcmp(filename, "logger.c") & t->tracking;
1373 #ifdef HAVE_BKTR
1374         struct ast_bt *bt = NULL;
1375 #endif
1376
1377 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1378         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1379                  /* Don't warn abount uninitialized lock.
1380                   * Simple try to initialize it.
1381                   * May be not needed in linux system.
1382                   */
1383                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1384                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1385                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1386                                         filename, line, func, name);
1387                         return res;
1388                 }
1389         }
1390 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1391
1392         if (t->tracking) {
1393 #ifdef HAVE_BKTR
1394                 ast_reentrancy_lock(lt);
1395                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1396                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1397                         bt = &lt->backtrace[lt->reentrancy];
1398                 }
1399                 ast_reentrancy_unlock(lt);
1400                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1401 #else
1402                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
1403 #endif
1404         }
1405 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1406         res = pthread_rwlock_timedrdlock(&t->lock, abs_timeout);
1407 #else
1408         do {
1409                 struct timeval _start = ast_tvnow(), _diff;
1410                 for (;;) {
1411                         if (!(res = pthread_rwlock_tryrdlock(&t->lock))) {
1412                                 break;
1413                         }
1414                         _diff = ast_tvsub(ast_tvnow(), _start);
1415                         if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1416                                 break;
1417                         }
1418                         usleep(1);
1419                 }
1420         } while (0);
1421 #endif
1422         if (!res) {
1423                 ast_reentrancy_lock(lt);
1424                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1425                         lt->file[lt->reentrancy] = filename;
1426                         lt->lineno[lt->reentrancy] = line;
1427                         lt->func[lt->reentrancy] = func;
1428                         lt->thread[lt->reentrancy] = pthread_self();
1429                         lt->reentrancy++;
1430                 }
1431                 ast_reentrancy_unlock(lt);
1432                 if (t->tracking) {
1433                         ast_mark_lock_acquired(t);
1434                 }
1435         } else {
1436 #ifdef HAVE_BKTR
1437                 if (lt->reentrancy) {
1438                         ast_reentrancy_lock(lt);
1439                         bt = &lt->backtrace[lt->reentrancy-1];
1440                         ast_reentrancy_unlock(lt);
1441                 } else {
1442                         bt = NULL;
1443                 }
1444                 if (t->tracking) {
1445                         ast_remove_lock_info(t, bt);
1446                 }
1447 #else
1448                 if (t->tracking) {
1449                         ast_remove_lock_info(t);
1450                 }
1451 #endif
1452                 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
1453                                 filename, line, func, strerror(res));
1454                 DO_THREAD_CRASH;
1455         }
1456         return res;
1457 }
1458
1459 #define ast_rwlock_timedwrlock(a, b) \
1460         _ast_rwlock_timedwrlock(a, # a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1461
1462 static inline int _ast_rwlock_timedwrlock(ast_rwlock_t *t, const char *name,
1463         const struct timespec *abs_timeout, const char *filename, int line, const char *func)
1464 {
1465         int res;
1466         struct ast_lock_track *lt = &t->track;
1467         int canlog = strcmp(filename, "logger.c") & t->tracking;
1468 #ifdef HAVE_BKTR
1469         struct ast_bt *bt = NULL;
1470 #endif
1471
1472 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1473         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1474                  /* Don't warn abount uninitialized lock.
1475                   * Simple try to initialize it.
1476                   * May be not needed in linux system.
1477                   */
1478                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1479                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1480                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1481                                         filename, line, func, name);
1482                         return res;
1483                 }
1484         }
1485 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1486
1487         if (t->tracking) {
1488 #ifdef HAVE_BKTR
1489                 ast_reentrancy_lock(lt);
1490                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1491                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1492                         bt = &lt->backtrace[lt->reentrancy];
1493                 }
1494                 ast_reentrancy_unlock(lt);
1495                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1496 #else
1497                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
1498 #endif
1499         }
1500 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1501         res = pthread_rwlock_timedwrlock(&t->lock, abs_timeout);
1502 #else
1503         do {
1504                 struct timeval _start = ast_tvnow(), _diff;
1505                 for (;;) {
1506                         if (!(res = pthread_rwlock_trywrlock(&t->lock))) {
1507                                 break;
1508                         }
1509                         _diff = ast_tvsub(ast_tvnow(), _start);
1510                         if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1511                                 break;
1512                         }
1513                         usleep(1);
1514                 }
1515         } while (0);
1516 #endif
1517         if (!res) {
1518                 ast_reentrancy_lock(lt);
1519                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1520                         lt->file[lt->reentrancy] = filename;
1521                         lt->lineno[lt->reentrancy] = line;
1522                         lt->func[lt->reentrancy] = func;
1523                         lt->thread[lt->reentrancy] = pthread_self();
1524                         lt->reentrancy++;
1525                 }
1526                 ast_reentrancy_unlock(lt);
1527                 if (t->tracking) {
1528                         ast_mark_lock_acquired(t);
1529                 }
1530         } else {
1531 #ifdef HAVE_BKTR
1532                 if (lt->reentrancy) {
1533                         ast_reentrancy_lock(lt);
1534                         bt = &lt->backtrace[lt->reentrancy-1];
1535                         ast_reentrancy_unlock(lt);
1536                 } else {
1537                         bt = NULL;
1538                 }
1539                 if (t->tracking) {
1540                         ast_remove_lock_info(t, bt);
1541                 }
1542 #else
1543                 if (t->tracking) {
1544                         ast_remove_lock_info(t);
1545                 }
1546 #endif
1547                 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
1548                                 filename, line, func, strerror(res));
1549                 DO_THREAD_CRASH;
1550         }
1551         return res;
1552 }
1553
1554 static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *t, const char *name,
1555         const char *filename, int line, const char *func)
1556 {
1557         int res;
1558         struct ast_lock_track *lt = &t->track;
1559 #ifdef HAVE_BKTR
1560         struct ast_bt *bt = NULL;
1561 #endif
1562 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1563         int canlog = strcmp(filename, "logger.c") & t->tracking;
1564
1565         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1566                  /* Don't warn abount uninitialized lock.
1567                   * Simple try to initialize it.
1568                   * May be not needed in linux system.
1569                   */
1570                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1571                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1572                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1573                                         filename, line, func, name);
1574                         return res;
1575                 }
1576         }
1577 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1578
1579         if (t->tracking) {
1580 #ifdef HAVE_BKTR
1581                 ast_reentrancy_lock(lt);
1582                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1583                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1584                         bt = &lt->backtrace[lt->reentrancy];
1585                 }
1586                 ast_reentrancy_unlock(lt);
1587                 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
1588 #else
1589                 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
1590 #endif
1591         }
1592
1593         if (!(res = pthread_rwlock_tryrdlock(&t->lock))) {
1594                 ast_reentrancy_lock(lt);
1595                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1596                         lt->file[lt->reentrancy] = filename;
1597                         lt->lineno[lt->reentrancy] = line;
1598                         lt->func[lt->reentrancy] = func;
1599                         lt->thread[lt->reentrancy] = pthread_self();
1600                         lt->reentrancy++;
1601                 }
1602                 ast_reentrancy_unlock(lt);
1603                 if (t->tracking) {
1604                         ast_mark_lock_acquired(t);
1605                 }
1606         } else if (t->tracking) {
1607                 ast_mark_lock_failed(t);
1608         }
1609         return res;
1610 }
1611
1612 static inline int _ast_rwlock_trywrlock(ast_rwlock_t *t, const char *name,
1613         const char *filename, int line, const char *func)
1614 {
1615         int res;
1616         struct ast_lock_track *lt= &t->track;
1617 #ifdef HAVE_BKTR
1618         struct ast_bt *bt = NULL;
1619 #endif
1620 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1621         int canlog = strcmp(filename, "logger.c") & t->tracking;
1622
1623         if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1624                  /* Don't warn abount uninitialized lock.
1625                   * Simple try to initialize it.
1626                   * May be not needed in linux system.
1627                   */
1628                 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
1629                 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
1630                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1631                                         filename, line, func, name);
1632                         return res;
1633                 }
1634         }
1635 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1636
1637         if (t->tracking) {
1638 #ifdef HAVE_BKTR
1639                 ast_reentrancy_lock(lt);
1640                 if (lt->reentrancy != AST_MAX_REENTRANCY) {
1641                         ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
1642                         bt = &lt->backtrace[lt->reentrancy];
1643                 }
1644                 ast_reentrancy_unlock(lt);
1645                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1646 #else
1647                 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
1648 #endif
1649         }
1650
1651         if (!(res = pthread_rwlock_trywrlock(&t->lock))) {
1652                 ast_reentrancy_lock(lt);
1653                 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1654                         lt->file[lt->reentrancy] = filename;
1655                         lt->lineno[lt->reentrancy] = line;
1656                         lt->func[lt->reentrancy] = func;
1657                         lt->thread[lt->reentrancy] = pthread_self();
1658                         lt->reentrancy++;
1659                 }
1660                 ast_reentrancy_unlock(lt);
1661                 if (t->tracking) {
1662                         ast_mark_lock_acquired(t);
1663                 }
1664         } else if (t->tracking) {
1665                 ast_mark_lock_failed(t);
1666         }
1667         return res;
1668 }
1669
1670 #else /* !DEBUG_THREADS */
1671
1672 #define CHANNEL_DEADLOCK_AVOIDANCE(chan) \
1673         ast_channel_unlock(chan); \
1674         usleep(1); \
1675         ast_channel_lock(chan);
1676
1677 #define DEADLOCK_AVOIDANCE(lock) \
1678         ast_mutex_unlock(lock); \
1679         usleep(1); \
1680         ast_mutex_lock(lock);
1681
1682 #define DLA_UNLOCK(lock)        ast_mutex_unlock(lock)
1683
1684 #define DLA_LOCK(lock)  ast_mutex_lock(lock)
1685
1686 typedef pthread_mutex_t ast_mutex_t;
1687
1688 #define AST_MUTEX_INIT_VALUE                    ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
1689 #define AST_MUTEX_INIT_VALUE_NOTRACKING         ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
1690
1691 #define ast_mutex_init_notracking(m)            ast_mutex_init(m)
1692
1693 static inline int ast_mutex_init(ast_mutex_t *pmutex)
1694 {
1695         int res;
1696         pthread_mutexattr_t attr;
1697
1698         pthread_mutexattr_init(&attr);
1699         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
1700
1701         res = pthread_mutex_init(pmutex, &attr);
1702         pthread_mutexattr_destroy(&attr);
1703         return res;
1704 }
1705
1706 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
1707
1708 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
1709 {
1710         return pthread_mutex_unlock(pmutex);
1711 }
1712
1713 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
1714 {
1715         return pthread_mutex_destroy(pmutex);
1716 }
1717
1718 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
1719 {
1720         __MTX_PROF(pmutex);
1721 }
1722
1723 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
1724 {
1725         return pthread_mutex_trylock(pmutex);
1726 }
1727
1728 typedef pthread_cond_t ast_cond_t;
1729
1730 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
1731 {
1732         return pthread_cond_init(cond, cond_attr);
1733 }
1734
1735 static inline int ast_cond_signal(ast_cond_t *cond)
1736 {
1737         return pthread_cond_signal(cond);
1738 }
1739
1740 static inline int ast_cond_broadcast(ast_cond_t *cond)
1741 {
1742         return pthread_cond_broadcast(cond);
1743 }
1744
1745 static inline int ast_cond_destroy(ast_cond_t *cond)
1746 {
1747         return pthread_cond_destroy(cond);
1748 }
1749
1750 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
1751 {
1752         return pthread_cond_wait(cond, t);
1753 }
1754
1755 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
1756 {
1757         return pthread_cond_timedwait(cond, t, abstime);
1758 }
1759
1760
1761 typedef pthread_rwlock_t ast_rwlock_t;
1762
1763 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
1764 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
1765 #else
1766 #define AST_RWLOCK_INIT_VALUE { 0 }
1767 #endif
1768
1769 #define ast_rwlock_init_notracking(a) ast_rwlock_init(a)
1770
1771 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
1772 {
1773         int res;
1774         pthread_rwlockattr_t attr;
1775
1776         pthread_rwlockattr_init(&attr);
1777
1778 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
1779         pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
1780 #endif
1781
1782         res = pthread_rwlock_init(prwlock, &attr);
1783         pthread_rwlockattr_destroy(&attr);
1784         return res;
1785 }
1786
1787 static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
1788 {
1789         return pthread_rwlock_destroy(prwlock);
1790 }
1791
1792 static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
1793 {
1794         return pthread_rwlock_unlock(prwlock);
1795 }
1796
1797 static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
1798 {
1799         return pthread_rwlock_rdlock(prwlock);
1800 }
1801
1802 static inline int ast_rwlock_timedrdlock(ast_rwlock_t *prwlock, const struct timespec *abs_timeout)
1803 {
1804         int res;
1805 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1806         res = pthread_rwlock_timedrdlock(prwlock, abs_timeout);
1807 #else
1808         struct timeval _start = ast_tvnow(), _diff;
1809         for (;;) {
1810                 if (!(res = pthread_rwlock_tryrdlock(prwlock))) {
1811                         break;
1812                 }
1813                 _diff = ast_tvsub(ast_tvnow(), _start);
1814                 if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1815                         break;
1816                 }
1817                 usleep(1);
1818         }
1819 #endif
1820         return res;
1821 }
1822
1823 static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
1824 {
1825         return pthread_rwlock_tryrdlock(prwlock);
1826 }
1827
1828 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
1829 {
1830         return pthread_rwlock_wrlock(prwlock);
1831 }
1832
1833 static inline int ast_rwlock_timedwrlock(ast_rwlock_t *prwlock, const struct timespec *abs_timeout)
1834 {
1835         int res;
1836 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1837         res = pthread_rwlock_timedwrlock(prwlock, abs_timeout);
1838 #else
1839         do {
1840                 struct timeval _start = ast_tvnow(), _diff;
1841                 for (;;) {
1842                         if (!(res = pthread_rwlock_trywrlock(prwlock))) {
1843                                 break;
1844                         }
1845                         _diff = ast_tvsub(ast_tvnow(), _start);
1846                         if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1847                                 break;
1848                         }
1849                         usleep(1);
1850                 }
1851         } while (0);
1852 #endif
1853         return res;
1854 }
1855
1856 static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
1857 {
1858         return pthread_rwlock_trywrlock(prwlock);
1859 }
1860
1861 #endif /* !DEBUG_THREADS */
1862
1863 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1864 /*
1865  * If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope constructors
1866  * and destructors to create/destroy global mutexes.
1867  */
1868 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)       \
1869         scope ast_mutex_t mutex = init_val;                     \
1870 static void  __attribute__((constructor)) init_##mutex(void)    \
1871 {                                                               \
1872         if (track)                                              \
1873                 ast_mutex_init(&mutex);                         \
1874         else                                                    \
1875                 ast_mutex_init_notracking(&mutex);              \
1876 }                                                               \
1877                                                                 \
1878 static void  __attribute__((destructor)) fini_##mutex(void)     \
1879 {                                                               \
1880         ast_mutex_destroy(&mutex);                              \
1881 }
1882 #else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
1883 /* By default, use static initialization of mutexes. */
1884 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)       scope ast_mutex_t mutex = init_val
1885 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1886
1887 #ifndef __CYGWIN__      /* temporary disabled for cygwin */
1888 #define pthread_mutex_t         use_ast_mutex_t_instead_of_pthread_mutex_t
1889 #define pthread_cond_t          use_ast_cond_t_instead_of_pthread_cond_t
1890 #endif
1891 #define pthread_mutex_lock      use_ast_mutex_lock_instead_of_pthread_mutex_lock
1892 #define pthread_mutex_unlock    use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
1893 #define pthread_mutex_trylock   use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
1894 #define pthread_mutex_init      use_ast_mutex_init_instead_of_pthread_mutex_init
1895 #define pthread_mutex_destroy   use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
1896 #define pthread_cond_init       use_ast_cond_init_instead_of_pthread_cond_init
1897 #define pthread_cond_destroy    use_ast_cond_destroy_instead_of_pthread_cond_destroy
1898 #define pthread_cond_signal     use_ast_cond_signal_instead_of_pthread_cond_signal
1899 #define pthread_cond_broadcast  use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
1900 #define pthread_cond_wait       use_ast_cond_wait_instead_of_pthread_cond_wait
1901 #define pthread_cond_timedwait  use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
1902
1903 #define AST_MUTEX_DEFINE_STATIC(mutex)                  __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
1904 #define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex)       __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
1905
1906 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
1907
1908 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
1909
1910 #ifndef __linux__
1911 #define pthread_create __use_ast_pthread_create_instead__
1912 #endif
1913
1914 /* Statically declared read/write locks */
1915
1916 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1917 #define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) \
1918         scope ast_rwlock_t rwlock = init_val; \
1919 static void  __attribute__((constructor)) init_##rwlock(void) \
1920 { \
1921         if (track) \
1922                 ast_rwlock_init(&rwlock); \
1923         else \
1924                 ast_rwlock_init_notracking(&rwlock); \
1925 } \
1926 static void  __attribute__((destructor)) fini_##rwlock(void) \
1927 { \
1928         ast_rwlock_destroy(&rwlock); \
1929 }
1930 #else
1931 #define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) \
1932         scope ast_rwlock_t rwlock = init_val
1933 #endif
1934
1935 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE, 1)
1936 #define AST_RWLOCK_DEFINE_STATIC_NOTRACKING(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE_NOTRACKING, 0)
1937
1938 /*
1939  * Support for atomic instructions.
1940  * For platforms that have it, use the native cpu instruction to
1941  * implement them. For other platforms, resort to a 'slow' version
1942  * (defined in utils.c) that protects the atomic instruction with
1943  * a single lock.
1944  * The slow versions is always available, for testing purposes,
1945  * as ast_atomic_fetchadd_int_slow()
1946  */
1947
1948 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
1949
1950 #include "asterisk/inline_api.h"
1951
1952 #if defined(HAVE_OSX_ATOMICS)
1953 #include "libkern/OSAtomic.h"
1954 #endif
1955
1956 /*! \brief Atomically add v to *p and return * the previous value of *p.
1957  * This can be used to handle reference counts, and the return value
1958  * can be used to generate unique identifiers.
1959  */
1960
1961 #if defined(HAVE_GCC_ATOMICS)
1962 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1963 {
1964         return __sync_fetch_and_add(p, v);
1965 })
1966 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1967 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1968 {
1969         return OSAtomicAdd32(v, (int32_t *) p) - v;
1970 })
1971 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1972 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1973 {
1974         return OSAtomicAdd64(v, (int64_t *) p) - v;
1975 #elif defined (__i386__) || defined(__x86_64__)
1976 #ifdef sun
1977 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1978 {
1979         __asm __volatile (
1980         "       lock;  xaddl   %0, %1 ;        "
1981         : "+r" (v),                     /* 0 (result) */
1982           "=m" (*p)                     /* 1 */
1983         : "m" (*p));                    /* 2 */
1984         return (v);
1985 })
1986 #else /* ifndef sun */
1987 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1988 {
1989         __asm __volatile (
1990         "       lock   xaddl   %0, %1 ;        "
1991         : "+r" (v),                     /* 0 (result) */
1992           "=m" (*p)                     /* 1 */
1993         : "m" (*p));                    /* 2 */
1994         return (v);
1995 })
1996 #endif
1997 #else   /* low performance version in utils.c */
1998 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1999 {
2000         return ast_atomic_fetchadd_int_slow(p, v);
2001 })
2002 #endif
2003
2004 /*! \brief decrement *p by 1 and return true if the variable has reached 0.
2005  * Useful e.g. to check if a refcount has reached 0.
2006  */
2007 #if defined(HAVE_GCC_ATOMICS)
2008 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
2009 {
2010         return __sync_sub_and_fetch(p, 1) == 0;
2011 })
2012 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
2013 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
2014 {
2015         return OSAtomicAdd32( -1, (int32_t *) p) == 0;
2016 })
2017 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
2018 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
2019 {
2020         return OSAtomicAdd64( -1, (int64_t *) p) == 0;
2021 #else
2022 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
2023 {
2024         int a = ast_atomic_fetchadd_int(p, -1);
2025         return a == 1; /* true if the value is 0 now (so it was 1 previously) */
2026 })
2027 #endif
2028
2029 #endif /* _ASTERISK_LOCK_H */