Mon Mar 20 08:25:43 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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 inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
00101                   const char *mutex_name, ast_mutex_t *t,
00102                   pthread_mutexattr_t *attr) 
00103 {
00104 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00105    int canlog = strcmp(filename, "logger.c");
00106 
00107    if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00108       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
00109                filename, lineno, func, mutex_name);
00110       __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
00111                t->file, t->lineno, t->func, mutex_name);
00112 #ifdef THREAD_CRASH
00113       DO_THREAD_CRASH;
00114 #endif
00115       return 0;
00116    }
00117 #endif
00118 
00119    t->file[0] = filename;
00120    t->lineno[0] = lineno;
00121    t->func[0] = func;
00122    t->thread[0]  = 0;
00123    t->reentrancy = 0;
00124 
00125    return pthread_mutex_init(&t->mutex, attr);
00126 }
00127 
00128 static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
00129                   const char *mutex_name, ast_mutex_t *t)
00130 {
00131    static pthread_mutexattr_t  attr;
00132 
00133    pthread_mutexattr_init(&attr);
00134    pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00135 
00136    return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
00137 }
00138 
00139 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
00140                   const char *mutex_name, ast_mutex_t *t)
00141 {
00142    int res;
00143    int canlog = strcmp(filename, "logger.c");
00144 
00145 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00146    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00147       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00148                filename, lineno, func, mutex_name);
00149    }
00150 #endif
00151 
00152    res = pthread_mutex_trylock(&t->mutex);
00153    switch (res) {
00154    case 0:
00155       pthread_mutex_unlock(&t->mutex);
00156       break;
00157    case EINVAL:
00158       __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
00159               filename, lineno, func, mutex_name);
00160       break;
00161    case EBUSY:
00162       __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
00163                filename, lineno, func, mutex_name);
00164       __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
00165                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00166       break;
00167    }
00168 
00169    if ((res = pthread_mutex_destroy(&t->mutex)))
00170       __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
00171                filename, lineno, func, strerror(res));
00172 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00173    else
00174       t->mutex = PTHREAD_MUTEX_INIT_VALUE;
00175 #endif
00176    t->file[0] = filename;
00177    t->lineno[0] = lineno;
00178    t->func[0] = func;
00179 
00180    return res;
00181 }
00182 
00183 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00184 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
00185  constrictors/destructors to create/destroy mutexes.  */
00186 #define __AST_MUTEX_DEFINE(scope,mutex) \
00187    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
00188 static void  __attribute__ ((constructor)) init_##mutex(void) \
00189 { \
00190    ast_mutex_init(&mutex); \
00191 } \
00192 static void  __attribute__ ((destructor)) fini_##mutex(void) \
00193 { \
00194    ast_mutex_destroy(&mutex); \
00195 }
00196 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
00197 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
00198  first use.  The performance impact on FreeBSD should be small since
00199  the pthreads library does this itself to initialize errror checking
00200  (defaulty type) mutexes.  If nither is defined, the pthreads librariy
00201  does the initialization itself on first use. */ 
00202 #define __AST_MUTEX_DEFINE(scope,mutex) \
00203    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00204 #else /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00205 /* By default, use static initialization of mutexes.*/ 
00206 #define __AST_MUTEX_DEFINE(scope,mutex) \
00207    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00208 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00209 
00210 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
00211                                            const char* mutex_name, ast_mutex_t *t)
00212 {
00213    int res;
00214    int canlog = strcmp(filename, "logger.c");
00215 
00216 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
00217    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00218 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00219       ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00220              filename, lineno, func, mutex_name);
00221 #endif
00222       ast_mutex_init(t);
00223    }
00224 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
00225 
00226 #ifdef DETECT_DEADLOCKS
00227    {
00228       time_t seconds = time(NULL);
00229       time_t current;
00230       do {
00231          res = pthread_mutex_trylock(&t->mutex);
00232          if (res == EBUSY) {
00233             current = time(NULL);
00234             if ((current - seconds) && (!((current - seconds) % 5))) {
00235                __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
00236                         filename, lineno, func, (int)(current - seconds), mutex_name);
00237                __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00238                         t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
00239                         t->func[t->reentrancy-1], mutex_name);
00240             }
00241             usleep(200);
00242          }
00243       } while (res == EBUSY);
00244    }
00245 #else
00246    res = pthread_mutex_lock(&t->mutex);
00247 #endif /* DETECT_DEADLOCKS */
00248 
00249    if (!res) {
00250       if (t->reentrancy < AST_MAX_REENTRANCY) {
00251          t->file[t->reentrancy] = filename;
00252          t->lineno[t->reentrancy] = lineno;
00253          t->func[t->reentrancy] = func;
00254          t->thread[t->reentrancy] = pthread_self();
00255          t->reentrancy++;
00256       } else {
00257          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00258                         filename, lineno, func, mutex_name);
00259       }
00260    } else {
00261       __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
00262                filename, lineno, func, strerror(errno));
00263 #ifdef THREAD_CRASH
00264       DO_THREAD_CRASH;
00265 #endif
00266    }
00267 
00268    return res;
00269 }
00270 
00271 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
00272                                               const char* mutex_name, ast_mutex_t *t)
00273 {
00274    int res;
00275    int canlog = strcmp(filename, "logger.c");
00276 
00277 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
00278    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00279 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00280 
00281       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00282                filename, lineno, func, mutex_name);
00283 #endif
00284       ast_mutex_init(t);
00285    }
00286 #endif /* defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */
00287 
00288    if (!(res = pthread_mutex_trylock(&t->mutex))) {
00289       if (t->reentrancy < AST_MAX_REENTRANCY) {
00290          t->file[t->reentrancy] = filename;
00291          t->lineno[t->reentrancy] = lineno;
00292          t->func[t->reentrancy] = func;
00293          t->thread[t->reentrancy] = pthread_self();
00294          t->reentrancy++;
00295       } else {
00296          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00297                         filename, lineno, func, mutex_name);
00298       }
00299    }
00300 
00301    return res;
00302 }
00303 
00304 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
00305                     const char *mutex_name, ast_mutex_t *t)
00306 {
00307    int res;
00308    int canlog = strcmp(filename, "logger.c");
00309 
00310 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00311    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00312       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00313                filename, lineno, func, mutex_name);
00314    }
00315 #endif
00316 
00317    if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
00318       __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00319                filename, lineno, func, mutex_name);
00320       __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00321                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00322 #ifdef THREAD_CRASH
00323       DO_THREAD_CRASH;
00324 #endif
00325    }
00326 
00327    if (--t->reentrancy < 0) {
00328       __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00329                filename, lineno, func, mutex_name);
00330       t->reentrancy = 0;
00331    }
00332 
00333    if (t->reentrancy < AST_MAX_REENTRANCY) {
00334       t->file[t->reentrancy] = NULL;
00335       t->lineno[t->reentrancy] = 0;
00336       t->func[t->reentrancy] = NULL;
00337       t->thread[t->reentrancy] = 0;
00338    }
00339 
00340    if ((res = pthread_mutex_unlock(&t->mutex))) {
00341       __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
00342                filename, lineno, func, strerror(res));
00343 #ifdef THREAD_CRASH
00344       DO_THREAD_CRASH;
00345 #endif
00346    }
00347 
00348    return res;
00349 }
00350 
00351 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
00352               const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
00353 {
00354    return pthread_cond_init(cond, cond_attr);
00355 }
00356 
00357 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
00358                 const char *cond_name, ast_cond_t *cond)
00359 {
00360    return pthread_cond_signal(cond);
00361 }
00362 
00363 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
00364                    const char *cond_name, ast_cond_t *cond)
00365 {
00366    return pthread_cond_broadcast(cond);
00367 }
00368 
00369 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
00370                  const char *cond_name, ast_cond_t *cond)
00371 {
00372    return pthread_cond_destroy(cond);
00373 }
00374 
00375 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
00376               const char *cond_name, const char *mutex_name,
00377               ast_cond_t *cond, ast_mutex_t *t)
00378 {
00379    int res;
00380    int canlog = strcmp(filename, "logger.c");
00381 
00382 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00383    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00384       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00385                filename, lineno, func, mutex_name);
00386    }
00387 #endif
00388 
00389    if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
00390       __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00391                filename, lineno, func, mutex_name);
00392       __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00393                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00394 #ifdef THREAD_CRASH
00395       DO_THREAD_CRASH;
00396 #endif
00397    }
00398 
00399    if (t->reentrancy > 1)
00400       __ast_mutex_logger("%s line %d (%s): mutex '%s' locked more than once, cond_wait will block!\n",
00401                filename, lineno, func, mutex_name);
00402 
00403    if (--t->reentrancy < 0) {
00404       __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00405                filename, lineno, func, mutex_name);
00406       t->reentrancy = 0;
00407    }
00408 
00409    if (t->reentrancy < AST_MAX_REENTRANCY) {
00410       t->file[t->reentrancy] = NULL;
00411       t->lineno[t->reentrancy] = 0;
00412       t->func[t->reentrancy] = NULL;
00413       t->thread[t->reentrancy] = 0;
00414    }
00415 
00416    if ((res = pthread_cond_wait(cond, &t->mutex))) {
00417       __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
00418                filename, lineno, func, strerror(res));
00419 #ifdef THREAD_CRASH
00420       DO_THREAD_CRASH;
00421 #endif
00422    } else {
00423       if (t->reentrancy < AST_MAX_REENTRANCY) {
00424          t->file[t->reentrancy] = filename;
00425          t->lineno[t->reentrancy] = lineno;
00426          t->func[t->reentrancy] = func;
00427          t->thread[t->reentrancy] = pthread_self();
00428          t->reentrancy++;
00429       } else {
00430          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00431                         filename, lineno, func, mutex_name);
00432       }
00433    }
00434 
00435    return res;
00436 }
00437 
00438 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
00439                    const char *cond_name, const char *mutex_name, ast_cond_t *cond,
00440                    ast_mutex_t *t, const struct timespec *abstime)
00441 {
00442    int res;
00443    int canlog = strcmp(filename, "logger.c");
00444 
00445 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00446    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00447       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00448                filename, lineno, func, mutex_name);
00449    }
00450 #endif
00451 
00452    if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
00453       __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00454                filename, lineno, func, mutex_name);
00455       __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00456                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00457 #ifdef THREAD_CRASH
00458       DO_THREAD_CRASH;
00459 #endif
00460    }
00461 
00462    if (t->reentrancy > 1)
00463       __ast_mutex_logger("%s line %d (%s): mutex '%s' locked more than once, cond_timedwait will block!\n",
00464                filename, lineno, func, mutex_name);
00465 
00466    if (--t->reentrancy < 0) {
00467       __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00468                filename, lineno, func, mutex_name);
00469       t->reentrancy = 0;
00470    }
00471 
00472    if (t->reentrancy < AST_MAX_REENTRANCY) {
00473       t->file[t->reentrancy] = NULL;
00474       t->lineno[t->reentrancy] = 0;
00475       t->func[t->reentrancy] = NULL;
00476       t->thread[t->reentrancy] = 0;
00477    }
00478 
00479    if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime))) {
00480       __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
00481                filename, lineno, func, strerror(res));
00482 #ifdef THREAD_CRASH
00483       DO_THREAD_CRASH;
00484 #endif
00485    } else {
00486       if (t->reentrancy < AST_MAX_REENTRANCY) {
00487          t->file[t->reentrancy] = filename;
00488          t->lineno[t->reentrancy] = lineno;
00489          t->func[t->reentrancy] = func;
00490          t->thread[t->reentrancy] = pthread_self();
00491          t->reentrancy++;
00492       } else {
00493          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00494                         filename, lineno, func, mutex_name);
00495       }
00496    }
00497 
00498    return res;
00499 }
00500 
00501 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
00502 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00503 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00504 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00505 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00506 #define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
00507 #define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00508 #define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00509 #define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00510 #define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
00511 #define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
00512 
00513 #else /* !DEBUG_THREADS */
00514 
00515 
00516 #define AST_MUTEX_INIT_VALUE  PTHREAD_MUTEX_INIT_VALUE
00517 
00518 
00519 typedef pthread_mutex_t ast_mutex_t;
00520 
00521 static inline int ast_mutex_init(ast_mutex_t *pmutex)
00522 {
00523    pthread_mutexattr_t attr;
00524    pthread_mutexattr_init(&attr);
00525    pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00526    return pthread_mutex_init(pmutex, &attr);
00527 }
00528 
00529 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
00530 
00531 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
00532 {
00533    return pthread_mutex_unlock(pmutex);
00534 }
00535 
00536 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
00537 {
00538    return pthread_mutex_destroy(pmutex);
00539 }
00540 
00541 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00542 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
00543  constrictors/destructors to create/destroy mutexes.  */ 
00544 #define __AST_MUTEX_DEFINE(scope,mutex) \
00545    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
00546 static void  __attribute__ ((constructor)) init_##mutex(void) \
00547 { \
00548    ast_mutex_init(&mutex); \
00549 } \
00550 static void  __attribute__ ((destructor)) fini_##mutex(void) \
00551 { \
00552    ast_mutex_destroy(&mutex); \
00553 }
00554 
00555 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
00556 {
00557    return pthread_mutex_lock(pmutex);
00558 }
00559 
00560 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
00561 {
00562    return pthread_mutex_trylock(pmutex);
00563 }
00564 
00565 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
00566 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on
00567  first use.  The performance impact on FreeBSD should be small since
00568  the pthreads library does this itself to initialize errror checking
00569  (defaulty type) mutexes.*/ 
00570 #define __AST_MUTEX_DEFINE(scope,mutex) \
00571    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00572 
00573 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
00574 {
00575    if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
00576       ast_mutex_init(pmutex);
00577    return pthread_mutex_lock(pmutex);
00578 }
00579 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
00580 {
00581    if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
00582       ast_mutex_init(pmutex);
00583    return pthread_mutex_trylock(pmutex);
00584 }
00585 #else
00586 /* By default, use static initialization of mutexes.*/ 
00587 #define __AST_MUTEX_DEFINE(scope,mutex) \
00588    scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00589 
00590 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
00591 {
00592    return pthread_mutex_lock(pmutex);
00593 }
00594 
00595 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
00596 {
00597    return pthread_mutex_trylock(pmutex);
00598 }
00599 
00600 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00601 
00602 typedef pthread_cond_t ast_cond_t;
00603 
00604 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
00605 {
00606    return pthread_cond_init(cond, cond_attr);
00607 }
00608 
00609 static inline int ast_cond_signal(ast_cond_t *cond)
00610 {
00611    return pthread_cond_signal(cond);
00612 }
00613 
00614 static inline int ast_cond_broadcast(ast_cond_t *cond)
00615 {
00616    return pthread_cond_broadcast(cond);
00617 }
00618 
00619 static inline int ast_cond_destroy(ast_cond_t *cond)
00620 {
00621    return pthread_cond_destroy(cond);
00622 }
00623 
00624 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
00625 {
00626    return pthread_cond_wait(cond, t);
00627 }
00628 
00629 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
00630 {
00631    return pthread_cond_timedwait(cond, t, abstime);
00632 }
00633 
00634 #endif /* !DEBUG_THREADS */
00635 
00636 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
00637 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
00638 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
00639 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
00640 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
00641 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
00642 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
00643 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
00644 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
00645 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
00646 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
00647 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
00648 #define pthread_cond_timedwait use_ast_cond_wait_instead_of_pthread_cond_timedwait
00649 
00650 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static,mutex)
00651 #define AST_MUTEX_DEFINE_EXPORTED(mutex) __AST_MUTEX_DEFINE(/**/,mutex)
00652 
00653 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
00654 
00655 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
00656 #ifndef __linux__
00657 #define pthread_create __use_ast_pthread_create_instead__
00658 #endif
00659 
00660 #endif /* _ASTERISK_LOCK_H */

Generated on Mon Mar 20 08:25:43 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1