9e3f3d697911978854c11aeca59f0f36219fed77
[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 <sys/param.h>
53 #ifdef HAVE_BKTR
54 #include <execinfo.h>
55 #endif
56 #include "asterisk/logger.h"
57
58 /* internal macro to profile mutexes. Only computes the delay on
59  * non-blocking calls.
60  */
61 #ifndef HAVE_MTX_PROFILE
62 #define __MTX_PROF(a)   return pthread_mutex_lock((a))
63 #else
64 #define __MTX_PROF(a)   do {                    \
65         int i;                                  \
66         /* profile only non-blocking events */  \
67         ast_mark(mtx_prof, 1);                  \
68         i = pthread_mutex_trylock((a));         \
69         ast_mark(mtx_prof, 0);                  \
70         if (!i)                                 \
71                 return i;                       \
72         else                                    \
73                 return pthread_mutex_lock((a)); \
74         } while (0)
75 #endif  /* HAVE_MTX_PROFILE */
76
77 #define AST_PTHREADT_NULL (pthread_t) -1
78 #define AST_PTHREADT_STOP (pthread_t) -2
79
80 #if defined(SOLARIS) || defined(BSD)
81 #define AST_MUTEX_INIT_W_CONSTRUCTORS
82 #endif /* SOLARIS || BSD */
83
84 /* Asterisk REQUIRES recursive (not error checking) mutexes
85    and will not run without them. */
86 #if defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(HAVE_PTHREAD_MUTEX_RECURSIVE_NP)
87 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
88 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE_NP
89 #else
90 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_MUTEX_INITIALIZER
91 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE
92 #endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
93
94 /*
95  * Definition of ast_mutex_t, ast_cont_d and related functions with/without debugging
96  * (search for DEBUG_THREADS to find the start/end of the sections).
97  *
98  * The non-debug code contains just wrappers for the corresponding pthread functions.
99  * The debug code tracks usage and tries to identify deadlock situations.
100  */
101 #ifdef DEBUG_THREADS
102
103 #define __ast_mutex_logger(...)  do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
104
105 #ifdef THREAD_CRASH
106 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
107 #else
108 #define DO_THREAD_CRASH do { } while (0)
109 #endif
110
111 #include <errno.h>
112
113 #ifdef HAVE_BKTR
114 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
115 #define AST_MUTEX_INIT_VALUE_NOTRACKING \
116                              { PTHREAD_MUTEX_INIT_VALUE, 0, { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
117 #else
118 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
119 #define AST_MUTEX_INIT_VALUE_NOTRACKING \
120                              { PTHREAD_MUTEX_INIT_VALUE, 0, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
121 #endif
122
123 #define AST_MAX_REENTRANCY 10
124
125 struct ast_channel;
126
127 struct ast_mutex_info {
128         pthread_mutex_t mutex;
129         /*! Track which thread holds this lock */
130         unsigned int track:1;
131         const char *file[AST_MAX_REENTRANCY];
132         int lineno[AST_MAX_REENTRANCY];
133         int reentrancy;
134         const char *func[AST_MAX_REENTRANCY];
135         pthread_t thread[AST_MAX_REENTRANCY];
136 #ifdef HAVE_BKTR
137         struct ast_bt backtrace[AST_MAX_REENTRANCY];
138 #endif
139         pthread_mutex_t reentr_mutex;
140 };
141
142 typedef struct ast_mutex_info ast_mutex_t;
143
144 typedef pthread_cond_t ast_cond_t;
145
146 static pthread_mutex_t empty_mutex;
147
148 enum ast_lock_type {
149         AST_MUTEX,
150         AST_RDLOCK,
151         AST_WRLOCK,
152 };
153
154 /*!
155  * \brief Store lock info for the current thread
156  *
157  * This function gets called in ast_mutex_lock() and ast_mutex_trylock() so
158  * that information about this lock can be stored in this thread's
159  * lock info struct.  The lock is marked as pending as the thread is waiting
160  * on the lock.  ast_mark_lock_acquired() will mark it as held by this thread.
161  */
162 #if !defined(LOW_MEMORY)
163 #ifdef HAVE_BKTR
164 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
165         int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt);
166 #else
167 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
168         int line_num, const char *func, const char *lock_name, void *lock_addr);
169 #endif /* HAVE_BKTR */
170
171 #else
172
173 #ifdef HAVE_BKTR
174 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS,BUD)
175 #else
176 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
177 #endif /* HAVE_BKTR */
178 #endif /* !defined(LOW_MEMORY) */
179
180 /*!
181  * \brief Mark the last lock as acquired
182  */
183 #if !defined(LOW_MEMORY)
184 void ast_mark_lock_acquired(void *lock_addr);
185 #else
186 #define ast_mark_lock_acquired(ignore)
187 #endif
188
189 /*!
190  * \brief Mark the last lock as failed (trylock)
191  */
192 #if !defined(LOW_MEMORY)
193 void ast_mark_lock_failed(void *lock_addr);
194 #else
195 #define ast_mark_lock_failed(ignore)
196 #endif
197
198 /*!
199  * \brief remove lock info for the current thread
200  *
201  * this gets called by ast_mutex_unlock so that information on the lock can
202  * be removed from the current thread's lock info struct.
203  */
204 #if !defined(LOW_MEMORY)
205 #ifdef HAVE_BKTR
206 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt);
207 #else
208 void ast_remove_lock_info(void *lock_addr);
209 #endif /* HAVE_BKTR */
210 #else
211 #ifdef HAVE_BKTR
212 #define ast_remove_lock_info(ignore,me)
213 #else
214 #define ast_remove_lock_info(ignore)
215 #endif /* HAVE_BKTR */
216 #endif /* !defined(LOW_MEMORY) */
217
218 #ifdef HAVE_BKTR
219 static inline void __dump_backtrace(struct ast_bt *bt, int canlog)
220 {
221         char **strings;
222
223         ssize_t i;
224
225         strings = backtrace_symbols(bt->addresses, bt->num_frames);
226
227         for (i = 0; i < bt->num_frames; i++)
228                 __ast_mutex_logger("%s\n", strings[i]);
229
230         free(strings);
231 }
232 #endif
233
234 /*!
235  * \brief log info for the current lock with ast_log().
236  *
237  * this function would be mostly for debug. If you come across a lock
238  * that is unexpectedly but momentarily locked, and you wonder who
239  * are fighting with for the lock, this routine could be called, IF
240  * you have the thread debugging stuff turned on.
241  */
242 void log_show_lock(void *this_lock_addr);
243
244 /*!
245  * \brief retrieve lock info for the specified mutex
246  *
247  * this gets called during deadlock avoidance, so that the information may
248  * be preserved as to what location originally acquired the lock.
249  */
250 #if !defined(LOW_MEMORY)
251 int ast_find_lock_info(void *lock_addr, const char **filename, int *lineno, const char **func, const char **mutex_name);
252 #else
253 #define ast_find_lock_info(a,b,c,d,e) -1
254 #endif
255
256 /*!
257  * \brief Unlock a lock briefly
258  *
259  * used during deadlock avoidance, to preserve the original location where
260  * a lock was originally acquired.
261  */
262 #define DEADLOCK_AVOIDANCE(lock) \
263         do { \
264                 const char *__filename, *__func, *__mutex_name; \
265                 int __lineno; \
266                 int __res = ast_find_lock_info(lock, &__filename, &__lineno, &__func, &__mutex_name); \
267                 ast_mutex_unlock(lock); \
268                 usleep(1); \
269                 if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
270                         ast_mutex_lock(lock); \
271                 } else { \
272                         __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
273                 } \
274         } while (0)
275
276 static void __attribute__((constructor)) init_empty_mutex(void)
277 {
278         memset(&empty_mutex, 0, sizeof(empty_mutex));
279 }
280
281 static inline void ast_reentrancy_lock(ast_mutex_t *p_ast_mutex)
282 {
283         pthread_mutex_lock(&p_ast_mutex->reentr_mutex);
284 }
285
286 static inline void ast_reentrancy_unlock(ast_mutex_t *p_ast_mutex)
287 {
288         pthread_mutex_unlock(&p_ast_mutex->reentr_mutex);
289 }
290
291 static inline void ast_reentrancy_init(ast_mutex_t *p_ast_mutex)
292 {
293         int i;
294         pthread_mutexattr_t reentr_attr;
295
296         for (i = 0; i < AST_MAX_REENTRANCY; i++) {
297                 p_ast_mutex->file[i] = NULL;
298                 p_ast_mutex->lineno[i] = 0;
299                 p_ast_mutex->func[i] = NULL;
300                 p_ast_mutex->thread[i] = 0;
301 #ifdef HAVE_BKTR
302                 memset(&p_ast_mutex->backtrace[i], 0, sizeof(p_ast_mutex->backtrace[i]));
303 #endif
304         }
305
306         p_ast_mutex->reentrancy = 0;
307
308         pthread_mutexattr_init(&reentr_attr);
309         pthread_mutexattr_settype(&reentr_attr, AST_MUTEX_KIND);
310         pthread_mutex_init(&p_ast_mutex->reentr_mutex, &reentr_attr);
311         pthread_mutexattr_destroy(&reentr_attr);
312 }
313
314 static inline void delete_reentrancy_cs(ast_mutex_t * p_ast_mutex)
315 {
316         pthread_mutex_destroy(&p_ast_mutex->reentr_mutex);
317 }
318
319 static inline int __ast_pthread_mutex_init(int track, const char *filename, int lineno, const char *func,
320                                                 const char *mutex_name, ast_mutex_t *t) 
321 {
322         int res;
323         pthread_mutexattr_t  attr;
324
325 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
326
327         if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
328 /*
329                 int canlog = strcmp(filename, "logger.c") & track;
330                 __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n",
331                                    filename, lineno, func, mutex_name);
332                 DO_THREAD_CRASH;
333 */
334                 return 0;
335         }
336
337 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
338
339         ast_reentrancy_init(t);
340         t->track = track;
341
342         pthread_mutexattr_init(&attr);
343         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
344
345         res = pthread_mutex_init(&t->mutex, &attr);
346         pthread_mutexattr_destroy(&attr);
347         return res;
348 }
349
350 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
351 #define ast_mutex_init_notracking(pmutex) \
352         __ast_pthread_mutex_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
353
354 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
355                                                 const char *mutex_name, ast_mutex_t *t)
356 {
357         int res;
358         int canlog = strcmp(filename, "logger.c") & t->track;
359
360 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
361         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
362                 /* Don't try to uninitialize non initialized mutex
363                  * This may no effect on linux
364                  * And always ganerate core on *BSD with 
365                  * linked libpthread
366                  * This not error condition if the mutex created on the fly.
367                  */
368                 __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
369                                    filename, lineno, func, mutex_name);
370                 return 0;
371         }
372 #endif
373
374         res = pthread_mutex_trylock(&t->mutex);
375         switch (res) {
376         case 0:
377                 pthread_mutex_unlock(&t->mutex);
378                 break;
379         case EINVAL:
380                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
381                                   filename, lineno, func, mutex_name);
382                 break;
383         case EBUSY:
384                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
385                                    filename, lineno, func, mutex_name);
386                 ast_reentrancy_lock(t);
387                 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
388                             t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
389 #ifdef HAVE_BKTR
390                 __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
391 #endif
392                 ast_reentrancy_unlock(t);
393                 break;
394         }
395
396         if ((res = pthread_mutex_destroy(&t->mutex)))
397                 __ast_mutex_logger("%s line %d (%s): Error destroying mutex %s: %s\n",
398                                    filename, lineno, func, mutex_name, strerror(res));
399 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
400         else
401                 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
402 #endif
403         ast_reentrancy_lock(t);
404         t->file[0] = filename;
405         t->lineno[0] = lineno;
406         t->func[0] = func;
407         t->reentrancy = 0;
408         t->thread[0] = 0;
409 #ifdef HAVE_BKTR
410         memset(&t->backtrace[0], 0, sizeof(t->backtrace[0]));
411 #endif
412         ast_reentrancy_unlock(t);
413         delete_reentrancy_cs(t);
414
415         return res;
416 }
417
418 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
419                                            const char* mutex_name, ast_mutex_t *t)
420 {
421         int res;
422         int canlog = strcmp(filename, "logger.c") & t->track;
423 #ifdef HAVE_BKTR
424         struct ast_bt *bt = NULL;
425 #endif
426
427 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
428         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
429                 /* Don't warn abount uninitialized mutex.
430                  * Simple try to initialize it.
431                  * May be not needed in linux system.
432                  */
433                 res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
434                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
435                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
436                                          filename, lineno, func, mutex_name);
437                         return res;
438                 }               
439         }
440 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
441
442         if (t->track) {
443 #ifdef HAVE_BKTR
444                 ast_reentrancy_lock(t);
445                 ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
446                 bt = &t->backtrace[t->reentrancy];
447                 ast_reentrancy_unlock(t);
448                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
449 #else
450                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
451 #endif
452         }
453
454 #ifdef DETECT_DEADLOCKS
455         {
456                 time_t seconds = time(NULL);
457                 time_t wait_time, reported_wait = 0;
458                 do {
459 #ifdef  HAVE_MTX_PROFILE
460                         ast_mark(mtx_prof, 1);
461 #endif
462                         res = pthread_mutex_trylock(&t->mutex);
463 #ifdef  HAVE_MTX_PROFILE
464                         ast_mark(mtx_prof, 0);
465 #endif
466                         if (res == EBUSY) {
467                                 wait_time = time(NULL) - seconds;
468                                 if (wait_time > reported_wait && (wait_time % 5) == 0) {
469                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
470                                                            filename, lineno, func, (int) wait_time, mutex_name);
471                                         ast_reentrancy_lock(t);
472 #ifdef HAVE_BKTR
473                                         __dump_backtrace(&t->backtrace[t->reentrancy], canlog);
474 #endif
475                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
476                                                            t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
477                                                            t->func[t->reentrancy-1], mutex_name);
478 #ifdef HAVE_BKTR
479                                         __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
480 #endif
481                                         ast_reentrancy_unlock(t);
482                                         reported_wait = wait_time;
483                                 }
484                                 usleep(200);
485                         }
486                 } while (res == EBUSY);
487         }
488 #else
489 #ifdef  HAVE_MTX_PROFILE
490         ast_mark(mtx_prof, 1);
491         res = pthread_mutex_trylock(&t->mutex);
492         ast_mark(mtx_prof, 0);
493         if (res)
494 #endif
495         res = pthread_mutex_lock(&t->mutex);
496 #endif /* DETECT_DEADLOCKS */
497
498         if (!res) {
499                 ast_reentrancy_lock(t);
500                 if (t->reentrancy < AST_MAX_REENTRANCY) {
501                         t->file[t->reentrancy] = filename;
502                         t->lineno[t->reentrancy] = lineno;
503                         t->func[t->reentrancy] = func;
504                         t->thread[t->reentrancy] = pthread_self();
505                         t->reentrancy++;
506                 } else {
507                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
508                                                            filename, lineno, func, mutex_name);
509                 }
510                 ast_reentrancy_unlock(t);
511                 if (t->track)
512                         ast_mark_lock_acquired(&t->mutex);
513         } else {
514 #ifdef HAVE_BKTR
515                 if (t->reentrancy) {
516                         ast_reentrancy_lock(t);
517                         bt = &t->backtrace[t->reentrancy-1];
518                         ast_reentrancy_unlock(t);
519                 } else {
520                         bt = NULL;
521                 }
522                 if (t->track)
523                         ast_remove_lock_info(&t->mutex, bt);
524 #else
525                 if (t->track)
526                         ast_remove_lock_info(&t->mutex);
527 #endif
528                 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
529                                    filename, lineno, func, strerror(res));
530                 DO_THREAD_CRASH;
531         }
532
533         return res;
534 }
535
536 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
537                                               const char* mutex_name, ast_mutex_t *t)
538 {
539         int res;
540         int canlog = strcmp(filename, "logger.c") & t->track;
541 #ifdef HAVE_BKTR
542         struct ast_bt *bt = NULL;
543 #endif
544
545 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
546         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
547                 /* Don't warn abount uninitialized mutex.
548                  * Simple try to initialize it.
549                  * May be not needed in linux system.
550                  */
551                 res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
552                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
553                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
554                                          filename, lineno, func, mutex_name);
555                         return res;
556                 }               
557         }
558 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
559
560         if (t->track) {
561 #ifdef HAVE_BKTR
562                 ast_reentrancy_lock(t);
563                 ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
564                 bt = &t->backtrace[t->reentrancy];
565                 ast_reentrancy_unlock(t);
566                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
567 #else
568                 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
569 #endif
570         }
571
572         if (!(res = pthread_mutex_trylock(&t->mutex))) {
573                 ast_reentrancy_lock(t);
574                 if (t->reentrancy < AST_MAX_REENTRANCY) {
575                         t->file[t->reentrancy] = filename;
576                         t->lineno[t->reentrancy] = lineno;
577                         t->func[t->reentrancy] = func;
578                         t->thread[t->reentrancy] = pthread_self();
579                         t->reentrancy++;
580                 } else {
581                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
582                                            filename, lineno, func, mutex_name);
583                 }
584                 ast_reentrancy_unlock(t);
585                 if (t->track)
586                         ast_mark_lock_acquired(&t->mutex);
587         } else if (t->track) {
588                 ast_mark_lock_failed(&t->mutex);
589         }
590
591         return res;
592 }
593
594 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
595                                              const char *mutex_name, ast_mutex_t *t)
596 {
597         int res;
598         int canlog = strcmp(filename, "logger.c") & t->track;
599 #ifdef HAVE_BKTR
600         struct ast_bt *bt = NULL;
601 #endif
602
603 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
604         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
605                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
606                                    filename, lineno, func, mutex_name);
607                 res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
608                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
609                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
610                                          filename, lineno, func, mutex_name);
611                 }
612                 return res;
613         }
614 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
615
616         ast_reentrancy_lock(t);
617         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
618                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
619                                    filename, lineno, func, mutex_name);
620                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
621                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
622 #ifdef HAVE_BKTR
623                 __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
624 #endif
625                 DO_THREAD_CRASH;
626         }
627
628         if (--t->reentrancy < 0) {
629                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
630                                    filename, lineno, func, mutex_name);
631                 t->reentrancy = 0;
632         }
633
634         if (t->reentrancy < AST_MAX_REENTRANCY) {
635                 t->file[t->reentrancy] = NULL;
636                 t->lineno[t->reentrancy] = 0;
637                 t->func[t->reentrancy] = NULL;
638                 t->thread[t->reentrancy] = 0;
639         }
640
641 #ifdef HAVE_BKTR
642         if (t->reentrancy) {
643                 bt = &t->backtrace[t->reentrancy - 1];
644         }
645 #endif
646         ast_reentrancy_unlock(t);
647
648         if (t->track) {
649 #ifdef HAVE_BKTR
650                 ast_remove_lock_info(&t->mutex, bt);
651 #else
652                 ast_remove_lock_info(&t->mutex);
653 #endif
654         }
655         if ((res = pthread_mutex_unlock(&t->mutex))) {
656                 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
657                                    filename, lineno, func, strerror(res));
658                 DO_THREAD_CRASH;
659         }
660
661         return res;
662 }
663
664 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
665                                   const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
666 {
667         return pthread_cond_init(cond, cond_attr);
668 }
669
670 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
671                                     const char *cond_name, ast_cond_t *cond)
672 {
673         return pthread_cond_signal(cond);
674 }
675
676 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
677                                        const char *cond_name, ast_cond_t *cond)
678 {
679         return pthread_cond_broadcast(cond);
680 }
681
682 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
683                                      const char *cond_name, ast_cond_t *cond)
684 {
685         return pthread_cond_destroy(cond);
686 }
687
688 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
689                                   const char *cond_name, const char *mutex_name,
690                                   ast_cond_t *cond, ast_mutex_t *t)
691 {
692         int res;
693         int canlog = strcmp(filename, "logger.c") & t->track;
694 #ifdef HAVE_BKTR
695         struct ast_bt *bt = NULL;
696 #endif
697
698 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
699         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
700                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
701                                    filename, lineno, func, mutex_name);
702                 res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
703                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
704                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
705                                          filename, lineno, func, mutex_name);
706                 }
707                 return res;
708         }
709 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
710
711         ast_reentrancy_lock(t);
712         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
713                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
714                                    filename, lineno, func, mutex_name);
715                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
716                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
717 #ifdef HAVE_BKTR
718                 __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
719 #endif
720                 DO_THREAD_CRASH;
721         }
722
723         if (--t->reentrancy < 0) {
724                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
725                                    filename, lineno, func, mutex_name);
726                 t->reentrancy = 0;
727         }
728
729         if (t->reentrancy < AST_MAX_REENTRANCY) {
730                 t->file[t->reentrancy] = NULL;
731                 t->lineno[t->reentrancy] = 0;
732                 t->func[t->reentrancy] = NULL;
733                 t->thread[t->reentrancy] = 0;
734         }
735
736 #ifdef HAVE_BKTR
737         if (t->reentrancy) {
738                 bt = &t->backtrace[t->reentrancy - 1];
739         }
740 #endif
741         ast_reentrancy_unlock(t);
742
743         if (t->track) {
744 #ifdef HAVE_BKTR
745                 ast_remove_lock_info(&t->mutex, bt);
746 #else
747                 ast_remove_lock_info(&t->mutex);
748 #endif
749         }
750
751         if ((res = pthread_cond_wait(cond, &t->mutex))) {
752                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
753                                    filename, lineno, func, strerror(res));
754                 DO_THREAD_CRASH;
755         } else {
756                 ast_reentrancy_lock(t);
757                 if (t->reentrancy < AST_MAX_REENTRANCY) {
758                         t->file[t->reentrancy] = filename;
759                         t->lineno[t->reentrancy] = lineno;
760                         t->func[t->reentrancy] = func;
761                         t->thread[t->reentrancy] = pthread_self();
762 #ifdef HAVE_BKTR
763                         ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
764                         bt = &t->backtrace[t->reentrancy];
765 #endif
766                         t->reentrancy++;
767                 } else {
768                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
769                                                            filename, lineno, func, mutex_name);
770                 }
771                 ast_reentrancy_unlock(t);
772
773                 if (t->track) {
774 #ifdef HAVE_BKTR
775                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
776 #else
777                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
778 #endif
779                 }
780         }
781
782         return res;
783 }
784
785 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
786                                        const char *cond_name, const char *mutex_name, ast_cond_t *cond,
787                                        ast_mutex_t *t, const struct timespec *abstime)
788 {
789         int res;
790         int canlog = strcmp(filename, "logger.c") & t->track;
791 #ifdef HAVE_BKTR
792         struct ast_bt *bt = NULL;
793 #endif
794
795 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
796         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
797                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
798                                    filename, lineno, func, mutex_name);
799                 res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
800                 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
801                         __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
802                                          filename, lineno, func, mutex_name);
803                 }
804                 return res;
805         }
806 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
807
808         ast_reentrancy_lock(t);
809         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
810                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
811                                    filename, lineno, func, mutex_name);
812                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
813                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
814 #ifdef HAVE_BKTR
815                 __dump_backtrace(&t->backtrace[t->reentrancy-1], canlog);
816 #endif
817                 DO_THREAD_CRASH;
818         }
819
820         if (--t->reentrancy < 0) {
821                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
822                                    filename, lineno, func, mutex_name);
823                 t->reentrancy = 0;
824         }
825
826         if (t->reentrancy < AST_MAX_REENTRANCY) {
827                 t->file[t->reentrancy] = NULL;
828                 t->lineno[t->reentrancy] = 0;
829                 t->func[t->reentrancy] = NULL;
830                 t->thread[t->reentrancy] = 0;
831         }
832 #ifdef HAVE_BKTR
833         if (t->reentrancy) {
834                 bt = &t->backtrace[t->reentrancy - 1];
835         }
836 #endif
837         ast_reentrancy_unlock(t);
838
839         if (t->track)
840 #ifdef HAVE_BKTR
841                 ast_remove_lock_info(&t->mutex, bt);
842 #else
843                 ast_remove_lock_info(&t->mutex);
844 #endif
845
846         if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
847                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
848                                    filename, lineno, func, strerror(res));
849                 DO_THREAD_CRASH;
850         } else {
851                 ast_reentrancy_lock(t);
852                 if (t->reentrancy < AST_MAX_REENTRANCY) {
853                         t->file[t->reentrancy] = filename;
854                         t->lineno[t->reentrancy] = lineno;
855                         t->func[t->reentrancy] = func;
856                         t->thread[t->reentrancy] = pthread_self();
857 #ifdef HAVE_BKTR
858                         ast_bt_get_addresses(&t->backtrace[t->reentrancy]);
859                         bt = &t->backtrace[t->reentrancy];
860 #endif
861                         t->reentrancy++;
862                 } else {
863                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
864                                                            filename, lineno, func, mutex_name);
865                 }
866                 ast_reentrancy_unlock(t);
867
868                 if (t->track) {
869 #ifdef HAVE_BKTR
870                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex, bt);
871 #else
872                         ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
873 #endif
874                 }
875         }
876
877         return res;
878 }
879
880 #define ast_mutex_destroy(a)                    __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
881 #define ast_mutex_lock(a)                       __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
882 #define ast_mutex_unlock(a)                     __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
883 #define ast_mutex_trylock(a)                    __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
884 #define ast_cond_init(cond, attr)               __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
885 #define ast_cond_destroy(cond)                  __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
886 #define ast_cond_signal(cond)                   __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
887 #define ast_cond_broadcast(cond)                __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
888 #define ast_cond_wait(cond, mutex)              __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
889 #define ast_cond_timedwait(cond, mutex, time)   __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
890
891 struct ast_rwlock_info {
892         pthread_rwlock_t lock;
893 #ifdef HAVE_BKTR
894         struct ast_bt backtrace;
895 #endif
896 };
897
898 typedef struct ast_rwlock_info ast_rwlock_t;
899
900 #define ast_rwlock_init(rwlock)         __ast_rwlock_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
901 #define ast_rwlock_destroy(rwlock)      __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
902 #define ast_rwlock_unlock(a)            _ast_rwlock_unlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
903 #define ast_rwlock_rdlock(a)            _ast_rwlock_rdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
904 #define ast_rwlock_wrlock(a)            _ast_rwlock_wrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
905 #define ast_rwlock_tryrdlock(a)         _ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
906 #define ast_rwlock_trywrlock(a) _ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
907
908 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
909 #ifdef HAVE_BKTR
910 #define AST_RWLOCK_INIT_VALUE { PTHREAD_RWLOCK_INITIALIZER, {{0,},} }
911 #else
912 #define AST_RWLOCK_INIT_VALUE { PTHREAD_RWLOCK_INITIALIZER }
913 #endif /* HAVE_BKTR */
914 #else  /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
915 #ifdef HAVE_BKTR
916 #define AST_RWLOCK_INIT_VALUE { 0 , {0,},}}
917 #else
918 #define AST_RWLOCK_INIT_VALUE { 0 }
919 #endif /* HAVE_BKTR */
920 #endif /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
921
922 static inline int __ast_rwlock_init(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
923 {
924         int res;
925         pthread_rwlockattr_t attr;
926 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
927         int canlog = strcmp(filename, "logger.c");
928
929         if (*prwlock != ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
930                 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
931                                 filename, lineno, func, rwlock_name);
932                 return 0;
933         }
934 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
935         pthread_rwlockattr_init(&attr);
936
937 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
938         pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
939 #endif
940
941         res = pthread_rwlock_init(&prwlock->lock, &attr);
942         pthread_rwlockattr_destroy(&attr);
943         return res;
944 }
945
946
947 static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
948 {
949         int res;
950         int canlog = strcmp(filename, "logger.c");
951
952 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
953         if (*prwlock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
954                 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
955                                    filename, lineno, func, rwlock_name);
956                 return 0;
957         }
958 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
959         
960         if ((res = pthread_rwlock_destroy(&prwlock->lock)))
961                 __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
962                                 filename, lineno, func, rwlock_name, strerror(res));
963
964         return res;
965 }
966
967
968 static inline int _ast_rwlock_unlock(ast_rwlock_t *lock, const char *name,
969         const char *file, int line, const char *func)
970 {
971         int res;
972 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
973         int canlog = strcmp(file, "logger.c");
974
975         if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
976                 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
977                                    file, line, func, name);
978                 res = __ast_rwlock_init(file, line, func, name, lock);
979                 if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
980                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
981                                         file, line, func, name);
982                 }
983                 return res;
984         }
985 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
986         
987         res = pthread_rwlock_unlock(&lock->lock);
988 #ifdef HAVE_BKTR
989         memset(&lock->backtrace, 0, sizeof(lock->backtrace));
990         ast_remove_lock_info(lock, NULL);
991 #else
992         ast_remove_lock_info(lock);
993 #endif
994         return res;
995 }
996
997
998 static inline int _ast_rwlock_rdlock(ast_rwlock_t *lock, const char *name,
999         const char *file, int line, const char *func)
1000 {
1001         int res;
1002 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1003         int canlog = strcmp(file, "logger.c");
1004         
1005         if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
1006                  /* Don't warn abount uninitialized lock.
1007                   * Simple try to initialize it.
1008                   * May be not needed in linux system.
1009                   */
1010                 res = __ast_rwlock_init(file, line, func, name, lock);
1011                 if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
1012                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1013                                         file, line, func, name);
1014                         return res;
1015                 }
1016         }
1017 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1018 #ifdef HAVE_BKTR        
1019         ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock, &lock->backtrace);
1020 #else
1021         ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
1022 #endif
1023         res = pthread_rwlock_rdlock(&lock->lock);
1024         if (!res)
1025                 ast_mark_lock_acquired(lock);
1026         else
1027 #ifdef HAVE_BKTR
1028                 ast_remove_lock_info(lock, NULL);
1029 #else
1030                 ast_remove_lock_info(lock);
1031 #endif
1032         return res;
1033 }
1034
1035
1036 static inline int _ast_rwlock_wrlock(ast_rwlock_t *lock, const char *name,
1037         const char *file, int line, const char *func)
1038 {
1039         int res;
1040 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1041         int canlog = strcmp(file, "logger.c");
1042         
1043         if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
1044                  /* Don't warn abount uninitialized lock.
1045                   * Simple try to initialize it.
1046                   * May be not needed in linux system.
1047                   */
1048                 res = __ast_rwlock_init(file, line, func, name, lock);
1049                 if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
1050                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1051                                         file, line, func, name);
1052                         return res;
1053                 }
1054         }
1055 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1056 #ifdef HAVE_BKTR
1057         ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock, &lock->backtrace);
1058 #else
1059         ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
1060 #endif
1061         res = pthread_rwlock_wrlock(&lock->lock);
1062         if (!res)
1063                 ast_mark_lock_acquired(lock);
1064         else
1065 #ifdef HAVE_BKTR
1066                 ast_remove_lock_info(lock, NULL);
1067 #else
1068                 ast_remove_lock_info(lock);
1069 #endif
1070         return res;
1071 }
1072
1073
1074 static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *lock, const char *name,
1075         const char *file, int line, const char *func)
1076 {
1077         int res;
1078 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1079         int canlog = strcmp(file, "logger.c");
1080         
1081         if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
1082                  /* Don't warn abount uninitialized lock.
1083                   * Simple try to initialize it.
1084                   * May be not needed in linux system.
1085                   */
1086                 res = __ast_rwlock_init(file, line, func, name, lock);
1087                 if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
1088                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1089                                         file, line, func, name);
1090                         return res;
1091                 }
1092         }
1093 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1094 #ifdef HAVE_BKTR
1095         ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock, &lock->backtrace);
1096 #else
1097         ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
1098 #endif
1099         res = pthread_rwlock_tryrdlock(&lock->lock);
1100         if (!res)
1101                 ast_mark_lock_acquired(lock);
1102         else
1103 #ifdef HAVE_BKTR
1104                 ast_remove_lock_info(lock, NULL);
1105 #else
1106                 ast_remove_lock_info(lock);
1107 #endif
1108         return res;
1109 }
1110
1111
1112 static inline int _ast_rwlock_trywrlock(ast_rwlock_t *lock, const char *name,
1113         const char *file, int line, const char *func)
1114 {
1115         int res;
1116 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
1117         int canlog = strcmp(file, "logger.c");
1118         
1119         if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
1120                  /* Don't warn abount uninitialized lock.
1121                   * Simple try to initialize it.
1122                   * May be not needed in linux system.
1123                   */
1124                 res = __ast_rwlock_init(file, line, func, name, lock);
1125                 if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
1126                         __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
1127                                         file, line, func, name);
1128                         return res;
1129                 }
1130         }
1131 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1132 #ifdef HAVE_BKTR
1133         ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock, &lock->backtrace);
1134 #else
1135         ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
1136 #endif
1137         res = pthread_rwlock_trywrlock(&lock->lock);
1138         if (!res)
1139                 ast_mark_lock_acquired(lock);
1140         else
1141 #ifdef HAVE_BKTR
1142                 ast_remove_lock_info(lock, NULL);
1143 #else
1144                 ast_remove_lock_info(lock);
1145 #endif
1146         return res;
1147 }
1148
1149 #else /* !DEBUG_THREADS */
1150
1151 #define DEADLOCK_AVOIDANCE(lock) \
1152         ast_mutex_lock(lock); \
1153         usleep(1); \
1154         ast_mutex_unlock(lock);
1155
1156 typedef pthread_mutex_t ast_mutex_t;
1157
1158 #define AST_MUTEX_INIT_VALUE                    ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
1159 #define AST_MUTEX_INIT_VALUE_NOTRACKING         ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
1160
1161 #define ast_mutex_init_notracking(m)            ast_mutex_init(m)
1162
1163 static inline int ast_mutex_init(ast_mutex_t *pmutex)
1164 {
1165         int res;
1166         pthread_mutexattr_t attr;
1167
1168         pthread_mutexattr_init(&attr);
1169         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
1170
1171         res = pthread_mutex_init(pmutex, &attr);
1172         pthread_mutexattr_destroy(&attr);
1173         return res;
1174 }
1175
1176 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
1177
1178 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
1179 {
1180         return pthread_mutex_unlock(pmutex);
1181 }
1182
1183 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
1184 {
1185         return pthread_mutex_destroy(pmutex);
1186 }
1187
1188 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
1189 {
1190         __MTX_PROF(pmutex);
1191 }
1192
1193 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
1194 {
1195         return pthread_mutex_trylock(pmutex);
1196 }
1197
1198 typedef pthread_cond_t ast_cond_t;
1199
1200 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
1201 {
1202         return pthread_cond_init(cond, cond_attr);
1203 }
1204
1205 static inline int ast_cond_signal(ast_cond_t *cond)
1206 {
1207         return pthread_cond_signal(cond);
1208 }
1209
1210 static inline int ast_cond_broadcast(ast_cond_t *cond)
1211 {
1212         return pthread_cond_broadcast(cond);
1213 }
1214
1215 static inline int ast_cond_destroy(ast_cond_t *cond)
1216 {
1217         return pthread_cond_destroy(cond);
1218 }
1219
1220 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
1221 {
1222         return pthread_cond_wait(cond, t);
1223 }
1224
1225 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
1226 {
1227         return pthread_cond_timedwait(cond, t, abstime);
1228 }
1229
1230
1231 typedef pthread_rwlock_t ast_rwlock_t;
1232
1233 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
1234 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
1235 #else
1236 #define AST_RWLOCK_INIT_VALUE { 0 }
1237 #endif
1238
1239 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
1240 {
1241         int res;
1242         pthread_rwlockattr_t attr;
1243
1244         pthread_rwlockattr_init(&attr);
1245
1246 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
1247         pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
1248 #endif
1249
1250         res = pthread_rwlock_init(prwlock, &attr);
1251         pthread_rwlockattr_destroy(&attr);
1252         return res;
1253 }
1254
1255 static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
1256 {
1257         return pthread_rwlock_destroy(prwlock);
1258 }
1259
1260 static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
1261 {
1262         return pthread_rwlock_unlock(prwlock);
1263 }
1264
1265 static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
1266 {
1267         return pthread_rwlock_rdlock(prwlock);
1268 }
1269
1270 static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
1271 {
1272         return pthread_rwlock_tryrdlock(prwlock);
1273 }
1274
1275 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
1276 {
1277         return pthread_rwlock_wrlock(prwlock);
1278 }
1279
1280 static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
1281 {
1282         return pthread_rwlock_trywrlock(prwlock);
1283 }
1284
1285 #endif /* !DEBUG_THREADS */
1286
1287 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
1288 /*
1289  * If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope constructors
1290  * and destructors to create/destroy global mutexes.
1291  */
1292 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)       \
1293         scope ast_mutex_t mutex = init_val;                     \
1294 static void  __attribute__ ((constructor)) init_##mutex(void)   \
1295 {                                                               \
1296         if (track)                                              \
1297                 ast_mutex_init(&mutex);                         \
1298         else                                                    \
1299                 ast_mutex_init_notracking(&mutex);              \
1300 }                                                               \
1301                                                                 \
1302 static void  __attribute__ ((destructor)) fini_##mutex(void)    \
1303 {                                                               \
1304         ast_mutex_destroy(&mutex);                              \
1305 }
1306 #else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
1307 /* By default, use static initialization of mutexes. */ 
1308 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)       scope ast_mutex_t mutex = init_val
1309 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
1310
1311 #ifndef __CYGWIN__      /* temporary disabled for cygwin */
1312 #define pthread_mutex_t         use_ast_mutex_t_instead_of_pthread_mutex_t
1313 #define pthread_cond_t          use_ast_cond_t_instead_of_pthread_cond_t
1314 #endif
1315 #define pthread_mutex_lock      use_ast_mutex_lock_instead_of_pthread_mutex_lock
1316 #define pthread_mutex_unlock    use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
1317 #define pthread_mutex_trylock   use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
1318 #define pthread_mutex_init      use_ast_mutex_init_instead_of_pthread_mutex_init
1319 #define pthread_mutex_destroy   use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
1320 #define pthread_cond_init       use_ast_cond_init_instead_of_pthread_cond_init
1321 #define pthread_cond_destroy    use_ast_cond_destroy_instead_of_pthread_cond_destroy
1322 #define pthread_cond_signal     use_ast_cond_signal_instead_of_pthread_cond_signal
1323 #define pthread_cond_broadcast  use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
1324 #define pthread_cond_wait       use_ast_cond_wait_instead_of_pthread_cond_wait
1325 #define pthread_cond_timedwait  use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
1326
1327 #define AST_MUTEX_DEFINE_STATIC(mutex)                  __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
1328 #define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex)       __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
1329
1330 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
1331
1332 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
1333
1334 #ifndef __linux__
1335 #define pthread_create __use_ast_pthread_create_instead__
1336 #endif
1337
1338 /* Statically declared read/write locks */
1339
1340 #ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
1341 #define __AST_RWLOCK_DEFINE(scope, rwlock)                      \
1342         scope ast_rwlock_t rwlock;                              \
1343 static void  __attribute__ ((constructor)) init_##rwlock(void)  \
1344 {                                                               \
1345         ast_rwlock_init(&rwlock);                               \
1346 }                                                               \
1347                                                                 \
1348 static void  __attribute__ ((destructor)) fini_##rwlock(void)   \
1349 {                                                               \
1350         ast_rwlock_destroy(&rwlock);                            \
1351 }
1352 #else
1353 #define __AST_RWLOCK_DEFINE(scope, rwlock)      scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE
1354 #endif
1355
1356 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
1357
1358 /*
1359  * Support for atomic instructions.
1360  * For platforms that have it, use the native cpu instruction to
1361  * implement them. For other platforms, resort to a 'slow' version
1362  * (defined in utils.c) that protects the atomic instruction with
1363  * a single lock.
1364  * The slow versions is always available, for testing purposes,
1365  * as ast_atomic_fetchadd_int_slow()
1366  */
1367
1368 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
1369
1370 #include "asterisk/inline_api.h"
1371
1372 #if defined(HAVE_OSX_ATOMICS)
1373 #include "libkern/OSAtomic.h"
1374 #endif
1375
1376 /*! \brief Atomically add v to *p and return * the previous value of *p.
1377  * This can be used to handle reference counts, and the return value
1378  * can be used to generate unique identifiers.
1379  */
1380
1381 #if defined(HAVE_GCC_ATOMICS)
1382 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1383 {
1384         return __sync_fetch_and_add(p, v);
1385 })
1386 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1387 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1388 {
1389         return OSAtomicAdd32(v, (int32_t *) p) - v;
1390 })
1391 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1392 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1393 {
1394         return OSAtomicAdd64(v, (int64_t *) p) - v;
1395 #elif defined (__i386__) || defined(__x86_64__)
1396 #ifdef sun
1397 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1398 {
1399         __asm __volatile (
1400         "       lock;  xaddl   %0, %1 ;        "
1401         : "+r" (v),                     /* 0 (result) */   
1402           "=m" (*p)                     /* 1 */
1403         : "m" (*p));                    /* 2 */
1404         return (v);
1405 })
1406 #else /* ifndef sun */
1407 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1408 {
1409         __asm __volatile (
1410         "       lock   xaddl   %0, %1 ;        "
1411         : "+r" (v),                     /* 0 (result) */   
1412           "=m" (*p)                     /* 1 */
1413         : "m" (*p));                    /* 2 */
1414         return (v);
1415 })
1416 #endif
1417 #else   /* low performance version in utils.c */
1418 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
1419 {
1420         return ast_atomic_fetchadd_int_slow(p, v);
1421 })
1422 #endif
1423
1424 /*! \brief decrement *p by 1 and return true if the variable has reached 0.
1425  * Useful e.g. to check if a refcount has reached 0.
1426  */
1427 #if defined(HAVE_GCC_ATOMICS)
1428 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1429 {
1430         return __sync_sub_and_fetch(p, 1) == 0;
1431 })
1432 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
1433 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1434 {
1435         return OSAtomicAdd32( -1, (int32_t *) p) == 0;
1436 })
1437 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
1438 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1439 {
1440         return OSAtomicAdd64( -1, (int64_t *) p) == 0;
1441 #else
1442 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
1443 {
1444         int a = ast_atomic_fetchadd_int(p, -1);
1445         return a == 1; /* true if the value is 0 now (so it was 1 previously) */
1446 })
1447 #endif
1448
1449 #ifndef DEBUG_CHANNEL_LOCKS
1450 /*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined 
1451         in the Makefile, print relevant output for debugging */
1452 #define ast_channel_lock(x)             ast_mutex_lock(&x->lock_dont_use)
1453 /*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined 
1454         in the Makefile, print relevant output for debugging */
1455 #define ast_channel_unlock(x)           ast_mutex_unlock(&x->lock_dont_use)
1456 /*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined 
1457         in the Makefile, print relevant output for debugging */
1458 #define ast_channel_trylock(x)          ast_mutex_trylock(&x->lock_dont_use)
1459 #else
1460
1461 #define ast_channel_lock(a) __ast_channel_lock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1462 /*! \brief Lock AST channel (and print debugging output)
1463 \note You need to enable DEBUG_CHANNEL_LOCKS for this function */
1464 int __ast_channel_lock(struct ast_channel *chan, const char *file, int lineno, const char *func);
1465
1466 #define ast_channel_unlock(a) __ast_channel_unlock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1467 /*! \brief Unlock AST channel (and print debugging output)
1468 \note You need to enable DEBUG_CHANNEL_LOCKS for this function
1469 */
1470 int __ast_channel_unlock(struct ast_channel *chan, const char *file, int lineno, const char *func);
1471
1472 #define ast_channel_trylock(a) __ast_channel_trylock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
1473 /*! \brief Lock AST channel (and print debugging output)
1474 \note   You need to enable DEBUG_CHANNEL_LOCKS for this function */
1475 int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func);
1476 #endif
1477
1478 #endif /* _ASTERISK_LOCK_H */