f1747454c6fcf166e37f724a8c0dfea87c83e8cf
[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 static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
95                                                 const char *mutex_name, ast_mutex_t *t,
96                                                 pthread_mutexattr_t *attr) 
97 {
98 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
99         int canlog = strcmp(filename, "logger.c");
100
101         if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
102                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
103                                    filename, lineno, func, mutex_name);
104                 __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
105                                    t->file, t->lineno, t->func, mutex_name);
106 #ifdef THREAD_CRASH
107                 DO_THREAD_CRASH;
108 #endif
109                 return 0;
110         }
111 #endif
112
113         t->file[0] = filename;
114         t->lineno[0] = lineno;
115         t->func[0] = func;
116         t->thread[0]  = 0;
117         t->reentrancy = 0;
118
119         return pthread_mutex_init(&t->mutex, attr);
120 }
121
122 static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
123                                            const char *mutex_name, ast_mutex_t *t)
124 {
125         static pthread_mutexattr_t  attr;
126
127         pthread_mutexattr_init(&attr);
128         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
129
130         return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
131 }
132
133 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
134                                                 const char *mutex_name, ast_mutex_t *t)
135 {
136         int res;
137         int canlog = strcmp(filename, "logger.c");
138
139 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
140         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
141                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
142                                    filename, lineno, func, mutex_name);
143         }
144 #endif
145
146         res = pthread_mutex_trylock(&t->mutex);
147         switch (res) {
148         case 0:
149                 pthread_mutex_unlock(&t->mutex);
150                 break;
151         case EINVAL:
152                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
153                                   filename, lineno, func, mutex_name);
154                 break;
155         case EBUSY:
156                 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
157                                    filename, lineno, func, mutex_name);
158                 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
159                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
160                 break;
161         }
162
163         if ((res = pthread_mutex_destroy(&t->mutex)))
164                 __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
165                                    filename, lineno, func, strerror(res));
166 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
167         else
168                 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
169 #endif
170         t->file[0] = filename;
171         t->lineno[0] = lineno;
172         t->func[0] = func;
173
174         return res;
175 }
176
177 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
178 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
179  constrictors/destructors to create/destroy mutexes.  */
180 #define __AST_MUTEX_DEFINE(scope,mutex) \
181         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
182 static void  __attribute__ ((constructor)) init_##mutex(void) \
183 { \
184         ast_mutex_init(&mutex); \
185 } \
186 static void  __attribute__ ((destructor)) fini_##mutex(void) \
187 { \
188         ast_mutex_destroy(&mutex); \
189 }
190 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
191 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
192  first use.  The performance impact on FreeBSD should be small since
193  the pthreads library does this itself to initialize errror checking
194  (defaulty type) mutexes.  If nither is defined, the pthreads librariy
195  does the initialization itself on first use. */ 
196 #define __AST_MUTEX_DEFINE(scope,mutex) \
197         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
198 #else /* AST_MUTEX_INIT_W_CONSTRUCTORS */
199 /* By default, use static initialization of mutexes.*/ 
200 #define __AST_MUTEX_DEFINE(scope,mutex) \
201         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
202 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
203
204 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
205                                            const char* mutex_name, ast_mutex_t *t)
206 {
207         int res;
208         int canlog = strcmp(filename, "logger.c");
209
210 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
211         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
212 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
213                 ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
214                                  filename, lineno, func, mutex_name);
215 #endif
216                 ast_mutex_init(t);
217         }
218 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
219
220 #ifdef DETECT_DEADLOCKS
221         {
222                 time_t seconds = time(NULL);
223                 time_t current;
224                 do {
225                         res = pthread_mutex_trylock(&t->mutex);
226                         if (res == EBUSY) {
227                                 current = time(NULL);
228                                 if ((current - seconds) && (!((current - seconds) % 5))) {
229                                         __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
230                                                            filename, lineno, func, (int)(current - seconds), mutex_name);
231                                         __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
232                                                            t->file, t->lineno, t->func, mutex_name);
233                                 }
234                                 usleep(200);
235                         }
236                 } while (res == EBUSY);
237         }
238 #else
239         res = pthread_mutex_lock(&t->mutex);
240 #endif /* DETECT_DEADLOCKS */
241
242         if (!res) {
243                 if (t->reentrancy < AST_MAX_REENTRANCY) {
244                         t->file[t->reentrancy] = filename;
245                         t->lineno[t->reentrancy] = lineno;
246                         t->func[t->reentrancy] = func;
247                         t->thread[t->reentrancy] = pthread_self();
248                         t->reentrancy++;
249                 } else {
250                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
251                                                            filename, lineno, func, mutex_name);
252                 }
253         } else {
254                 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
255                                    filename, lineno, func, strerror(errno));
256 #ifdef THREAD_CRASH
257                 DO_THREAD_CRASH;
258 #endif
259         }
260
261         return res;
262 }
263
264 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
265                                               const char* mutex_name, ast_mutex_t *t)
266 {
267         int res;
268         int canlog = strcmp(filename, "logger.c");
269
270 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
271         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
272 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
273
274                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
275                                    filename, lineno, func, mutex_name);
276 #endif
277                 ast_mutex_init(t);
278         }
279 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
280
281         if (!(res = pthread_mutex_trylock(&t->mutex))) {
282                 if (t->reentrancy < AST_MAX_REENTRANCY) {
283                         t->file[t->reentrancy] = filename;
284                         t->lineno[t->reentrancy] = lineno;
285                         t->func[t->reentrancy] = func;
286                         t->thread[t->reentrancy] = pthread_self();
287                         t->reentrancy++;
288                 } else {
289                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
290                                                            filename, lineno, func, mutex_name);
291                 }
292         }
293
294         return res;
295 }
296
297 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
298                                              const char *mutex_name, ast_mutex_t *t)
299 {
300         int res;
301         int canlog = strcmp(filename, "logger.c");
302
303 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
304         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
305                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
306                                    filename, lineno, func, mutex_name);
307         }
308 #endif
309
310         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
311                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
312                                    filename, lineno, func, mutex_name);
313                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
314                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
315 #ifdef THREAD_CRASH
316                 DO_THREAD_CRASH;
317 #endif
318         }
319
320         if (--t->reentrancy < 0) {
321                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
322                                    filename, lineno, func, mutex_name);
323                 t->reentrancy = 0;
324         }
325
326         if (t->reentrancy < AST_MAX_REENTRANCY) {
327                 t->file[t->reentrancy] = NULL;
328                 t->lineno[t->reentrancy] = 0;
329                 t->func[t->reentrancy] = NULL;
330                 t->thread[t->reentrancy] = 0;
331         }
332
333         if ((res = pthread_mutex_unlock(&t->mutex))) {
334                 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
335                                    filename, lineno, func, strerror(res));
336 #ifdef THREAD_CRASH
337                 DO_THREAD_CRASH;
338 #endif
339         }
340
341         return res;
342 }
343
344 static inline int __ast_pthread_cond_wait(const char *filename, int lineno, const char *func,
345                                           pthread_cond_t *cond, const char *mutex_name, ast_mutex_t *t)
346 {
347         int res;
348         int canlog = strcmp(filename, "logger.c");
349
350 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
351         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
352                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
353                                    filename, lineno, func, mutex_name);
354         }
355 #endif
356
357         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
358                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
359                                    filename, lineno, func, mutex_name);
360                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
361                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
362 #ifdef THREAD_CRASH
363                 DO_THREAD_CRASH;
364 #endif
365         }
366
367         if (--t->reentrancy < 0) {
368                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
369                                    filename, lineno, func, mutex_name);
370                 t->reentrancy = 0;
371         }
372
373         if (t->reentrancy < AST_MAX_REENTRANCY) {
374                 t->file[t->reentrancy] = NULL;
375                 t->lineno[t->reentrancy] = 0;
376                 t->func[t->reentrancy] = NULL;
377                 t->thread[t->reentrancy] = 0;
378         }
379
380         if ((res = pthread_cond_wait(cond, &t->mutex))) {
381                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
382                                    filename, lineno, func, strerror(res));
383 #ifdef THREAD_CRASH
384                 DO_THREAD_CRASH;
385 #endif
386         } else {
387                 if (t->reentrancy < AST_MAX_REENTRANCY) {
388                         t->file[t->reentrancy] = filename;
389                         t->lineno[t->reentrancy] = lineno;
390                         t->func[t->reentrancy] = func;
391                         t->thread[t->reentrancy] = pthread_self();
392                         t->reentrancy++;
393                 } else {
394                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
395                                                            filename, lineno, func, mutex_name);
396                 }
397         }
398
399         return res;
400 }
401
402 static inline int __ast_pthread_cond_timedwait(const char *filename, int lineno, const char *func,
403                                                pthread_cond_t *cond, const struct timespec *abstime,
404                                                const char *mutex_name, ast_mutex_t *t)
405 {
406         int res;
407         int canlog = strcmp(filename, "logger.c");
408
409 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
410         if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
411                 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
412                                    filename, lineno, func, mutex_name);
413         }
414 #endif
415
416         if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
417                 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
418                                    filename, lineno, func, mutex_name);
419                 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
420                                    t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
421 #ifdef THREAD_CRASH
422                 DO_THREAD_CRASH;
423 #endif
424         }
425
426         if (--t->reentrancy < 0) {
427                 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
428                                    filename, lineno, func, mutex_name);
429                 t->reentrancy = 0;
430         }
431
432         if (t->reentrancy < AST_MAX_REENTRANCY) {
433                 t->file[t->reentrancy] = NULL;
434                 t->lineno[t->reentrancy] = 0;
435                 t->func[t->reentrancy] = NULL;
436                 t->thread[t->reentrancy] = 0;
437         }
438
439         if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime))) {
440                 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
441                                    filename, lineno, func, strerror(res));
442 #ifdef THREAD_CRASH
443                 DO_THREAD_CRASH;
444 #endif
445         } else {
446                 if (t->reentrancy < AST_MAX_REENTRANCY) {
447                         t->file[t->reentrancy] = filename;
448                         t->lineno[t->reentrancy] = lineno;
449                         t->func[t->reentrancy] = func;
450                         t->thread[t->reentrancy] = pthread_self();
451                         t->reentrancy++;
452                 } else {
453                         __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
454                                                            filename, lineno, func, mutex_name);
455                 }
456         }
457
458         return res;
459 }
460
461 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
462 #define ast_pthread_mutex_init(pmutex,attr) __ast_pthread_mutex_init_attr(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex, attr)
463 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
464 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
465 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
466 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
467 #define ast_pthread_cond_wait(cond, a) __ast_pthread_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, cond, #a, a)
468 #define ast_pthread_cond_timedwait(cond, a, t) __ast_pthread_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, cond, t, #a, a)
469
470 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
471 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
472 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
473 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
474 #define pthread_mutex_init use_ast_pthread_mutex_init_instead_of_pthread_mutex_init
475 #define pthread_mutex_destroy use_ast_pthread_mutex_destroy_instead_of_pthread_mutex_destroy
476 #define pthread_cond_wait use_ast_pthread_cond_wait_instead_of_pthread_cond_wait
477 #define pthread_cond_timedwait use_ast_pthread_cond_wait_instead_of_pthread_cond_timedwait
478
479 #else /* !DEBUG_THREADS */
480
481
482 #define AST_MUTEX_INIT_VALUE    PTHREAD_MUTEX_INIT_VALUE
483
484
485 typedef pthread_mutex_t ast_mutex_t;
486
487 static inline int ast_mutex_init(ast_mutex_t *pmutex)
488 {
489         pthread_mutexattr_t attr;
490         pthread_mutexattr_init(&attr);
491         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
492         return pthread_mutex_init(pmutex, &attr);
493 }
494 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
495 #define ast_mutex_unlock(pmutex) pthread_mutex_unlock(pmutex)
496 #define ast_mutex_destroy(pmutex) pthread_mutex_destroy(pmutex)
497
498 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
499 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
500  constrictors/destructors to create/destroy mutexes.  */ 
501 #define __AST_MUTEX_DEFINE(scope,mutex) \
502         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
503 static void  __attribute__ ((constructor)) init_##mutex(void) \
504 { \
505         ast_mutex_init(&mutex); \
506 } \
507 static void  __attribute__ ((destructor)) fini_##mutex(void) \
508 { \
509         ast_mutex_destroy(&mutex); \
510 }
511
512 #define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex)
513 #define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex)
514
515 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
516 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
517  first use.  The performance impact on FreeBSD should be small since
518  the pthreads library does this itself to initialize errror checking
519  (defaulty type) mutexes.*/ 
520 #define __AST_MUTEX_DEFINE(scope,mutex) \
521         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
522
523 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
524 {
525         if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
526                 ast_mutex_init(pmutex);
527         return pthread_mutex_lock(pmutex);
528 }
529 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
530 {
531         if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
532                 ast_mutex_init(pmutex);
533         return pthread_mutex_trylock(pmutex);
534 }
535 #else
536 /* By default, use static initialization of mutexes.*/ 
537 #define __AST_MUTEX_DEFINE(scope,mutex) \
538         scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
539 #define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex)
540 #define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex)
541 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
542
543 #define ast_pthread_cond_wait pthread_cond_wait
544 #define ast_pthread_cond_timedwait pthread_cond_timedwait
545
546 #endif /* !DEBUG_THREADS */
547
548 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static,mutex)
549 #define AST_MUTEX_DEFINE_EXPORTED(mutex) __AST_MUTEX_DEFINE(/**/,mutex)
550
551 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
552
553 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
554 #ifndef __linux__
555 #define pthread_create __use_ast_pthread_create_instead__
556 #endif
557
558 #endif /* _ASTERISK_LOCK_H */