Mon Nov 6 06:42:41 2006

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(errno));
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 #endif /* _ASTERISK_LOCK_H */

Generated on Mon Nov 6 06:42:41 2006 for Asterisk - the Open Source PBX by  doxygen 1.5.1