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