Doxygen doc updates
[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 General Asterisk channel locking definitions.
21  *
22  * - See \ref LockDef
23  */
24 /* \page LockDef Asterisk thread locking models
25  *
26  * This file provides several different implementation of the functions,
27  * depending on the platform, the use of DEBUG_THREADS, and the way
28  * global mutexes are initialized.
29  * At the moment, we have 3 ways to initialize global mutexes, depending on
30  *
31  *  - \b static: the mutex is assigned the value AST_MUTEX_INIT_VALUE
32  *        this is done at compile time, and is the way used on Linux.
33  *        This method is not applicable to all platforms e.g. when the
34  *        initialization needs that some code is run.
35  *
36  *  - \b on first use: the mutex is assigned a magic value at compile time,
37  *        and ast_mutex_init() is called when this magic value is detected.
38  *        This technique is generally applicable, though it has a bit of
39  *        overhead on each access to check whether initialization is needed.
40  *        On the other hand, the overall cost of a mutex_lock operation
41  *        is such that this overhead is often negligible.
42
43  *  - \b through constructors: for each mutex, a constructor function is
44  *        defined, which then runs when the program (or the module)
45  *        starts. The problem with this approach is that there is a
46  *        lot of code duplication (a new block of code is created for
47  *        each mutex). Also, it does not prevent a user from declaring
48  *        a global mutex without going through the wrapper macros,
49  *        so sane programming practices are still required.
50  *
51  * Eventually we should converge on a single method for all platforms.
52  */
53
54 #ifndef _ASTERISK_LOCK_H
55 #define _ASTERISK_LOCK_H
56
57 #include <pthread.h>
58 #include <netdb.h>
59 #include <time.h>
60 #include <sys/param.h>
61
62 #include "asterisk/logger.h"
63
64 #define AST_PTHREADT_NULL (pthread_t) -1
65 #define AST_PTHREADT_STOP (pthread_t) -2
66
67 #ifdef __APPLE__
68 /* Provide the Linux initializers for MacOS X */
69 #define PTHREAD_MUTEX_RECURSIVE_NP                      PTHREAD_MUTEX_RECURSIVE
70 #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP          { 0x4d555458, \
71                                                         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
72                                                         0x20 } }
73 #endif
74
75 #ifdef BSD
76 #ifdef __GNUC__
77 #define AST_MUTEX_INIT_W_CONSTRUCTORS
78 #else
79 #define AST_MUTEX_INIT_ON_FIRST_USE
80 #endif
81 #endif /* BSD */
82
83 /* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes
84    and will not run without them. */
85 #if defined(__CYGWIN__)
86 #define PTHREAD_MUTEX_RECURSIVE_NP      PTHREAD_MUTEX_RECURSIVE
87 #define PTHREAD_MUTEX_INIT_VALUE        (ast_mutex_t)18
88 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE_NP
89 #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
90 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
91 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE_NP
92 #else
93 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_MUTEX_INITIALIZER
94 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE
95 #endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
96
97 #ifdef SOLARIS
98 #define AST_MUTEX_INIT_W_CONSTRUCTORS
99 #endif
100
101 #ifdef DEBUG_THREADS
102
103 #define __ast_mutex_logger(...) { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); }
104
105 #ifdef THREAD_CRASH
106 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
107 #endif
108
109 #include <errno.h>
110 #include <string.h>
111 #include <stdio.h>
112 #include <unistd.h>
113
114 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, { NULL }, { 0 }, 0, { NULL }, { 0 } }
115
116 #define AST_MAX_REENTRANCY 10
117
118 struct ast_mutex_info {
119         pthread_mutex_t mutex;
120         const char *file[AST_MAX_REENTRANCY];
121         int lineno[AST_MAX_REENTRANCY];
122         int reentrancy;
123         const char *func[AST_MAX_REENTRANCY];
124         pthread_t thread[AST_MAX_REENTRANCY];
125 };
126
127 typedef struct ast_mutex_info ast_mutex_t;
128
129 typedef pthread_cond_t ast_cond_t;
130
131 static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
132                                                 const char *mutex_name, ast_mutex_t *t,
133                                                 pthread_mutexattr_t *attr) 
134 {
135 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
136         int canlog = strcmp(filename, "logger.c");
137
138         if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
139                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
140                                    filename, lineno, func, mutex_name);
141                 __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
142                                    t->file, t->lineno, t->func, mutex_name);
143 #ifdef THREAD_CRASH
144                 DO_THREAD_CRASH;
145 #endif
146                 return 0;
147         }
148 #endif
149
150         t->file[0] = filename;
151         t->lineno[0] = lineno;
152         t->func[0] = func;
153         t->thread[0]  = 0;
154         t->reentrancy = 0;
155
156         return pthread_mutex_init(&t->mutex, attr);
157 }
158
159 static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
160                                            const char *mutex_name, ast_mutex_t *t)
161 {
162         static pthread_mutexattr_t  attr;
163
164         pthread_mutexattr_init(&attr);
165         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
166
167         return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
168 }
169
170 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
171                                                 const char *mutex_name, ast_mutex_t *t)
172 {
173         int res;
174         int canlog = strcmp(filename, "logger.c");
175
176 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
177         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
178                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
179                                    filename, lineno, func, mutex_name);
180         }
181 #endif
182
183         res = pthread_mutex_trylock(&t->mutex);
184         switch (res) {
185         case 0:
186                 pthread_mutex_unlock(&t->mutex);
187                 break;
188         case EINVAL:
189                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
190                                   filename, lineno, func, mutex_name);
191                 break;
192         case EBUSY:
193                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
194                                    filename, lineno, func, mutex_name);
195                 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
196                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
197                 break;
198         }
199
200         if ((res = pthread_mutex_destroy(&t->mutex)))
201                 __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
202                                    filename, lineno, func, strerror(res));
203 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
204         else
205                 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
206 #endif
207         t->file[0] = filename;
208         t->lineno[0] = lineno;
209         t->func[0] = func;
210
211         return res;
212 }
213
214 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
215 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
216  constrictors/destructors to create/destroy mutexes.  */
217 #define __AST_MUTEX_DEFINE(scope,mutex) \
218         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
219 static void  __attribute__ ((constructor)) init_##mutex(void) \
220 { \
221         ast_mutex_init(&mutex); \
222 } \
223 static void  __attribute__ ((destructor)) fini_##mutex(void) \
224 { \
225         ast_mutex_destroy(&mutex); \
226 }
227 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
228 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
229  first use.  The performance impact on FreeBSD should be small since
230  the pthreads library does this itself to initialize errror checking
231  (defaulty type) mutexes.  If nither is defined, the pthreads librariy
232  does the initialization itself on first use. */ 
233 #define __AST_MUTEX_DEFINE(scope,mutex) \
234         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
235 #else /* AST_MUTEX_INIT_W_CONSTRUCTORS */
236 /* By default, use static initialization of mutexes.*/ 
237 #define __AST_MUTEX_DEFINE(scope,mutex) \
238         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
239 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
240
241 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
242                                            const char* mutex_name, ast_mutex_t *t)
243 {
244         int res;
245         int canlog = strcmp(filename, "logger.c");
246
247 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
248         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
249 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
250                 ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
251                                  filename, lineno, func, mutex_name);
252 #endif
253                 ast_mutex_init(t);
254         }
255 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
256
257 #ifdef DETECT_DEADLOCKS
258         {
259                 time_t seconds = time(NULL);
260                 time_t current;
261                 do {
262                         res = pthread_mutex_trylock(&t->mutex);
263                         if (res == EBUSY) {
264                                 current = time(NULL);
265                                 if ((current - seconds) && (!((current - seconds) % 5))) {
266                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
267                                                            filename, lineno, func, (int)(current - seconds), mutex_name);
268                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
269                                                            t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
270                                                            t->func[t->reentrancy-1], mutex_name);
271                                 }
272                                 usleep(200);
273                         }
274                 } while (res == EBUSY);
275         }
276 #else
277         res = pthread_mutex_lock(&t->mutex);
278 #endif /* DETECT_DEADLOCKS */
279
280         if (!res) {
281                 if (t->reentrancy < AST_MAX_REENTRANCY) {
282                         t->file[t->reentrancy] = filename;
283                         t->lineno[t->reentrancy] = lineno;
284                         t->func[t->reentrancy] = func;
285                         t->thread[t->reentrancy] = pthread_self();
286                         t->reentrancy++;
287                 } else {
288                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
289                                                            filename, lineno, func, mutex_name);
290                 }
291         } else {
292                 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
293                                    filename, lineno, func, strerror(errno));
294 #ifdef THREAD_CRASH
295                 DO_THREAD_CRASH;
296 #endif
297         }
298
299         return res;
300 }
301
302 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
303                                               const char* mutex_name, ast_mutex_t *t)
304 {
305         int res;
306         int canlog = strcmp(filename, "logger.c");
307
308 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
309         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
310 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
311
312                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
313                                    filename, lineno, func, mutex_name);
314 #endif
315                 ast_mutex_init(t);
316         }
317 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
318
319         if (!(res = pthread_mutex_trylock(&t->mutex))) {
320                 if (t->reentrancy < AST_MAX_REENTRANCY) {
321                         t->file[t->reentrancy] = filename;
322                         t->lineno[t->reentrancy] = lineno;
323                         t->func[t->reentrancy] = func;
324                         t->thread[t->reentrancy] = pthread_self();
325                         t->reentrancy++;
326                 } else {
327                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
328                                                            filename, lineno, func, mutex_name);
329                 }
330         }
331
332         return res;
333 }
334
335 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
336                                              const char *mutex_name, ast_mutex_t *t)
337 {
338         int res;
339         int canlog = strcmp(filename, "logger.c");
340
341 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
342         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
343                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
344                                    filename, lineno, func, mutex_name);
345         }
346 #endif
347
348         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
349                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
350                                    filename, lineno, func, mutex_name);
351                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
352                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
353 #ifdef THREAD_CRASH
354                 DO_THREAD_CRASH;
355 #endif
356         }
357
358         if (--t->reentrancy < 0) {
359                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
360                                    filename, lineno, func, mutex_name);
361                 t->reentrancy = 0;
362         }
363
364         if (t->reentrancy < AST_MAX_REENTRANCY) {
365                 t->file[t->reentrancy] = NULL;
366                 t->lineno[t->reentrancy] = 0;
367                 t->func[t->reentrancy] = NULL;
368                 t->thread[t->reentrancy] = 0;
369         }
370
371         if ((res = pthread_mutex_unlock(&t->mutex))) {
372                 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
373                                    filename, lineno, func, strerror(res));
374 #ifdef THREAD_CRASH
375                 DO_THREAD_CRASH;
376 #endif
377         }
378
379         return res;
380 }
381
382 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
383                                   const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
384 {
385         return pthread_cond_init(cond, cond_attr);
386 }
387
388 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
389                                     const char *cond_name, ast_cond_t *cond)
390 {
391         return pthread_cond_signal(cond);
392 }
393
394 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
395                                        const char *cond_name, ast_cond_t *cond)
396 {
397         return pthread_cond_broadcast(cond);
398 }
399
400 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
401                                      const char *cond_name, ast_cond_t *cond)
402 {
403         return pthread_cond_destroy(cond);
404 }
405
406 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
407                                   const char *cond_name, const char *mutex_name,
408                                   ast_cond_t *cond, ast_mutex_t *t)
409 {
410         int res;
411         int canlog = strcmp(filename, "logger.c");
412
413 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
414         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
415                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
416                                    filename, lineno, func, mutex_name);
417         }
418 #endif
419
420         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
421                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
422                                    filename, lineno, func, mutex_name);
423                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
424                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
425 #ifdef THREAD_CRASH
426                 DO_THREAD_CRASH;
427 #endif
428         }
429
430         if (--t->reentrancy < 0) {
431                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
432                                    filename, lineno, func, mutex_name);
433                 t->reentrancy = 0;
434         }
435
436         if (t->reentrancy < AST_MAX_REENTRANCY) {
437                 t->file[t->reentrancy] = NULL;
438                 t->lineno[t->reentrancy] = 0;
439                 t->func[t->reentrancy] = NULL;
440                 t->thread[t->reentrancy] = 0;
441         }
442
443         if ((res = pthread_cond_wait(cond, &t->mutex))) {
444                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
445                                    filename, lineno, func, strerror(res));
446 #ifdef THREAD_CRASH
447                 DO_THREAD_CRASH;
448 #endif
449         } else {
450                 if (t->reentrancy < AST_MAX_REENTRANCY) {
451                         t->file[t->reentrancy] = filename;
452                         t->lineno[t->reentrancy] = lineno;
453                         t->func[t->reentrancy] = func;
454                         t->thread[t->reentrancy] = pthread_self();
455                         t->reentrancy++;
456                 } else {
457                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
458                                                            filename, lineno, func, mutex_name);
459                 }
460         }
461
462         return res;
463 }
464
465 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
466                                        const char *cond_name, const char *mutex_name, ast_cond_t *cond,
467                                        ast_mutex_t *t, const struct timespec *abstime)
468 {
469         int res;
470         int canlog = strcmp(filename, "logger.c");
471
472 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
473         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
474                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
475                                    filename, lineno, func, mutex_name);
476         }
477 #endif
478
479         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
480                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
481                                    filename, lineno, func, mutex_name);
482                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
483                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
484 #ifdef THREAD_CRASH
485                 DO_THREAD_CRASH;
486 #endif
487         }
488
489         if (--t->reentrancy < 0) {
490                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
491                                    filename, lineno, func, mutex_name);
492                 t->reentrancy = 0;
493         }
494
495         if (t->reentrancy < AST_MAX_REENTRANCY) {
496                 t->file[t->reentrancy] = NULL;
497                 t->lineno[t->reentrancy] = 0;
498                 t->func[t->reentrancy] = NULL;
499                 t->thread[t->reentrancy] = 0;
500         }
501
502         if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
503                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
504                                    filename, lineno, func, strerror(res));
505 #ifdef THREAD_CRASH
506                 DO_THREAD_CRASH;
507 #endif
508         } else {
509                 if (t->reentrancy < AST_MAX_REENTRANCY) {
510                         t->file[t->reentrancy] = filename;
511                         t->lineno[t->reentrancy] = lineno;
512                         t->func[t->reentrancy] = func;
513                         t->thread[t->reentrancy] = pthread_self();
514                         t->reentrancy++;
515                 } else {
516                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
517                                                            filename, lineno, func, mutex_name);
518                 }
519         }
520
521         return res;
522 }
523
524 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
525 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
526 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
527 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
528 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
529 #define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
530 #define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
531 #define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
532 #define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
533 #define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
534 #define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
535
536 #else /* !DEBUG_THREADS */
537
538
539 #define AST_MUTEX_INIT_VALUE    PTHREAD_MUTEX_INIT_VALUE
540
541
542 typedef pthread_mutex_t ast_mutex_t;
543
544 static inline int ast_mutex_init(ast_mutex_t *pmutex)
545 {
546         pthread_mutexattr_t attr;
547         pthread_mutexattr_init(&attr);
548         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
549         return pthread_mutex_init(pmutex, &attr);
550 }
551
552 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
553
554 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
555 {
556         return pthread_mutex_unlock(pmutex);
557 }
558
559 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
560 {
561         return pthread_mutex_destroy(pmutex);
562 }
563
564 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
565 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
566  constrictors/destructors to create/destroy mutexes.  */ 
567 #define __AST_MUTEX_DEFINE(scope,mutex) \
568         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
569 static void  __attribute__ ((constructor)) init_##mutex(void) \
570 { \
571         ast_mutex_init(&mutex); \
572 } \
573 static void  __attribute__ ((destructor)) fini_##mutex(void) \
574 { \
575         ast_mutex_destroy(&mutex); \
576 }
577
578 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
579 {
580         return pthread_mutex_lock(pmutex);
581 }
582
583 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
584 {
585         return pthread_mutex_trylock(pmutex);
586 }
587
588 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
589 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
590  first use.  The performance impact on FreeBSD should be small since
591  the pthreads library does this itself to initialize errror checking
592  (defaulty type) mutexes.*/ 
593 #define __AST_MUTEX_DEFINE(scope,mutex) \
594         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
595
596 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
597 {
598         if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
599                 ast_mutex_init(pmutex);
600         return pthread_mutex_lock(pmutex);
601 }
602 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
603 {
604         if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
605                 ast_mutex_init(pmutex);
606         return pthread_mutex_trylock(pmutex);
607 }
608 #else
609 /* By default, use static initialization of mutexes.*/ 
610 #define __AST_MUTEX_DEFINE(scope,mutex) \
611         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
612
613 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
614 {
615         return pthread_mutex_lock(pmutex);
616 }
617
618 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
619 {
620         return pthread_mutex_trylock(pmutex);
621 }
622
623 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
624
625 typedef pthread_cond_t ast_cond_t;
626
627 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
628 {
629         return pthread_cond_init(cond, cond_attr);
630 }
631
632 static inline int ast_cond_signal(ast_cond_t *cond)
633 {
634         return pthread_cond_signal(cond);
635 }
636
637 static inline int ast_cond_broadcast(ast_cond_t *cond)
638 {
639         return pthread_cond_broadcast(cond);
640 }
641
642 static inline int ast_cond_destroy(ast_cond_t *cond)
643 {
644         return pthread_cond_destroy(cond);
645 }
646
647 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
648 {
649         return pthread_cond_wait(cond, t);
650 }
651
652 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
653 {
654         return pthread_cond_timedwait(cond, t, abstime);
655 }
656
657 #endif /* !DEBUG_THREADS */
658
659 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
660 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
661 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
662 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
663 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
664 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
665 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
666 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
667 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
668 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
669 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
670 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
671 #define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
672
673 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static,mutex)
674
675 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
676
677 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
678 #ifndef __linux__
679 #define pthread_create __use_ast_pthread_create_instead__
680 #endif
681
682 #endif /* _ASTERISK_LOCK_H */