Wed Feb 11 11:59:56 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 - 2006, 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  * - See \ref LockDef
00023  */
00024 
00025 /*! \page LockDef Asterisk thread locking models
00026  *
00027  * This file provides different implementation of the functions,
00028  * depending on the platform, the use of DEBUG_THREADS, and the way
00029  * module-level mutexes are initialized.
00030  *
00031  *  - \b static: the mutex is assigned the value AST_MUTEX_INIT_VALUE
00032  *        this is done at compile time, and is the way used on Linux.
00033  *        This method is not applicable to all platforms e.g. when the
00034  *        initialization needs that some code is run.
00035  *
00036  *  - \b through constructors: for each mutex, a constructor function is
00037  *        defined, which then runs when the program (or the module)
00038  *        starts. The problem with this approach is that there is a
00039  *        lot of code duplication (a new block of code is created for
00040  *        each mutex). Also, it does not prevent a user from declaring
00041  *        a global mutex without going through the wrapper macros,
00042  *        so sane programming practices are still required.
00043  */
00044 
00045 #ifndef _ASTERISK_LOCK_H
00046 #define _ASTERISK_LOCK_H
00047 
00048 #include <pthread.h>
00049 #include <netdb.h>
00050 #include <time.h>
00051 #include <sys/param.h>
00052 
00053 #include "asterisk/logger.h"
00054 
00055 /* internal macro to profile mutexes. Only computes the delay on
00056  * non-blocking calls.
00057  */
00058 #ifndef  HAVE_MTX_PROFILE
00059 #define  __MTX_PROF(a)  return pthread_mutex_lock((a))
00060 #else
00061 #define  __MTX_PROF(a)  do {        \
00062    int i;               \
00063    /* profile only non-blocking events */ \
00064    ast_mark(mtx_prof, 1);        \
00065    i = pthread_mutex_trylock((a));     \
00066    ast_mark(mtx_prof, 0);        \
00067    if (!i)              \
00068       return i;         \
00069    else              \
00070       return pthread_mutex_lock((a)); \
00071    } while (0)
00072 #endif   /* HAVE_MTX_PROFILE */
00073 
00074 #define AST_PTHREADT_NULL (pthread_t) -1
00075 #define AST_PTHREADT_STOP (pthread_t) -2
00076 
00077 #if defined(SOLARIS) || defined(BSD)
00078 #define AST_MUTEX_INIT_W_CONSTRUCTORS
00079 #endif /* SOLARIS || BSD */
00080 
00081 /* Asterisk REQUIRES recursive (not error checking) mutexes
00082    and will not run without them. */
00083 #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
00084 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00085 #define AST_MUTEX_KIND        PTHREAD_MUTEX_RECURSIVE_NP
00086 #else
00087 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
00088 #define AST_MUTEX_KIND        PTHREAD_MUTEX_RECURSIVE
00089 #endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
00090 
00091 #ifdef DEBUG_THREADS
00092 
00093 #define __ast_mutex_logger(...)  do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
00094 
00095 #ifdef THREAD_CRASH
00096 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
00097 #else
00098 #define DO_THREAD_CRASH do { } while (0)
00099 #endif
00100 
00101 #include <errno.h>
00102 #include <string.h>
00103 #include <stdio.h>
00104 #include <unistd.h>
00105 
00106 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
00107 #define AST_MUTEX_INIT_VALUE_NOTRACKING \
00108                              { PTHREAD_MUTEX_INIT_VALUE, 0, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
00109 
00110 #define AST_MAX_REENTRANCY 10
00111 
00112 struct ast_mutex_info {
00113    pthread_mutex_t mutex;
00114    /*! Track which thread holds this lock */
00115    unsigned int track:1;
00116    const char *file[AST_MAX_REENTRANCY];
00117    int lineno[AST_MAX_REENTRANCY];
00118    int reentrancy;
00119    const char *func[AST_MAX_REENTRANCY];
00120    pthread_t thread[AST_MAX_REENTRANCY];
00121    pthread_mutex_t reentr_mutex;
00122 };
00123 
00124 typedef struct ast_mutex_info ast_mutex_t;
00125 
00126 typedef pthread_cond_t ast_cond_t;
00127 
00128 static pthread_mutex_t empty_mutex;
00129 
00130 enum ast_lock_type {
00131    AST_MUTEX,
00132    AST_RDLOCK,
00133    AST_WRLOCK,
00134 };
00135 
00136 /*!
00137  * \brief Store lock info for the current thread
00138  *
00139  * This function gets called in ast_mutex_lock() and ast_mutex_trylock() so
00140  * that information about this lock can be stored in this thread's
00141  * lock info struct.  The lock is marked as pending as the thread is waiting
00142  * on the lock.  ast_mark_lock_acquired() will mark it as held by this thread.
00143  */
00144 #if !defined(LOW_MEMORY)
00145 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00146    int line_num, const char *func, const char *lock_name, void *lock_addr);
00147 #else
00148 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
00149 #endif
00150 
00151 
00152 /*!
00153  * \brief Mark the last lock as acquired
00154  */
00155 #if !defined(LOW_MEMORY)
00156 void ast_mark_lock_acquired(void *lock_addr);
00157 #else
00158 #define ast_mark_lock_acquired(ignore)
00159 #endif
00160 
00161 /*!
00162  * \brief Mark the last lock as failed (trylock)
00163  */
00164 #if !defined(LOW_MEMORY)
00165 void ast_mark_lock_failed(void *lock_addr);
00166 #else
00167 #define ast_mark_lock_failed(ignore)
00168 #endif
00169 
00170 /*!
00171  * \brief remove lock info for the current thread
00172  *
00173  * this gets called by ast_mutex_unlock so that information on the lock can
00174  * be removed from the current thread's lock info struct.
00175  */
00176 #if !defined(LOW_MEMORY)
00177 void ast_remove_lock_info(void *lock_addr);
00178 #else
00179 #define ast_remove_lock_info(ignore)
00180 #endif
00181 
00182 /*!
00183  * \brief retrieve lock info for the specified mutex
00184  *
00185  * this gets called during deadlock avoidance, so that the information may
00186  * be preserved as to what location originally acquired the lock.
00187  */
00188 #if !defined(LOW_MEMORY)
00189 int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, int *lineno, char *func, size_t func_size, char *mutex_name, size_t mutex_name_size);
00190 #else
00191 #define ast_find_lock_info(a,b,c,d,e,f,g,h) -1
00192 #endif
00193 
00194 /*!
00195  * \brief Unlock a lock briefly
00196  *
00197  * used during deadlock avoidance, to preserve the original location where
00198  * a lock was originally acquired.
00199  */
00200 #define DEADLOCK_AVOIDANCE(lock) \
00201    do { \
00202       char __filename[80], __func[80], __mutex_name[80]; \
00203       int __lineno; \
00204       int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
00205       ast_mutex_unlock(lock); \
00206       usleep(1); \
00207       if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
00208          ast_mutex_lock(lock); \
00209       } else { \
00210          __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
00211       } \
00212    } while (0)
00213 
00214 static void __attribute__((constructor)) init_empty_mutex(void)
00215 {
00216    memset(&empty_mutex, 0, sizeof(empty_mutex));
00217 }
00218 
00219 static inline void ast_reentrancy_lock(ast_mutex_t *p_ast_mutex)
00220 {
00221    pthread_mutex_lock(&p_ast_mutex->reentr_mutex);
00222 }
00223 
00224 static inline void ast_reentrancy_unlock(ast_mutex_t *p_ast_mutex)
00225 {
00226    pthread_mutex_unlock(&p_ast_mutex->reentr_mutex);
00227 }
00228 
00229 static inline void ast_reentrancy_init(ast_mutex_t *p_ast_mutex)
00230 {
00231    int i;
00232    pthread_mutexattr_t reentr_attr;
00233 
00234    for (i = 0; i < AST_MAX_REENTRANCY; i++) {
00235       p_ast_mutex->file[i] = NULL;
00236       p_ast_mutex->lineno[i] = 0;
00237       p_ast_mutex->func[i] = NULL;
00238       p_ast_mutex->thread[i] = 0;
00239    }
00240 
00241    p_ast_mutex->reentrancy = 0;
00242 
00243    pthread_mutexattr_init(&reentr_attr);
00244    pthread_mutexattr_settype(&reentr_attr, AST_MUTEX_KIND);
00245    pthread_mutex_init(&p_ast_mutex->reentr_mutex, &reentr_attr);
00246    pthread_mutexattr_destroy(&reentr_attr);
00247 }
00248 
00249 static inline void delete_reentrancy_cs(ast_mutex_t * p_ast_mutex)
00250 {
00251    pthread_mutex_destroy(&p_ast_mutex->reentr_mutex);
00252 }
00253 
00254 static inline int __ast_pthread_mutex_init(int track, const char *filename, int lineno, const char *func,
00255                   const char *mutex_name, ast_mutex_t *t) 
00256 {
00257    int res;
00258    pthread_mutexattr_t  attr;
00259 
00260 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00261 
00262    if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00263 /*
00264       int canlog = strcmp(filename, "logger.c") & track;
00265       __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n",
00266                filename, lineno, func, mutex_name);
00267       DO_THREAD_CRASH;
00268 */
00269       return 0;
00270    }
00271 
00272 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00273 
00274    ast_reentrancy_init(t);
00275    t->track = track;
00276 
00277    pthread_mutexattr_init(&attr);
00278    pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00279 
00280    res = pthread_mutex_init(&t->mutex, &attr);
00281    pthread_mutexattr_destroy(&attr);
00282    return res;
00283 }
00284 
00285 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
00286 #define ast_mutex_init_notracking(pmutex) \
00287    __ast_pthread_mutex_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
00288 
00289 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
00290                   const char *mutex_name, ast_mutex_t *t)
00291 {
00292    int res;
00293    int canlog = strcmp(filename, "logger.c") & t->track;
00294 
00295 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00296    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00297       /* Don't try to uninitialize non initialized mutex
00298        * This may no effect on linux
00299        * And always ganerate core on *BSD with 
00300        * linked libpthread
00301        * This not error condition if the mutex created on the fly.
00302        */
00303       __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
00304                filename, lineno, func, mutex_name);
00305       return 0;
00306    }
00307 #endif
00308 
00309    res = pthread_mutex_trylock(&t->mutex);
00310    switch (res) {
00311    case 0:
00312       pthread_mutex_unlock(&t->mutex);
00313       break;
00314    case EINVAL:
00315       __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
00316               filename, lineno, func, mutex_name);
00317       break;
00318    case EBUSY:
00319       __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
00320                filename, lineno, func, mutex_name);
00321       ast_reentrancy_lock(t);
00322       __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
00323              t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00324       ast_reentrancy_unlock(t);
00325       break;
00326    }
00327 
00328    if ((res = pthread_mutex_destroy(&t->mutex)))
00329       __ast_mutex_logger("%s line %d (%s): Error destroying mutex %s: %s\n",
00330                filename, lineno, func, mutex_name, strerror(res));
00331 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00332    else
00333       t->mutex = PTHREAD_MUTEX_INIT_VALUE;
00334 #endif
00335    ast_reentrancy_lock(t);
00336    t->file[0] = filename;
00337    t->lineno[0] = lineno;
00338    t->func[0] = func;
00339    t->reentrancy = 0;
00340    t->thread[0] = 0;
00341    ast_reentrancy_unlock(t);
00342    delete_reentrancy_cs(t);
00343 
00344    return res;
00345 }
00346 
00347 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
00348                                            const char* mutex_name, ast_mutex_t *t)
00349 {
00350    int res;
00351    int canlog = strcmp(filename, "logger.c") & t->track;
00352 
00353 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00354    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00355       /* Don't warn abount uninitialized mutex.
00356        * Simple try to initialize it.
00357        * May be not needed in linux system.
00358        */
00359       res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
00360       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00361          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00362                 filename, lineno, func, mutex_name);
00363          return res;
00364       }     
00365    }
00366 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00367 
00368    if (t->track)
00369       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
00370 
00371 #ifdef DETECT_DEADLOCKS
00372    {
00373       time_t seconds = time(NULL);
00374       time_t wait_time, reported_wait = 0;
00375       do {
00376 #ifdef   HAVE_MTX_PROFILE
00377          ast_mark(mtx_prof, 1);
00378 #endif
00379          res = pthread_mutex_trylock(&t->mutex);
00380 #ifdef   HAVE_MTX_PROFILE
00381          ast_mark(mtx_prof, 0);
00382 #endif
00383          if (res == EBUSY) {
00384             wait_time = time(NULL) - seconds;
00385             if (wait_time > reported_wait && (wait_time % 5) == 0) {
00386                __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
00387                         filename, lineno, func, (int) wait_time, mutex_name);
00388                ast_reentrancy_lock(t);
00389                __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00390                         t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
00391                         t->func[t->reentrancy-1], mutex_name);
00392                ast_reentrancy_unlock(t);
00393                reported_wait = wait_time;
00394             }
00395             usleep(200);
00396          }
00397       } while (res == EBUSY);
00398    }
00399 #else
00400 #ifdef   HAVE_MTX_PROFILE
00401    ast_mark(mtx_prof, 1);
00402    res = pthread_mutex_trylock(&t->mutex);
00403    ast_mark(mtx_prof, 0);
00404    if (res)
00405 #endif
00406    res = pthread_mutex_lock(&t->mutex);
00407 #endif /* DETECT_DEADLOCKS */
00408 
00409    if (!res) {
00410       ast_reentrancy_lock(t);
00411       if (t->reentrancy < AST_MAX_REENTRANCY) {
00412          t->file[t->reentrancy] = filename;
00413          t->lineno[t->reentrancy] = lineno;
00414          t->func[t->reentrancy] = func;
00415          t->thread[t->reentrancy] = pthread_self();
00416          t->reentrancy++;
00417       } else {
00418          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00419                         filename, lineno, func, mutex_name);
00420       }
00421       ast_reentrancy_unlock(t);
00422       if (t->track)
00423          ast_mark_lock_acquired(&t->mutex);
00424    } else {
00425       if (t->track)
00426          ast_remove_lock_info(&t->mutex);
00427       __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
00428                filename, lineno, func, strerror(res));
00429       DO_THREAD_CRASH;
00430    }
00431 
00432    return res;
00433 }
00434 
00435 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
00436                                               const char* mutex_name, ast_mutex_t *t)
00437 {
00438    int res;
00439    int canlog = strcmp(filename, "logger.c") & t->track;
00440 
00441 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00442    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00443       /* Don't warn abount uninitialized mutex.
00444        * Simple try to initialize it.
00445        * May be not needed in linux system.
00446        */
00447       res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
00448       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00449          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00450                 filename, lineno, func, mutex_name);
00451          return res;
00452       }     
00453    }
00454 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00455 
00456    if (t->track)
00457       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
00458 
00459    if (!(res = pthread_mutex_trylock(&t->mutex))) {
00460       ast_reentrancy_lock(t);
00461       if (t->reentrancy < AST_MAX_REENTRANCY) {
00462          t->file[t->reentrancy] = filename;
00463          t->lineno[t->reentrancy] = lineno;
00464          t->func[t->reentrancy] = func;
00465          t->thread[t->reentrancy] = pthread_self();
00466          t->reentrancy++;
00467       } else {
00468          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00469                   filename, lineno, func, mutex_name);
00470       }
00471       ast_reentrancy_unlock(t);
00472       if (t->track)
00473          ast_mark_lock_acquired(&t->mutex);
00474    } else if (t->track) {
00475       ast_mark_lock_failed(&t->mutex);
00476    }
00477 
00478    return res;
00479 }
00480 
00481 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
00482                     const char *mutex_name, ast_mutex_t *t)
00483 {
00484    int res;
00485    int canlog = strcmp(filename, "logger.c") & t->track;
00486 
00487 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00488    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00489       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00490                filename, lineno, func, mutex_name);
00491       res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
00492       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00493          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00494                 filename, lineno, func, mutex_name);
00495       }
00496       return res;
00497    }
00498 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00499 
00500    ast_reentrancy_lock(t);
00501    if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
00502       __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00503                filename, lineno, func, mutex_name);
00504       __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00505                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00506       DO_THREAD_CRASH;
00507    }
00508 
00509    if (--t->reentrancy < 0) {
00510       __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00511                filename, lineno, func, mutex_name);
00512       t->reentrancy = 0;
00513    }
00514 
00515    if (t->reentrancy < AST_MAX_REENTRANCY) {
00516       t->file[t->reentrancy] = NULL;
00517       t->lineno[t->reentrancy] = 0;
00518       t->func[t->reentrancy] = NULL;
00519       t->thread[t->reentrancy] = 0;
00520    }
00521    ast_reentrancy_unlock(t);
00522 
00523    if (t->track)
00524       ast_remove_lock_info(&t->mutex);
00525 
00526    if ((res = pthread_mutex_unlock(&t->mutex))) {
00527       __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 
00528                filename, lineno, func, strerror(res));
00529       DO_THREAD_CRASH;
00530    }
00531 
00532    return res;
00533 }
00534 
00535 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
00536               const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
00537 {
00538    return pthread_cond_init(cond, cond_attr);
00539 }
00540 
00541 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
00542                 const char *cond_name, ast_cond_t *cond)
00543 {
00544    return pthread_cond_signal(cond);
00545 }
00546 
00547 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
00548                    const char *cond_name, ast_cond_t *cond)
00549 {
00550    return pthread_cond_broadcast(cond);
00551 }
00552 
00553 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
00554                  const char *cond_name, ast_cond_t *cond)
00555 {
00556    return pthread_cond_destroy(cond);
00557 }
00558 
00559 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
00560               const char *cond_name, const char *mutex_name,
00561               ast_cond_t *cond, ast_mutex_t *t)
00562 {
00563    int res;
00564    int canlog = strcmp(filename, "logger.c") & t->track;
00565 
00566 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00567    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00568       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00569                filename, lineno, func, mutex_name);
00570       res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
00571       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00572          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00573                 filename, lineno, func, mutex_name);
00574       }
00575       return res;
00576    }
00577 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00578 
00579    ast_reentrancy_lock(t);
00580    if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
00581       __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00582                filename, lineno, func, mutex_name);
00583       __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00584                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00585       DO_THREAD_CRASH;
00586    }
00587 
00588    if (--t->reentrancy < 0) {
00589       __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00590                filename, lineno, func, mutex_name);
00591       t->reentrancy = 0;
00592    }
00593 
00594    if (t->reentrancy < AST_MAX_REENTRANCY) {
00595       t->file[t->reentrancy] = NULL;
00596       t->lineno[t->reentrancy] = 0;
00597       t->func[t->reentrancy] = NULL;
00598       t->thread[t->reentrancy] = 0;
00599    }
00600    ast_reentrancy_unlock(t);
00601 
00602    if (t->track)
00603       ast_remove_lock_info(&t->mutex);
00604 
00605    if ((res = pthread_cond_wait(cond, &t->mutex))) {
00606       __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
00607                filename, lineno, func, strerror(res));
00608       DO_THREAD_CRASH;
00609    } else {
00610       ast_reentrancy_lock(t);
00611       if (t->reentrancy < AST_MAX_REENTRANCY) {
00612          t->file[t->reentrancy] = filename;
00613          t->lineno[t->reentrancy] = lineno;
00614          t->func[t->reentrancy] = func;
00615          t->thread[t->reentrancy] = pthread_self();
00616          t->reentrancy++;
00617       } else {
00618          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00619                         filename, lineno, func, mutex_name);
00620       }
00621       ast_reentrancy_unlock(t);
00622 
00623       if (t->track)
00624          ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
00625    }
00626 
00627    return res;
00628 }
00629 
00630 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
00631                    const char *cond_name, const char *mutex_name, ast_cond_t *cond,
00632                    ast_mutex_t *t, const struct timespec *abstime)
00633 {
00634    int res;
00635    int canlog = strcmp(filename, "logger.c") & t->track;
00636 
00637 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00638    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00639       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00640                filename, lineno, func, mutex_name);
00641       res = __ast_pthread_mutex_init(t->track, filename, lineno, func, mutex_name, t);
00642       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00643          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00644                 filename, lineno, func, mutex_name);
00645       }
00646       return res;
00647    }
00648 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00649 
00650    ast_reentrancy_lock(t);
00651    if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
00652       __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00653                filename, lineno, func, mutex_name);
00654       __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00655                t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00656       DO_THREAD_CRASH;
00657    }
00658 
00659    if (--t->reentrancy < 0) {
00660       __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00661                filename, lineno, func, mutex_name);
00662       t->reentrancy = 0;
00663    }
00664 
00665    if (t->reentrancy < AST_MAX_REENTRANCY) {
00666       t->file[t->reentrancy] = NULL;
00667       t->lineno[t->reentrancy] = 0;
00668       t->func[t->reentrancy] = NULL;
00669       t->thread[t->reentrancy] = 0;
00670    }
00671    ast_reentrancy_unlock(t);
00672 
00673    if (t->track)
00674       ast_remove_lock_info(&t->mutex);
00675 
00676    if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
00677       __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 
00678                filename, lineno, func, strerror(res));
00679       DO_THREAD_CRASH;
00680    } else {
00681       ast_reentrancy_lock(t);
00682       if (t->reentrancy < AST_MAX_REENTRANCY) {
00683          t->file[t->reentrancy] = filename;
00684          t->lineno[t->reentrancy] = lineno;
00685          t->func[t->reentrancy] = func;
00686          t->thread[t->reentrancy] = pthread_self();
00687          t->reentrancy++;
00688       } else {
00689          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00690                         filename, lineno, func, mutex_name);
00691       }
00692       ast_reentrancy_unlock(t);
00693 
00694       if (t->track)
00695          ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, &t->mutex);
00696    }
00697 
00698    return res;
00699 }
00700 
00701 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00702 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00703 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00704 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00705 #define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
00706 #define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00707 #define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00708 #define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00709 #define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
00710 #define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
00711 
00712 #else /* !DEBUG_THREADS */
00713 
00714 #define  DEADLOCK_AVOIDANCE(lock) \
00715    ast_mutex_unlock(lock); \
00716    usleep(1); \
00717    ast_mutex_lock(lock);
00718 
00719 
00720 typedef pthread_mutex_t ast_mutex_t;
00721 
00722 #define AST_MUTEX_INIT_VALUE  ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
00723 #define AST_MUTEX_INIT_VALUE_NOTRACKING \
00724    ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
00725 
00726 #define ast_mutex_init_notracking(m) ast_mutex_init(m)
00727 
00728 static inline int ast_mutex_init(ast_mutex_t *pmutex)
00729 {
00730    int res;
00731    pthread_mutexattr_t attr;
00732 
00733    pthread_mutexattr_init(&attr);
00734    pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00735 
00736    res = pthread_mutex_init(pmutex, &attr);
00737    pthread_mutexattr_destroy(&attr);
00738    return res;
00739 }
00740 
00741 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
00742 
00743 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
00744 {
00745    return pthread_mutex_unlock(pmutex);
00746 }
00747 
00748 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
00749 {
00750    return pthread_mutex_destroy(pmutex);
00751 }
00752 
00753 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
00754 {
00755    __MTX_PROF(pmutex);
00756 }
00757 
00758 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
00759 {
00760    return pthread_mutex_trylock(pmutex);
00761 }
00762 
00763 typedef pthread_cond_t ast_cond_t;
00764 
00765 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
00766 {
00767    return pthread_cond_init(cond, cond_attr);
00768 }
00769 
00770 static inline int ast_cond_signal(ast_cond_t *cond)
00771 {
00772    return pthread_cond_signal(cond);
00773 }
00774 
00775 static inline int ast_cond_broadcast(ast_cond_t *cond)
00776 {
00777    return pthread_cond_broadcast(cond);
00778 }
00779 
00780 static inline int ast_cond_destroy(ast_cond_t *cond)
00781 {
00782    return pthread_cond_destroy(cond);
00783 }
00784 
00785 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
00786 {
00787    return pthread_cond_wait(cond, t);
00788 }
00789 
00790 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
00791 {
00792    return pthread_cond_timedwait(cond, t, abstime);
00793 }
00794 
00795 #endif /* !DEBUG_THREADS */
00796 
00797 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00798 /* If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope
00799  destructors to destroy mutexes and create it on the fly.  */
00800 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track) \
00801    scope ast_mutex_t mutex = init_val; \
00802 static void  __attribute__((constructor)) init_##mutex(void) \
00803 { \
00804    if (track) \
00805       ast_mutex_init(&mutex); \
00806    else \
00807       ast_mutex_init_notracking(&mutex); \
00808 } \
00809 static void  __attribute__((destructor)) fini_##mutex(void) \
00810 { \
00811    ast_mutex_destroy(&mutex); \
00812 }
00813 #else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
00814 /* By default, use static initialization of mutexes. */ 
00815 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track) \
00816    scope ast_mutex_t mutex = init_val
00817 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00818 
00819 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
00820 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
00821 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
00822 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
00823 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
00824 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
00825 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
00826 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
00827 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
00828 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
00829 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
00830 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
00831 #define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
00832 
00833 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
00834 #define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
00835 
00836 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
00837 
00838 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
00839 
00840 #ifndef __linux__
00841 #define pthread_create __use_ast_pthread_create_instead__
00842 #endif
00843 
00844 typedef pthread_rwlock_t ast_rwlock_t;
00845 
00846 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
00847 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
00848 #else
00849 #define AST_RWLOCK_INIT_VALUE NULL
00850 #endif
00851 
00852 #ifdef DEBUG_THREADS
00853 
00854 #define ast_rwlock_init(rwlock) __ast_rwlock_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
00855 
00856 
00857 static inline int __ast_rwlock_init(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
00858 {
00859    int res;
00860    pthread_rwlockattr_t attr;
00861 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00862         int canlog = strcmp(filename, "logger.c");
00863 
00864         if (*prwlock != ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
00865       __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
00866             filename, lineno, func, rwlock_name);
00867       return 0;
00868    }
00869 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00870    pthread_rwlockattr_init(&attr);
00871 
00872 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
00873    pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
00874 #endif
00875 
00876    res = pthread_rwlock_init(prwlock, &attr);
00877    pthread_rwlockattr_destroy(&attr);
00878    return res;
00879 }
00880 
00881 #define ast_rwlock_destroy(rwlock) __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
00882 
00883 static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *prwlock)
00884 {
00885    int res;
00886    int canlog = strcmp(filename, "logger.c");
00887 
00888 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00889    if (*prwlock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
00890       __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
00891                filename, lineno, func, rwlock_name);
00892       return 0;
00893    }
00894 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00895    
00896    if ((res = pthread_rwlock_destroy(prwlock)))
00897       __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
00898             filename, lineno, func, rwlock_name, strerror(res));
00899 
00900    return res;
00901 }
00902 
00903 #define ast_rwlock_unlock(a) \
00904    _ast_rwlock_unlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00905 
00906 static inline int _ast_rwlock_unlock(ast_rwlock_t *lock, const char *name,
00907    const char *file, int line, const char *func)
00908 {
00909    int res;
00910 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00911    int canlog = strcmp(file, "logger.c");
00912 
00913    if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
00914       __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
00915                file, line, func, name);
00916       res = __ast_rwlock_init(file, line, func, name, lock);
00917       if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
00918          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
00919                file, line, func, name);
00920       }
00921       return res;
00922    }
00923 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00924    
00925    res = pthread_rwlock_unlock(lock);
00926    ast_remove_lock_info(lock);
00927    return res;
00928 }
00929 
00930 #define ast_rwlock_rdlock(a) \
00931    _ast_rwlock_rdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00932 
00933 static inline int _ast_rwlock_rdlock(ast_rwlock_t *lock, const char *name,
00934    const char *file, int line, const char *func)
00935 {
00936    int res;
00937 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00938    int canlog = strcmp(file, "logger.c");
00939    
00940    if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
00941        /* Don't warn abount uninitialized lock.
00942         * Simple try to initialize it.
00943         * May be not needed in linux system.
00944         */
00945       res = __ast_rwlock_init(file, line, func, name, lock);
00946       if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
00947          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
00948                file, line, func, name);
00949          return res;
00950       }
00951    }
00952 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00953    
00954    ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
00955    res = pthread_rwlock_rdlock(lock);
00956    if (!res)
00957       ast_mark_lock_acquired(lock);
00958    else
00959       ast_remove_lock_info(lock);
00960    return res;
00961 }
00962 
00963 #define ast_rwlock_wrlock(a) \
00964    _ast_rwlock_wrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00965 
00966 static inline int _ast_rwlock_wrlock(ast_rwlock_t *lock, const char *name,
00967    const char *file, int line, const char *func)
00968 {
00969    int res;
00970 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00971    int canlog = strcmp(file, "logger.c");
00972    
00973    if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
00974        /* Don't warn abount uninitialized lock.
00975         * Simple try to initialize it.
00976         * May be not needed in linux system.
00977         */
00978       res = __ast_rwlock_init(file, line, func, name, lock);
00979       if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
00980          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
00981                file, line, func, name);
00982          return res;
00983       }
00984    }
00985 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00986 
00987    ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
00988    res = pthread_rwlock_wrlock(lock);
00989    if (!res)
00990       ast_mark_lock_acquired(lock);
00991    else
00992       ast_remove_lock_info(lock);
00993    return res;
00994 }
00995 
00996 #define ast_rwlock_tryrdlock(a) \
00997    _ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00998 
00999 static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *lock, const char *name,
01000    const char *file, int line, const char *func)
01001 {
01002    int res;
01003 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01004    int canlog = strcmp(file, "logger.c");
01005    
01006    if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
01007        /* Don't warn abount uninitialized lock.
01008         * Simple try to initialize it.
01009         * May be not needed in linux system.
01010         */
01011       res = __ast_rwlock_init(file, line, func, name, lock);
01012       if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
01013          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01014                file, line, func, name);
01015          return res;
01016       }
01017    }
01018 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
01019 
01020    ast_store_lock_info(AST_RDLOCK, file, line, func, name, lock);
01021    res = pthread_rwlock_tryrdlock(lock);
01022    if (!res)
01023       ast_mark_lock_acquired(lock);
01024    else
01025       ast_remove_lock_info(lock);
01026    return res;
01027 }
01028 
01029 #define ast_rwlock_trywrlock(a) \
01030    _ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01031 
01032 static inline int _ast_rwlock_trywrlock(ast_rwlock_t *lock, const char *name,
01033    const char *file, int line, const char *func)
01034 {
01035    int res;
01036 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01037    int canlog = strcmp(file, "logger.c");
01038    
01039    if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
01040        /* Don't warn abount uninitialized lock.
01041         * Simple try to initialize it.
01042         * May be not needed in linux system.
01043         */
01044       res = __ast_rwlock_init(file, line, func, name, lock);
01045       if (*lock == ((ast_rwlock_t) AST_RWLOCK_INIT_VALUE)) {
01046          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01047                file, line, func, name);
01048          return res;
01049       }
01050    }
01051 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
01052 
01053    ast_store_lock_info(AST_WRLOCK, file, line, func, name, lock);
01054    res = pthread_rwlock_trywrlock(lock);
01055    if (!res)
01056       ast_mark_lock_acquired(lock);
01057    else
01058       ast_remove_lock_info(lock);
01059    return res;
01060 }
01061 
01062 #else /* !DEBUG_THREADS */
01063 
01064 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
01065 {
01066    int res;
01067    pthread_rwlockattr_t attr;
01068 
01069    pthread_rwlockattr_init(&attr);
01070 
01071 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
01072    pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
01073 #endif
01074 
01075    res = pthread_rwlock_init(prwlock, &attr);
01076    pthread_rwlockattr_destroy(&attr);
01077    return res;
01078 }
01079 
01080 static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
01081 {
01082    return pthread_rwlock_destroy(prwlock);
01083 }
01084 
01085 static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
01086 {
01087    return pthread_rwlock_unlock(prwlock);
01088 }
01089 
01090 static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
01091 {
01092    return pthread_rwlock_rdlock(prwlock);
01093 }
01094 
01095 static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
01096 {
01097    return pthread_rwlock_tryrdlock(prwlock);
01098 }
01099 
01100 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
01101 {
01102    return pthread_rwlock_wrlock(prwlock);
01103 }
01104 
01105 static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
01106 {
01107    return pthread_rwlock_trywrlock(prwlock);
01108 }
01109 #endif /* !DEBUG_THREADS */
01110 
01111 /* Statically declared read/write locks */
01112 
01113 #ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
01114 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
01115         scope ast_rwlock_t rwlock; \
01116 static void  __attribute__((constructor)) init_##rwlock(void) \
01117 { \
01118         ast_rwlock_init(&rwlock); \
01119 } \
01120 static void  __attribute__((destructor)) fini_##rwlock(void) \
01121 { \
01122         ast_rwlock_destroy(&rwlock); \
01123 }
01124 #else
01125 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
01126         scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE
01127 #endif
01128 
01129 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
01130 
01131 /*
01132  * Initial support for atomic instructions.
01133  * For platforms that have it, use the native cpu instruction to
01134  * implement them. For other platforms, resort to a 'slow' version
01135  * (defined in utils.c) that protects the atomic instruction with
01136  * a single lock.
01137  * The slow versions is always available, for testing purposes,
01138  * as ast_atomic_fetchadd_int_slow()
01139  */
01140 
01141 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
01142 
01143 #include "asterisk/inline_api.h"
01144 
01145 #if defined(HAVE_OSX_ATOMICS)
01146 #include "libkern/OSAtomic.h"
01147 #endif
01148 
01149 /*! \brief Atomically add v to *p and return * the previous value of *p.
01150  * This can be used to handle reference counts, and the return value
01151  * can be used to generate unique identifiers.
01152  */
01153 
01154 #if defined(HAVE_GCC_ATOMICS)
01155 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01156 {
01157    return __sync_fetch_and_add(p, v);
01158 })
01159 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
01160 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01161 {
01162    return OSAtomicAdd32(v, (int32_t *) p) - v;
01163 })
01164 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
01165 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01166 {
01167    return OSAtomicAdd64(v, (int64_t *) p) - v;
01168 #elif defined (__i386__)
01169 #ifdef sun
01170 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01171 {
01172    __asm __volatile (
01173    "       lock;  xaddl   %0, %1 ;        "
01174    : "+r" (v),                     /* 0 (result) */   
01175      "=m" (*p)                     /* 1 */
01176    : "m" (*p));                    /* 2 */
01177    return (v);
01178 })
01179 #else /* ifndef sun */
01180 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01181 {
01182    __asm __volatile (
01183    "       lock   xaddl   %0, %1 ;        "
01184    : "+r" (v),                     /* 0 (result) */   
01185      "=m" (*p)                     /* 1 */
01186    : "m" (*p));                    /* 2 */
01187    return (v);
01188 })
01189 #endif
01190 #else   /* low performance version in utils.c */
01191 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01192 {
01193    return ast_atomic_fetchadd_int_slow(p, v);
01194 })
01195 #endif
01196 
01197 /*! \brief decrement *p by 1 and return true if the variable has reached 0.
01198  * Useful e.g. to check if a refcount has reached 0.
01199  */
01200 #if defined(HAVE_GCC_ATOMICS)
01201 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
01202 {
01203    return __sync_sub_and_fetch(p, 1) == 0;
01204 })
01205 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
01206 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
01207 {
01208    return OSAtomicAdd32( -1, (int32_t *) p) == 0;
01209 })
01210 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
01211 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
01212 {
01213    return OSAtomicAdd64( -1, (int64_t *) p) == 0;
01214 #else
01215 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
01216 {
01217    int a = ast_atomic_fetchadd_int(p, -1);
01218    return a == 1; /* true if the value is 0 now (so it was 1 previously) */
01219 })
01220 #endif
01221 
01222 #ifndef DEBUG_CHANNEL_LOCKS
01223 /*! \brief Lock a channel. If DEBUG_CHANNEL_LOCKS is defined 
01224    in the Makefile, print relevant output for debugging */
01225 #define ast_channel_lock(x)      ast_mutex_lock(&x->lock)
01226 /*! \brief Unlock a channel. If DEBUG_CHANNEL_LOCKS is defined 
01227    in the Makefile, print relevant output for debugging */
01228 #define ast_channel_unlock(x)    ast_mutex_unlock(&x->lock)
01229 /*! \brief Try locking a channel. If DEBUG_CHANNEL_LOCKS is defined 
01230    in the Makefile, print relevant output for debugging */
01231 #define ast_channel_trylock(x)      ast_mutex_trylock(&x->lock)
01232 #else
01233 
01234 struct ast_channel;
01235 
01236 #define ast_channel_lock(a) __ast_channel_lock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01237 /*! \brief Lock AST channel (and print debugging output)
01238 \note You need to enable DEBUG_CHANNEL_LOCKS for this function */
01239 int __ast_channel_lock(struct ast_channel *chan, const char *file, int lineno, const char *func);
01240 
01241 #define ast_channel_unlock(a) __ast_channel_unlock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01242 /*! \brief Unlock AST channel (and print debugging output)
01243 \note You need to enable DEBUG_CHANNEL_LOCKS for this function
01244 */
01245 int __ast_channel_unlock(struct ast_channel *chan, const char *file, int lineno, const char *func);
01246 
01247 #define ast_channel_trylock(a) __ast_channel_trylock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01248 /*! \brief Lock AST channel (and print debugging output)
01249 \note   You need to enable DEBUG_CHANNEL_LOCKS for this function */
01250 int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func);
01251 #endif
01252 
01253 #endif /* _ASTERISK_LOCK_H */

Generated on Wed Feb 11 11:59:56 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7