Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:47:54 2009

## Asterisk developer's documentation

# lock.h

Go to the documentation of this file.

    00001 /*
    00002  * Asterisk -- An open source telephony toolkit.
    00003  *
    00004  * Copyright (C) 1999 - 2005, Digium, Inc.
    00005  *
    00006  * Mark Spencer <markster@digium.com>
    00007  *
    00008  * See http://www.asterisk.org for more information about
    00009  * the Asterisk project. Please do not directly contact
    00010  * any of the maintainers of this project for assistance;
    00011  * the project provides a web site, mailing lists and IRC
    00012  * channels for your use.
    00013  *
    00014  * This program is free software, distributed under the terms of
    00015  * the GNU General Public License Version 2. See the LICENSE file
    00016  * at the top of the source tree.
    00017  */
    00018
    00019 /*! \file
    00020  * \brief General Asterisk channel locking definitions.
    00021  */
    00022
    00023 #ifndef _ASTERISK_LOCK_H
    00024 #define _ASTERISK_LOCK_H
    00025
    00026 #include <pthread.h>
    00027 #include <netdb.h>
    00028 #include <time.h>
    00029 #include <sys/param.h>
    00030
    00031 #include "asterisk/logger.h"
    00032
    00033 #define AST_PTHREADT_NULL (pthread_t) -1
    00034 #define AST_PTHREADT_STOP (pthread_t) -2
    00035
    00036 #ifdef __APPLE__
    00037 /* Provide the Linux initializers for MacOS X */
    00038 #define PTHREAD_MUTEX_RECURSIVE_NP        PTHREAD_MUTEX_RECURSIVE
    00039 #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP     { 0x4d555458, \
    00040                      { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    00041                      0x20 } }
    00042 #endif
    00043
    00044 #ifdef BSD
    00045 #ifdef __GNUC__
    00046 #define AST_MUTEX_INIT_W_CONSTRUCTORS
    00047 #else
    00048 #define AST_MUTEX_INIT_ON_FIRST_USE
    00049 #endif
    00050 #endif /* BSD */
    00051
    00052 /* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes
    00053    and will not run without them. */
    00054 #if defined(__CYGWIN__)
    00055 #define PTHREAD_MUTEX_RECURSIVE_NP  PTHREAD_MUTEX_RECURSIVE
    00056 #define PTHREAD_MUTEX_INIT_VALUE    (ast_mutex_t)18
    00057 #define AST_MUTEX_KIND        PTHREAD_MUTEX_RECURSIVE_NP
    00058 #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
    00059 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
    00060 #define AST_MUTEX_KIND        PTHREAD_MUTEX_RECURSIVE_NP
    00061 #else
    00062 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
    00063 #define AST_MUTEX_KIND        PTHREAD_MUTEX_RECURSIVE
    00064 #endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
    00065
    00066 #ifdef SOLARIS
    00067 #define AST_MUTEX_INIT_W_CONSTRUCTORS
    00068 #endif
    00069
    00070 #ifdef DEBUG_THREADS
    00071
    00072 #define __ast_mutex_logger(...) { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); }
    00073
    00074 #ifdef THREAD_CRASH
    00075 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
    00076 #endif
    00077
    00078 #include <errno.h>
    00079 #include <string.h>
    00080 #include <stdio.h>
    00081 #include <unistd.h>
    00082
    00083 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, { NULL }, { 0 }, 0, { NULL }, { 0 } }
    00084
    00085 #define AST_MAX_REENTRANCY 10
    00086
    00087 struct ast_mutex_info {
    00088    pthread_mutex_t mutex;
    00089    const char *file[AST_MAX_REENTRANCY];
    00090    int lineno[AST_MAX_REENTRANCY];
    00091    int reentrancy;
    00092    const char *func[AST_MAX_REENTRANCY];
    00093    pthread_t thread[AST_MAX_REENTRANCY];
    00094 };
    00095
    00096 typedef struct ast_mutex_info ast_mutex_t;
    00097
    00098 typedef pthread_cond_t ast_cond_t;
    00099
    00100 static pthread_mutex_t empty_mutex;
    00101
    00102 static void __attribute__((constructor)) init_empty_mutex(void)
    00103 {
    00104    memset(&empty_mutex, 0, sizeof(empty_mutex));
    00105 }
    00106
    00107 static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
    00108                   const char *mutex_name, ast_mutex_t *t,
    00109                   pthread_mutexattr_t *attr)
    00110 {
    00111 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
    00112    int canlog = strcmp(filename, "logger.c");
    00113
    00114    if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
    00115       if ((t->mutex) != (empty_mutex)) {
    00116          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
    00117                   filename, lineno, func, mutex_name);
    00118          __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
    00119                   t->file, t->lineno, t->func, mutex_name);
    00120 #ifdef THREAD_CRASH
    00121          DO_THREAD_CRASH;
    00122 #endif
    00123          return 0;
    00124       }
    00125    }
    00126 #endif
    00127
    00128    t->file[0] = filename;
    00129    t->lineno[0] = lineno;
    00130    t->func[0] = func;
    00131    t->thread[0]  = 0;
    00132    t->reentrancy = 0;
    00133
    00134    return pthread_mutex_init(&t->mutex, attr);
    00135 }
    00136
    00137 static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
    00138                   const char *mutex_name, ast_mutex_t *t)
    00139 {
    00140    static pthread_mutexattr_t  attr;
    00141
    00142    pthread_mutexattr_init(&attr);
    00143    pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
    00144
    00145    return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
    00146 }
    00147
    00148 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
    00149                   const char *mutex_name, ast_mutex_t *t)
    00150 {
    00151    int res;
    00152    int canlog = strcmp(filename, "logger.c");
    00153
    00154 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
    00155    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
    00156       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
    00157                filename, lineno, func, mutex_name);
    00158    }
    00159 #endif
    00160
    00161    res = pthread_mutex_trylock(&t->mutex);
    00162    switch (res) {
    00163    case 0:
    00164       pthread_mutex_unlock(&t->mutex);
    00165       break;
    00166    case EINVAL:
    00167       __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
    00168               filename, lineno, func, mutex_name);
    00169       break;
    00170    case EBUSY:
    00171       __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
    00172                filename, lineno, func, mutex_name);
    00173       __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
    00174                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
    00175       break;
    00176    }
    00177
    00178    if ((res = pthread_mutex_destroy(&t->mutex)))
    00179       __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
    00180                filename, lineno, func, strerror(res));
    00181 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
    00182    else
    00183       t->mutex = PTHREAD_MUTEX_INIT_VALUE;
    00184 #endif
    00185    t->file[0] = filename;
    00186    t->lineno[0] = lineno;
    00187    t->func[0] = func;
    00188
    00189    return res;
    00190 }
    00191
    00192 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
    00193 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
    00194  constrictors/destructors to create/destroy mutexes.  */
    00195 #define __AST_MUTEX_DEFINE(scope,mutex) \
    00196    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
    00197 static void  __attribute__ ((constructor)) init_##mutex(void) \
    00198 { \
    00199    ast_mutex_init(&mutex); \
    00200 } \
    00201 static void  __attribute__ ((destructor)) fini_##mutex(void) \
    00202 { \
    00203    ast_mutex_destroy(&mutex); \
    00204 }
    00205 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
    00206 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
    00207  first use.  The performance impact on FreeBSD should be small since
    00208  the pthreads library does this itself to initialize errror checking
    00209  (defaulty type) mutexes.  If nither is defined, the pthreads librariy
    00210  does the initialization itself on first use. */
    00211 #define __AST_MUTEX_DEFINE(scope,mutex) \
    00212    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
    00213 #else /* AST_MUTEX_INIT_W_CONSTRUCTORS */
    00214 /* By default, use static initialization of mutexes.*/
    00215 #define __AST_MUTEX_DEFINE(scope,mutex) \
    00216    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
    00217 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
    00218
    00219 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
    00220                                            const char* mutex_name, ast_mutex_t *t)
    00221 {
    00222    int res;
    00223    int canlog = strcmp(filename, "logger.c");
    00224
    00225 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
    00226    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
    00227 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
    00228       ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
    00229              filename, lineno, func, mutex_name);
    00230 #endif
    00231       ast_mutex_init(t);
    00232    }
    00233 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
    00234
    00235 #ifdef DETECT_DEADLOCKS
    00236    {
    00237       time_t seconds = time(NULL);
    00238       time_t current;
    00239       do {
    00240          res = pthread_mutex_trylock(&t->mutex);
    00241          if (res == EBUSY) {
    00242             current = time(NULL);
    00243             if ((current - seconds) && (!((current - seconds) % 5))) {
    00244                __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
    00245                         filename, lineno, func, (int)(current - seconds), mutex_name);
    00246                __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
    00247                         t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
    00248                         t->func[t->reentrancy-1], mutex_name);
    00249             }
    00250             usleep(200);
    00251          }
    00252       } while (res == EBUSY);
    00253    }
    00254 #else
    00255    res = pthread_mutex_lock(&t->mutex);
    00256 #endif /* DETECT_DEADLOCKS */
    00257
    00258    if (!res) {
    00259       if (t->reentrancy < AST_MAX_REENTRANCY) {
    00260          t->file[t->reentrancy] = filename;
    00261          t->lineno[t->reentrancy] = lineno;
    00262          t->func[t->reentrancy] = func;
    00263          t->thread[t->reentrancy] = pthread_self();
    00264          t->reentrancy++;
    00265       } else {
    00266          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
    00267                         filename, lineno, func, mutex_name);
    00268       }
    00269    } else {
    00270       __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
    00271                filename, lineno, func, strerror(res));
    00272 #ifdef THREAD_CRASH
    00273       DO_THREAD_CRASH;
    00274 #endif
    00275    }
    00276
    00277    return res;
    00278 }
    00279
    00280 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
    00281                                               const char* mutex_name, ast_mutex_t *t)
    00282 {
    00283    int res;
    00284    int canlog = strcmp(filename, "logger.c");
    00285
    00286 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
    00287    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
    00288 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
    00289
    00290       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
    00291                filename, lineno, func, mutex_name);
    00292 #endif
    00293       ast_mutex_init(t);
    00294    }
    00295 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
    00296
    00297    if (!(res = pthread_mutex_trylock(&t->mutex))) {
    00298       if (t->reentrancy < AST_MAX_REENTRANCY) {
    00299          t->file[t->reentrancy] = filename;
    00300          t->lineno[t->reentrancy] = lineno;
    00301          t->func[t->reentrancy] = func;
    00302          t->thread[t->reentrancy] = pthread_self();
    00303          t->reentrancy++;
    00304       } else {
    00305          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
    00306                         filename, lineno, func, mutex_name);
    00307       }
    00308    }
    00309
    00310    return res;
    00311 }
    00312
    00313 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
    00314                     const char *mutex_name, ast_mutex_t *t)
    00315 {
    00316    int res;
    00317    int canlog = strcmp(filename, "logger.c");
    00318
    00319 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
    00320    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
    00321       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
    00322                filename, lineno, func, mutex_name);
    00323    }
    00324 #endif
    00325
    00326    if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
    00327       __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
    00328                filename, lineno, func, mutex_name);
    00329       __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
    00330                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
    00331 #ifdef THREAD_CRASH
    00332       DO_THREAD_CRASH;
    00333 #endif
    00334    }
    00335
    00336    if (--t->reentrancy < 0) {
    00337       __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
    00338                filename, lineno, func, mutex_name);
    00339       t->reentrancy = 0;
    00340    }
    00341
    00342    if (t->reentrancy < AST_MAX_REENTRANCY) {
    00343       t->file[t->reentrancy] = NULL;
    00344       t->lineno[t->reentrancy] = 0;
    00345       t->func[t->reentrancy] = NULL;
    00346       t->thread[t->reentrancy] = 0;
    00347    }
    00348
    00349    if ((res = pthread_mutex_unlock(&t->mutex))) {
    00350       __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
    00351                filename, lineno, func, strerror(res));
    00352 #ifdef THREAD_CRASH
    00353       DO_THREAD_CRASH;
    00354 #endif
    00355    }
    00356
    00357    return res;
    00358 }
    00359
    00360 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
    00361               const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
    00362 {
    00363    return pthread_cond_init(cond, cond_attr);
    00364 }
    00365
    00366 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
    00367                 const char *cond_name, ast_cond_t *cond)
    00368 {
    00369    return pthread_cond_signal(cond);
    00370 }
    00371
    00372 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
    00373                    const char *cond_name, ast_cond_t *cond)
    00374 {
    00375    return pthread_cond_broadcast(cond);
    00376 }
    00377
    00378 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
    00379                  const char *cond_name, ast_cond_t *cond)
    00380 {
    00381    return pthread_cond_destroy(cond);
    00382 }
    00383
    00384 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
    00385               const char *cond_name, const char *mutex_name,
    00386               ast_cond_t *cond, ast_mutex_t *t)
    00387 {
    00388    int res;
    00389    int canlog = strcmp(filename, "logger.c");
    00390
    00391 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
    00392    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
    00393       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
    00394                filename, lineno, func, mutex_name);
    00395    }
    00396 #endif
    00397
    00398    if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
    00399       __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
    00400                filename, lineno, func, mutex_name);
    00401       __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
    00402                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
    00403 #ifdef THREAD_CRASH
    00404       DO_THREAD_CRASH;
    00405 #endif
    00406    }
    00407
    00408    if (t->reentrancy > 1)
    00409       __ast_mutex_logger("%s line %d (%s): mutex '%s' locked more than once, cond_wait will block!\n",
    00410                filename, lineno, func, mutex_name);
    00411
    00412    if (--t->reentrancy < 0) {
    00413       __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
    00414                filename, lineno, func, mutex_name);
    00415       t->reentrancy = 0;
    00416    }
    00417
    00418    if (t->reentrancy < AST_MAX_REENTRANCY) {
    00419       t->file[t->reentrancy] = NULL;
    00420       t->lineno[t->reentrancy] = 0;
    00421       t->func[t->reentrancy] = NULL;
    00422       t->thread[t->reentrancy] = 0;
    00423    }
    00424
    00425    if ((res = pthread_cond_wait(cond, &t->mutex))) {
    00426       __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
    00427                filename, lineno, func, strerror(res));
    00428 #ifdef THREAD_CRASH
    00429       DO_THREAD_CRASH;
    00430 #endif
    00431    } else {
    00432       if (t->reentrancy < AST_MAX_REENTRANCY) {
    00433          t->file[t->reentrancy] = filename;
    00434          t->lineno[t->reentrancy] = lineno;
    00435          t->func[t->reentrancy] = func;
    00436          t->thread[t->reentrancy] = pthread_self();
    00437          t->reentrancy++;
    00438       } else {
    00439          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
    00440                         filename, lineno, func, mutex_name);
    00441       }
    00442    }
    00443
    00444    return res;
    00445 }
    00446
    00447 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
    00448                    const char *cond_name, const char *mutex_name, ast_cond_t *cond,
    00449                    ast_mutex_t *t, const struct timespec *abstime)
    00450 {
    00451    int res;
    00452    int canlog = strcmp(filename, "logger.c");
    00453
    00454 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
    00455    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
    00456       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
    00457                filename, lineno, func, mutex_name);
    00458    }
    00459 #endif
    00460
    00461    if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
    00462       __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
    00463                filename, lineno, func, mutex_name);
    00464       __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
    00465                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
    00466 #ifdef THREAD_CRASH
    00467       DO_THREAD_CRASH;
    00468 #endif
    00469    }
    00470
    00471    if (t->reentrancy > 1)
    00472       __ast_mutex_logger("%s line %d (%s): mutex '%s' locked more than once, cond_timedwait will block!\n",
    00473                filename, lineno, func, mutex_name);
    00474
    00475    if (--t->reentrancy < 0) {
    00476       __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
    00477                filename, lineno, func, mutex_name);
    00478       t->reentrancy = 0;
    00479    }
    00480
    00481    if (t->reentrancy < AST_MAX_REENTRANCY) {
    00482       t->file[t->reentrancy] = NULL;
    00483       t->lineno[t->reentrancy] = 0;
    00484       t->func[t->reentrancy] = NULL;
    00485       t->thread[t->reentrancy] = 0;
    00486    }
    00487
    00488    if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
    00489       __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
    00490                filename, lineno, func, strerror(res));
    00491 #ifdef THREAD_CRASH
    00492       DO_THREAD_CRASH;
    00493 #endif
    00494    } else {
    00495       if (t->reentrancy < AST_MAX_REENTRANCY) {
    00496          t->file[t->reentrancy] = filename;
    00497          t->lineno[t->reentrancy] = lineno;
    00498          t->func[t->reentrancy] = func;
    00499          t->thread[t->reentrancy] = pthread_self();
    00500          t->reentrancy++;
    00501       } else {
    00502          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
    00503                         filename, lineno, func, mutex_name);
    00504       }
    00505    }
    00506
    00507    return res;
    00508 }
    00509
    00510 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
    00511 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
    00512 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
    00513 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
    00514 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
    00515 #define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
    00516 #define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
    00517 #define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
    00518 #define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
    00519 #define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
    00520 #define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
    00521
    00522 #else /* !DEBUG_THREADS */
    00523
    00524
    00525 #define AST_MUTEX_INIT_VALUE  PTHREAD_MUTEX_INIT_VALUE
    00526
    00527
    00528 typedef pthread_mutex_t ast_mutex_t;
    00529
    00530 static inline int ast_mutex_init(ast_mutex_t *pmutex)
    00531 {
    00532    pthread_mutexattr_t attr;
    00533    pthread_mutexattr_init(&attr);
    00534    pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
    00535    return pthread_mutex_init(pmutex, &attr);
    00536 }
    00537
    00538 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
    00539
    00540 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
    00541 {
    00542    return pthread_mutex_unlock(pmutex);
    00543 }
    00544
    00545 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
    00546 {
    00547    return pthread_mutex_destroy(pmutex);
    00548 }
    00549
    00550 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
    00551 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
    00552  constrictors/destructors to create/destroy mutexes.  */
    00553 #define __AST_MUTEX_DEFINE(scope,mutex) \
    00554    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
    00555 static void  __attribute__ ((constructor)) init_##mutex(void) \
    00556 { \
    00557    ast_mutex_init(&mutex); \
    00558 } \
    00559 static void  __attribute__ ((destructor)) fini_##mutex(void) \
    00560 { \
    00561    ast_mutex_destroy(&mutex); \
    00562 }
    00563
    00564 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
    00565 {
    00566    return pthread_mutex_lock(pmutex);
    00567 }
    00568
    00569 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
    00570 {
    00571    return pthread_mutex_trylock(pmutex);
    00572 }
    00573
    00574 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
    00575 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
    00576  first use.  The performance impact on FreeBSD should be small since
    00577  the pthreads library does this itself to initialize errror checking
    00578  (defaulty type) mutexes.*/
    00579 #define __AST_MUTEX_DEFINE(scope,mutex) \
    00580    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
    00581
    00582 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
    00583 {
    00584    if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
    00585       ast_mutex_init(pmutex);
    00586    return pthread_mutex_lock(pmutex);
    00587 }
    00588 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
    00589 {
    00590    if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
    00591       ast_mutex_init(pmutex);
    00592    return pthread_mutex_trylock(pmutex);
    00593 }
    00594 #else
    00595 /* By default, use static initialization of mutexes.*/
    00596 #define __AST_MUTEX_DEFINE(scope,mutex) \
    00597    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
    00598
    00599 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
    00600 {
    00601    return pthread_mutex_lock(pmutex);
    00602 }
    00603
    00604 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
    00605 {
    00606    return pthread_mutex_trylock(pmutex);
    00607 }
    00608
    00609 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
    00610
    00611 typedef pthread_cond_t ast_cond_t;
    00612
    00613 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
    00614 {
    00615    return pthread_cond_init(cond, cond_attr);
    00616 }
    00617
    00618 static inline int ast_cond_signal(ast_cond_t *cond)
    00619 {
    00620    return pthread_cond_signal(cond);
    00621 }
    00622
    00623 static inline int ast_cond_broadcast(ast_cond_t *cond)
    00624 {
    00625    return pthread_cond_broadcast(cond);
    00626 }
    00627
    00628 static inline int ast_cond_destroy(ast_cond_t *cond)
    00629 {
    00630    return pthread_cond_destroy(cond);
    00631 }
    00632
    00633 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
    00634 {
    00635    return pthread_cond_wait(cond, t);
    00636 }
    00637
    00638 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
    00639 {
    00640    return pthread_cond_timedwait(cond, t, abstime);
    00641 }
    00642
    00643 #endif /* !DEBUG_THREADS */
    00644
    00645 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
    00646 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
    00647 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
    00648 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
    00649 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
    00650 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
    00651 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
    00652 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
    00653 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
    00654 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
    00655 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
    00656 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
    00657 #define pthread_cond_timedwait use_ast_cond_wait_instead_of_pthread_cond_timedwait
    00658
    00659 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static,mutex)
    00660 #define AST_MUTEX_DEFINE_EXPORTED(mutex) __AST_MUTEX_DEFINE(/**/,mutex)
    00661
    00662 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
    00663
    00664 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
    00665 #ifndef __linux__
    00666 #define pthread_create __use_ast_pthread_create_instead__
    00667 #endif
    00668
    00669 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
    00670
    00671 #include "asterisk/inline_api.h"
    00672
    00673 #if defined (__i386__) && !defined(__APPLE__)
    00674 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
    00675 {
    00676    __asm __volatile (
    00677    "       lock   xaddl   %0, %1 ;        "
    00678    : "+r" (v),                     /* 0 (result) */
    00679      "=m" (*p)                     /* 1 */
    00680    : "m" (*p));                    /* 2 */
    00681    return (v);
    00682 })
    00683 #else   /* low performance version in utils.c */
    00684 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
    00685 {
    00686    return ast_atomic_fetchadd_int_slow(p, v);
    00687 })
    00688 #endif
    00689
    00690 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
    00691 {
    00692    int a = ast_atomic_fetchadd_int(p, -1);
    00693    return a == 1; /* true if the value is 0 now (so it was 1 previously) */
    00694 })
    00695
    00696 #endif /* _ASTERISK_LOCK_H */