add 'ast_cond_t' type for pthread condition variables, and appropriate API wrappers
[asterisk/asterisk.git] / include / asterisk / lock.h
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, 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
23 #ifndef _ASTERISK_LOCK_H
24 #define _ASTERISK_LOCK_H
25
26 #include <pthread.h>
27 #include <netdb.h>
28 #include <time.h>
29 #include <sys/param.h>
30
31 #include "asterisk/logger.h"
32
33 #define AST_PTHREADT_NULL (pthread_t) -1
34 #define AST_PTHREADT_STOP (pthread_t) -2
35
36 #ifdef __APPLE__
37 /* Provide the Linux initializers for MacOS X */
38 #define PTHREAD_MUTEX_RECURSIVE_NP                      PTHREAD_MUTEX_RECURSIVE
39 #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP           { 0x4d555458, \
40                                                                                                            { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
41                                                                                                                  0x20 } }
42 #endif
43
44 #ifdef BSD
45 #ifdef __GNUC__
46 #define AST_MUTEX_INIT_W_CONSTRUCTORS
47 #else
48 #define AST_MUTEX_INIT_ON_FIRST_USE
49 #endif
50 #endif /* BSD */
51
52 /* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes
53    and will not run without them. */
54 #ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
55 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
56 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE_NP
57 #else
58 #define PTHREAD_MUTEX_INIT_VALUE        PTHREAD_MUTEX_INITIALIZER
59 #define AST_MUTEX_KIND                  PTHREAD_MUTEX_RECURSIVE
60 #endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
61
62 #ifdef SOLARIS
63 #define AST_MUTEX_INIT_W_CONSTRUCTORS
64 #endif
65
66 #ifdef DEBUG_THREADS
67
68 #define __ast_mutex_logger(...) { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); }
69
70 #ifdef THREAD_CRASH
71 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
72 #endif
73
74 #include <errno.h>
75 #include <string.h>
76 #include <stdio.h>
77 #include <unistd.h>
78
79 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, { NULL }, { 0 }, 0, { NULL }, { 0 } }
80
81 #define AST_MAX_REENTRANCY 10
82
83 struct ast_mutex_info {
84         pthread_mutex_t mutex;
85         const char *file[AST_MAX_REENTRANCY];
86         int lineno[AST_MAX_REENTRANCY];
87         int reentrancy;
88         const char *func[AST_MAX_REENTRANCY];
89         pthread_t thread[AST_MAX_REENTRANCY];
90 };
91
92 typedef struct ast_mutex_info ast_mutex_t;
93
94 typedef pthread_cond_t ast_cond_t;
95
96 static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
97                                                 const char *mutex_name, ast_mutex_t *t,
98                                                 pthread_mutexattr_t *attr) 
99 {
100 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
101         int canlog = strcmp(filename, "logger.c");
102
103         if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
104                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
105                                    filename, lineno, func, mutex_name);
106                 __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
107                                    t->file, t->lineno, t->func, mutex_name);
108 #ifdef THREAD_CRASH
109                 DO_THREAD_CRASH;
110 #endif
111                 return 0;
112         }
113 #endif
114
115         t->file[0] = filename;
116         t->lineno[0] = lineno;
117         t->func[0] = func;
118         t->thread[0]  = 0;
119         t->reentrancy = 0;
120
121         return pthread_mutex_init(&t->mutex, attr);
122 }
123
124 static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
125                                            const char *mutex_name, ast_mutex_t *t)
126 {
127         static pthread_mutexattr_t  attr;
128
129         pthread_mutexattr_init(&attr);
130         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
131
132         return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
133 }
134
135 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
136                                                 const char *mutex_name, ast_mutex_t *t)
137 {
138         int res;
139         int canlog = strcmp(filename, "logger.c");
140
141 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
142         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
143                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
144                                    filename, lineno, func, mutex_name);
145         }
146 #endif
147
148         res = pthread_mutex_trylock(&t->mutex);
149         switch (res) {
150         case 0:
151                 pthread_mutex_unlock(&t->mutex);
152                 break;
153         case EINVAL:
154                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
155                                   filename, lineno, func, mutex_name);
156                 break;
157         case EBUSY:
158                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
159                                    filename, lineno, func, mutex_name);
160                 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
161                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
162                 break;
163         }
164
165         if ((res = pthread_mutex_destroy(&t->mutex)))
166                 __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
167                                    filename, lineno, func, strerror(res));
168 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
169         else
170                 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
171 #endif
172         t->file[0] = filename;
173         t->lineno[0] = lineno;
174         t->func[0] = func;
175
176         return res;
177 }
178
179 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
180 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
181  constrictors/destructors to create/destroy mutexes.  */
182 #define __AST_MUTEX_DEFINE(scope,mutex) \
183         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
184 static void  __attribute__ ((constructor)) init_##mutex(void) \
185 { \
186         ast_mutex_init(&mutex); \
187 } \
188 static void  __attribute__ ((destructor)) fini_##mutex(void) \
189 { \
190         ast_mutex_destroy(&mutex); \
191 }
192 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
193 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
194  first use.  The performance impact on FreeBSD should be small since
195  the pthreads library does this itself to initialize errror checking
196  (defaulty type) mutexes.  If nither is defined, the pthreads librariy
197  does the initialization itself on first use. */ 
198 #define __AST_MUTEX_DEFINE(scope,mutex) \
199         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
200 #else /* AST_MUTEX_INIT_W_CONSTRUCTORS */
201 /* By default, use static initialization of mutexes.*/ 
202 #define __AST_MUTEX_DEFINE(scope,mutex) \
203         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
204 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
205
206 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
207                                            const char* mutex_name, ast_mutex_t *t)
208 {
209         int res;
210         int canlog = strcmp(filename, "logger.c");
211
212 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
213         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
214 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
215                 ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
216                                  filename, lineno, func, mutex_name);
217 #endif
218                 ast_mutex_init(t);
219         }
220 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
221
222 #ifdef DETECT_DEADLOCKS
223         {
224                 time_t seconds = time(NULL);
225                 time_t current;
226                 do {
227                         res = pthread_mutex_trylock(&t->mutex);
228                         if (res == EBUSY) {
229                                 current = time(NULL);
230                                 if ((current - seconds) && (!((current - seconds) % 5))) {
231                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
232                                                            filename, lineno, func, (int)(current - seconds), mutex_name);
233                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
234                                                            t->file, t->lineno, t->func, mutex_name);
235                                 }
236                                 usleep(200);
237                         }
238                 } while (res == EBUSY);
239         }
240 #else
241         res = pthread_mutex_lock(&t->mutex);
242 #endif /* DETECT_DEADLOCKS */
243
244         if (!res) {
245                 if (t->reentrancy < AST_MAX_REENTRANCY) {
246                         t->file[t->reentrancy] = filename;
247                         t->lineno[t->reentrancy] = lineno;
248                         t->func[t->reentrancy] = func;
249                         t->thread[t->reentrancy] = pthread_self();
250                         t->reentrancy++;
251                 } else {
252                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
253                                                            filename, lineno, func, mutex_name);
254                 }
255         } else {
256                 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
257                                    filename, lineno, func, strerror(errno));
258 #ifdef THREAD_CRASH
259                 DO_THREAD_CRASH;
260 #endif
261         }
262
263         return res;
264 }
265
266 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
267                                               const char* mutex_name, ast_mutex_t *t)
268 {
269         int res;
270         int canlog = strcmp(filename, "logger.c");
271
272 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
273         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
274 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
275
276                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
277                                    filename, lineno, func, mutex_name);
278 #endif
279                 ast_mutex_init(t);
280         }
281 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
282
283         if (!(res = pthread_mutex_trylock(&t->mutex))) {
284                 if (t->reentrancy < AST_MAX_REENTRANCY) {
285                         t->file[t->reentrancy] = filename;
286                         t->lineno[t->reentrancy] = lineno;
287                         t->func[t->reentrancy] = func;
288                         t->thread[t->reentrancy] = pthread_self();
289                         t->reentrancy++;
290                 } else {
291                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
292                                                            filename, lineno, func, mutex_name);
293                 }
294         }
295
296         return res;
297 }
298
299 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
300                                              const char *mutex_name, ast_mutex_t *t)
301 {
302         int res;
303         int canlog = strcmp(filename, "logger.c");
304
305 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
306         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
307                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
308                                    filename, lineno, func, mutex_name);
309         }
310 #endif
311
312         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
313                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
314                                    filename, lineno, func, mutex_name);
315                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
316                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
317 #ifdef THREAD_CRASH
318                 DO_THREAD_CRASH;
319 #endif
320         }
321
322         if (--t->reentrancy < 0) {
323                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
324                                    filename, lineno, func, mutex_name);
325                 t->reentrancy = 0;
326         }
327
328         if (t->reentrancy < AST_MAX_REENTRANCY) {
329                 t->file[t->reentrancy] = NULL;
330                 t->lineno[t->reentrancy] = 0;
331                 t->func[t->reentrancy] = NULL;
332                 t->thread[t->reentrancy] = 0;
333         }
334
335         if ((res = pthread_mutex_unlock(&t->mutex))) {
336                 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
337                                    filename, lineno, func, strerror(res));
338 #ifdef THREAD_CRASH
339                 DO_THREAD_CRASH;
340 #endif
341         }
342
343         return res;
344 }
345
346 static inline int __ast_pthread_cond_init(const char *filename, int lineno, const char *func,
347                                           const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
348 {
349         return pthread_cond_init(cond, cond_attr);
350 }
351
352 static inline int __ast_pthread_cond_signal(const char *filename, int lineno, const char *func,
353                                             const char *cond_name, ast_cond_t *cond)
354 {
355         return pthread_cond_signal(cond);
356 }
357
358 static inline int __ast_pthread_cond_broadcast(const char *filename, int lineno, const char *func,
359                                                const char *cond_name, ast_cond_t *cond)
360 {
361         return pthread_cond_broadcast(cond);
362 }
363
364 static inline int __ast_pthread_cond_destroy(const char *filename, int lineno, const char *func,
365                                              const char *cond_name, ast_cond_t *cond)
366 {
367         return pthread_cond_destroy(cond);
368 }
369
370 static inline int __ast_pthread_cond_wait(const char *filename, int lineno, const char *func,
371                                           const char *cond_name, const char *mutex_name,
372                                           ast_cond_t *cond, ast_mutex_t *t)
373 {
374         int res;
375         int canlog = strcmp(filename, "logger.c");
376
377 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
378         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
379                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
380                                    filename, lineno, func, mutex_name);
381         }
382 #endif
383
384         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
385                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
386                                    filename, lineno, func, mutex_name);
387                 __ast_mutex_logger("%s line %d (%s): '%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 THREAD_CRASH
390                 DO_THREAD_CRASH;
391 #endif
392         }
393
394         if (--t->reentrancy < 0) {
395                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
396                                    filename, lineno, func, mutex_name);
397                 t->reentrancy = 0;
398         }
399
400         if (t->reentrancy < AST_MAX_REENTRANCY) {
401                 t->file[t->reentrancy] = NULL;
402                 t->lineno[t->reentrancy] = 0;
403                 t->func[t->reentrancy] = NULL;
404                 t->thread[t->reentrancy] = 0;
405         }
406
407         if ((res = pthread_cond_wait(cond, &t->mutex))) {
408                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
409                                    filename, lineno, func, strerror(res));
410 #ifdef THREAD_CRASH
411                 DO_THREAD_CRASH;
412 #endif
413         } else {
414                 if (t->reentrancy < AST_MAX_REENTRANCY) {
415                         t->file[t->reentrancy] = filename;
416                         t->lineno[t->reentrancy] = lineno;
417                         t->func[t->reentrancy] = func;
418                         t->thread[t->reentrancy] = pthread_self();
419                         t->reentrancy++;
420                 } else {
421                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
422                                                            filename, lineno, func, mutex_name);
423                 }
424         }
425
426         return res;
427 }
428
429 static inline int __ast_pthread_cond_timedwait(const char *filename, int lineno, const char *func,
430                                                const char *cond_name, const char *mutex_name, ast_cond_t *cond,
431                                                ast_mutex_t *t, const struct timespec *abstime)
432 {
433         int res;
434         int canlog = strcmp(filename, "logger.c");
435
436 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
437         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
438                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
439                                    filename, lineno, func, mutex_name);
440         }
441 #endif
442
443         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
444                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
445                                    filename, lineno, func, mutex_name);
446                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
447                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
448 #ifdef THREAD_CRASH
449                 DO_THREAD_CRASH;
450 #endif
451         }
452
453         if (--t->reentrancy < 0) {
454                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
455                                    filename, lineno, func, mutex_name);
456                 t->reentrancy = 0;
457         }
458
459         if (t->reentrancy < AST_MAX_REENTRANCY) {
460                 t->file[t->reentrancy] = NULL;
461                 t->lineno[t->reentrancy] = 0;
462                 t->func[t->reentrancy] = NULL;
463                 t->thread[t->reentrancy] = 0;
464         }
465
466         if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime))) {
467                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
468                                    filename, lineno, func, strerror(res));
469 #ifdef THREAD_CRASH
470                 DO_THREAD_CRASH;
471 #endif
472         } else {
473                 if (t->reentrancy < AST_MAX_REENTRANCY) {
474                         t->file[t->reentrancy] = filename;
475                         t->lineno[t->reentrancy] = lineno;
476                         t->func[t->reentrancy] = func;
477                         t->thread[t->reentrancy] = pthread_self();
478                         t->reentrancy++;
479                 } else {
480                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
481                                                            filename, lineno, func, mutex_name);
482                 }
483         }
484
485         return res;
486 }
487
488 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
489 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
490 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
491 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
492 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
493 #define ast_cond_init(cond, attr) __ast_pthread_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
494 #define ast_cond_destroy(cond) __ast_pthread_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
495 #define ast_cond_signal(cond) __ast_pthread_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
496 #define ast_cond_broadcast(cond) __ast_pthread_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
497 #define ast_cond_wait(cond, mutex) __ast_pthread_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
498 #define ast_cond_timedwait(cond, mutex, time) __ast_pthread_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
499
500 #else /* !DEBUG_THREADS */
501
502
503 #define AST_MUTEX_INIT_VALUE    PTHREAD_MUTEX_INIT_VALUE
504
505
506 typedef pthread_mutex_t ast_mutex_t;
507
508 static inline int ast_mutex_init(ast_mutex_t *pmutex)
509 {
510         pthread_mutexattr_t attr;
511         pthread_mutexattr_init(&attr);
512         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
513         return pthread_mutex_init(pmutex, &attr);
514 }
515 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
516 #define ast_mutex_unlock(pmutex) pthread_mutex_unlock(pmutex)
517 #define ast_mutex_destroy(pmutex) pthread_mutex_destroy(pmutex)
518
519 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
520 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
521  constrictors/destructors to create/destroy mutexes.  */ 
522 #define __AST_MUTEX_DEFINE(scope,mutex) \
523         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
524 static void  __attribute__ ((constructor)) init_##mutex(void) \
525 { \
526         ast_mutex_init(&mutex); \
527 } \
528 static void  __attribute__ ((destructor)) fini_##mutex(void) \
529 { \
530         ast_mutex_destroy(&mutex); \
531 }
532
533 #define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex)
534 #define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex)
535
536 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
537 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
538  first use.  The performance impact on FreeBSD should be small since
539  the pthreads library does this itself to initialize errror checking
540  (defaulty type) mutexes.*/ 
541 #define __AST_MUTEX_DEFINE(scope,mutex) \
542         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
543
544 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
545 {
546         if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
547                 ast_mutex_init(pmutex);
548         return pthread_mutex_lock(pmutex);
549 }
550 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
551 {
552         if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
553                 ast_mutex_init(pmutex);
554         return pthread_mutex_trylock(pmutex);
555 }
556 #else
557 /* By default, use static initialization of mutexes.*/ 
558 #define __AST_MUTEX_DEFINE(scope,mutex) \
559         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
560 #define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex)
561 #define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex)
562 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
563
564 typedef pthread_cond_t ast_cond_t
565
566 #define ast_cond_init pthread_cond_init
567 #define ast_cond_destroy pthread_cond_destroy
568 #define ast_cond_signal pthread_cond_signal
569 #define ast_cond_broadcast pthread_cond_broadcast
570 #define ast_cond_wait pthread_cond_wait
571 #define ast_cond_timedwait pthread_cond_timedwait
572
573 #endif /* !DEBUG_THREADS */
574
575 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
576 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
577 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
578 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
579 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
580 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
581 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
582 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
583 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
584 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
585 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
586 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
587 #define pthread_cond_timedwait use_ast_cond_wait_instead_of_pthread_cond_timedwait
588
589 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static,mutex)
590 #define AST_MUTEX_DEFINE_EXPORTED(mutex) __AST_MUTEX_DEFINE(/**/,mutex)
591
592 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
593
594 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
595 #ifndef __linux__
596 #define pthread_create __use_ast_pthread_create_instead__
597 #endif
598
599 #endif /* _ASTERISK_LOCK_H */