Mon Oct 8 12:39:24 2012

Asterisk developer's documentation


lock.c File Reference

General Asterisk locking. More...

#include "asterisk.h"
#include "asterisk/lock.h"

Go to the source code of this file.

Functions

int __ast_cond_broadcast (const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond)
int __ast_cond_destroy (const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond)
int __ast_cond_init (const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
int __ast_cond_signal (const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond)
int __ast_cond_timedwait (const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
int __ast_cond_wait (const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t)
int __ast_pthread_mutex_destroy (const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
int __ast_pthread_mutex_init (int tracking, const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
int __ast_pthread_mutex_lock (const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
int __ast_pthread_mutex_trylock (const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
int __ast_pthread_mutex_unlock (const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
int __ast_rwlock_destroy (const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
int __ast_rwlock_init (int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
int __ast_rwlock_rdlock (const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
int __ast_rwlock_timedrdlock (const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout)
int __ast_rwlock_timedwrlock (const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout)
int __ast_rwlock_tryrdlock (const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
int __ast_rwlock_trywrlock (const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
int __ast_rwlock_unlock (const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)
int __ast_rwlock_wrlock (const char *filename, int line, const char *func, ast_rwlock_t *t, const char *name)


Detailed Description

General Asterisk locking.

Definition in file lock.c.


Function Documentation

int __ast_cond_broadcast ( const char *  filename,
int  lineno,
const char *  func,
const char *  cond_name,
ast_cond_t cond 
)

Definition at line 463 of file lock.c.

References pthread_cond_broadcast.

00465 {
00466    return pthread_cond_broadcast(cond);
00467 }

int __ast_cond_destroy ( const char *  filename,
int  lineno,
const char *  func,
const char *  cond_name,
ast_cond_t cond 
)

Definition at line 469 of file lock.c.

References pthread_cond_destroy.

00471 {
00472    return pthread_cond_destroy(cond);
00473 }

int __ast_cond_init ( const char *  filename,
int  lineno,
const char *  func,
const char *  cond_name,
ast_cond_t cond,
pthread_condattr_t *  cond_attr 
)

Definition at line 451 of file lock.c.

References pthread_cond_init.

00453 {
00454    return pthread_cond_init(cond, cond_attr);
00455 }

int __ast_cond_signal ( const char *  filename,
int  lineno,
const char *  func,
const char *  cond_name,
ast_cond_t cond 
)

Definition at line 457 of file lock.c.

References pthread_cond_signal.

00459 {
00460    return pthread_cond_signal(cond);
00461 }

int __ast_cond_timedwait ( const char *  filename,
int  lineno,
const char *  func,
const char *  cond_name,
const char *  mutex_name,
ast_cond_t cond,
ast_mutex_t t,
const struct timespec *  abstime 
)

Definition at line 583 of file lock.c.

References __ast_pthread_mutex_init(), ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, pthread_cond_timedwait, pthread_mutex_t, ast_lock_track::reentrancy, ROFFSET, ast_lock_track::thread, ast_mutex_info::track, and ast_mutex_info::tracking.

00586 {
00587    int res;
00588 
00589 #ifdef DEBUG_THREADS
00590    struct ast_lock_track *lt;
00591    int canlog = strcmp(filename, "logger.c") & t->tracking;
00592 #ifdef HAVE_BKTR
00593    struct ast_bt *bt = NULL;
00594 #endif
00595 
00596 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00597    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00598       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00599                filename, lineno, func, mutex_name);
00600       res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00601       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00602          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00603                 filename, lineno, func, mutex_name);
00604       }
00605       return res;
00606    }
00607 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00608 
00609    if (t->tracking && !t->track) {
00610       ast_reentrancy_init(&t->track);
00611    }
00612    lt = t->track;
00613 
00614    if (t->tracking) {
00615       ast_reentrancy_lock(lt);
00616       if (lt->reentrancy && (lt->thread[ROFFSET] != pthread_self())) {
00617          __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00618                   filename, lineno, func, mutex_name);
00619          __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00620                   lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
00621 #ifdef HAVE_BKTR
00622          __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
00623 #endif
00624          DO_THREAD_CRASH;
00625       }
00626 
00627       if (--lt->reentrancy < 0) {
00628          __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00629                   filename, lineno, func, mutex_name);
00630          lt->reentrancy = 0;
00631       }
00632 
00633       if (lt->reentrancy < AST_MAX_REENTRANCY) {
00634          lt->file[lt->reentrancy] = NULL;
00635          lt->lineno[lt->reentrancy] = 0;
00636          lt->func[lt->reentrancy] = NULL;
00637          lt->thread[lt->reentrancy] = 0;
00638       }
00639 #ifdef HAVE_BKTR
00640       if (lt->reentrancy) {
00641          bt = &lt->backtrace[lt->reentrancy - 1];
00642       }
00643 #endif
00644       ast_reentrancy_unlock(lt);
00645 
00646 #ifdef HAVE_BKTR
00647       ast_remove_lock_info(t, bt);
00648 #else
00649       ast_remove_lock_info(t);
00650 #endif
00651    }
00652 #endif /* DEBUG_THREADS */
00653 
00654    res = pthread_cond_timedwait(cond, &t->mutex, abstime);
00655 
00656 #ifdef DEBUG_THREADS
00657    if (res && (res != ETIMEDOUT)) {
00658       __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
00659                filename, lineno, func, strerror(res));
00660       DO_THREAD_CRASH;
00661    } else if (t->tracking) {
00662       ast_reentrancy_lock(lt);
00663       if (lt->reentrancy < AST_MAX_REENTRANCY) {
00664          lt->file[lt->reentrancy] = filename;
00665          lt->lineno[lt->reentrancy] = lineno;
00666          lt->func[lt->reentrancy] = func;
00667          lt->thread[lt->reentrancy] = pthread_self();
00668 #ifdef HAVE_BKTR
00669          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
00670          bt = &lt->backtrace[lt->reentrancy];
00671 #endif
00672          lt->reentrancy++;
00673       } else {
00674          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00675                         filename, lineno, func, mutex_name);
00676       }
00677       ast_reentrancy_unlock(lt);
00678 
00679 #ifdef HAVE_BKTR
00680       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
00681 #else
00682       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
00683 #endif
00684    }
00685 #endif /* DEBUG_THREADS */
00686 
00687    return res;
00688 }

int __ast_cond_wait ( const char *  filename,
int  lineno,
const char *  func,
const char *  cond_name,
const char *  mutex_name,
ast_cond_t cond,
ast_mutex_t t 
)

Definition at line 475 of file lock.c.

References __ast_pthread_mutex_init(), ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, pthread_cond_wait, pthread_mutex_t, ast_lock_track::reentrancy, ROFFSET, ast_lock_track::thread, ast_mutex_info::track, and ast_mutex_info::tracking.

00478 {
00479    int res;
00480 
00481 #ifdef DEBUG_THREADS
00482    struct ast_lock_track *lt;
00483    int canlog = strcmp(filename, "logger.c") & t->tracking;
00484 #ifdef HAVE_BKTR
00485    struct ast_bt *bt = NULL;
00486 #endif
00487 
00488 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00489    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00490       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00491                filename, lineno, func, mutex_name);
00492       res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00493       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00494          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00495                 filename, lineno, func, mutex_name);
00496       }
00497       return res;
00498    }
00499 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00500 
00501    if (t->tracking && !t->track) {
00502       ast_reentrancy_init(&t->track);
00503    }
00504    lt = t->track;
00505 
00506    if (t->tracking) {
00507       ast_reentrancy_lock(lt);
00508       if (lt->reentrancy && (lt->thread[ROFFSET] != pthread_self())) {
00509          __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00510                   filename, lineno, func, mutex_name);
00511          __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00512                   lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
00513 #ifdef HAVE_BKTR
00514          __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
00515 #endif
00516          DO_THREAD_CRASH;
00517       }
00518 
00519       if (--lt->reentrancy < 0) {
00520          __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00521                filename, lineno, func, mutex_name);
00522          lt->reentrancy = 0;
00523       }
00524 
00525       if (lt->reentrancy < AST_MAX_REENTRANCY) {
00526          lt->file[lt->reentrancy] = NULL;
00527          lt->lineno[lt->reentrancy] = 0;
00528          lt->func[lt->reentrancy] = NULL;
00529          lt->thread[lt->reentrancy] = 0;
00530       }
00531 
00532 #ifdef HAVE_BKTR
00533       if (lt->reentrancy) {
00534          bt = &lt->backtrace[lt->reentrancy - 1];
00535       }
00536 #endif
00537       ast_reentrancy_unlock(lt);
00538 
00539 #ifdef HAVE_BKTR
00540       ast_remove_lock_info(t, bt);
00541 #else
00542       ast_remove_lock_info(t);
00543 #endif
00544    }
00545 #endif /* DEBUG_THREADS */
00546 
00547    res = pthread_cond_wait(cond, &t->mutex);
00548 
00549 #ifdef DEBUG_THREADS
00550    if (res) {
00551       __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
00552                filename, lineno, func, strerror(res));
00553       DO_THREAD_CRASH;
00554    } else if (t->tracking) {
00555       ast_reentrancy_lock(lt);
00556       if (lt->reentrancy < AST_MAX_REENTRANCY) {
00557          lt->file[lt->reentrancy] = filename;
00558          lt->lineno[lt->reentrancy] = lineno;
00559          lt->func[lt->reentrancy] = func;
00560          lt->thread[lt->reentrancy] = pthread_self();
00561 #ifdef HAVE_BKTR
00562          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
00563          bt = &lt->backtrace[lt->reentrancy];
00564 #endif
00565          lt->reentrancy++;
00566       } else {
00567          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00568                         filename, lineno, func, mutex_name);
00569       }
00570       ast_reentrancy_unlock(lt);
00571 
00572 #ifdef HAVE_BKTR
00573       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
00574 #else
00575       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
00576 #endif
00577    }
00578 #endif /* DEBUG_THREADS */
00579 
00580    return res;
00581 }

int __ast_pthread_mutex_destroy ( const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 82 of file lock.c.

References ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, pthread_mutex_destroy, pthread_mutex_t, pthread_mutex_trylock, pthread_mutex_unlock, ast_lock_track::reentrancy, ROFFSET, ast_lock_track::thread, ast_mutex_info::track, and ast_mutex_info::tracking.

00084 {
00085    int res;
00086 
00087 #ifdef DEBUG_THREADS
00088    struct ast_lock_track *lt;
00089    int canlog = strcmp(filename, "logger.c") & t->tracking;
00090 
00091 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00092    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00093       /* Don't try to uninitialize non initialized mutex
00094        * This may no effect on linux
00095        * And always ganerate core on *BSD with
00096        * linked libpthread
00097        * This not error condition if the mutex created on the fly.
00098        */
00099       __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
00100                filename, lineno, func, mutex_name);
00101       return 0;
00102    }
00103 #endif
00104 
00105    if (t->tracking && !t->track) {
00106       ast_reentrancy_init(&t->track);
00107    }
00108    lt = t->track;
00109 
00110    res = pthread_mutex_trylock(&t->mutex);
00111    switch (res) {
00112    case 0:
00113       pthread_mutex_unlock(&t->mutex);
00114       break;
00115    case EINVAL:
00116       __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
00117               filename, lineno, func, mutex_name);
00118       break;
00119    case EBUSY:
00120       __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
00121                filename, lineno, func, mutex_name);
00122       if (t->tracking) {
00123          ast_reentrancy_lock(lt);
00124          __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
00125                 lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
00126 #ifdef HAVE_BKTR
00127          __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
00128 #endif
00129          ast_reentrancy_unlock(lt);
00130       }
00131       break;
00132    }
00133 #endif /* DEBUG_THREADS */
00134 
00135    res = pthread_mutex_destroy(&t->mutex);
00136 
00137 #ifdef DEBUG_THREADS
00138    if (res) {
00139       __ast_mutex_logger("%s line %d (%s): Error destroying mutex %s: %s\n",
00140                filename, lineno, func, mutex_name, strerror(res));
00141    }
00142    if (t->tracking) {
00143       ast_reentrancy_lock(lt);
00144       lt->file[0] = filename;
00145       lt->lineno[0] = lineno;
00146       lt->func[0] = func;
00147       lt->reentrancy = 0;
00148       lt->thread[0] = 0;
00149 #ifdef HAVE_BKTR
00150       memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
00151 #endif
00152       ast_reentrancy_unlock(lt);
00153       delete_reentrancy_cs(&t->track);
00154    }
00155 #endif /* DEBUG_THREADS */
00156 
00157    return res;
00158 }

int __ast_pthread_mutex_init ( int  tracking,
const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 48 of file lock.c.

References AST_MUTEX_KIND, ast_mutex_info::mutex, pthread_mutex_init, pthread_mutex_t, ast_mutex_info::track, and ast_mutex_info::tracking.

Referenced by __ast_cond_timedwait(), __ast_cond_wait(), __ast_pthread_mutex_lock(), __ast_pthread_mutex_trylock(), and __ast_pthread_mutex_unlock().

00050 {
00051    int res;
00052    pthread_mutexattr_t  attr;
00053 
00054    t->track = NULL;
00055 #ifdef DEBUG_THREADS
00056 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00057    if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00058 /*
00059       int canlog = strcmp(filename, "logger.c") & track;
00060       __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n",
00061                filename, lineno, func, mutex_name);
00062       DO_THREAD_CRASH;
00063 */
00064       return 0;
00065    }
00066 
00067 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00068 
00069    if ((t->tracking = tracking)) {
00070       ast_reentrancy_init(&t->track);
00071    }
00072 #endif /* DEBUG_THREADS */
00073 
00074    pthread_mutexattr_init(&attr);
00075    pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00076 
00077    res = pthread_mutex_init(&t->mutex, &attr);
00078    pthread_mutexattr_destroy(&attr);
00079    return res;
00080 }

int __ast_pthread_mutex_lock ( const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 160 of file lock.c.

References __ast_pthread_mutex_init(), ast_bt_get_addresses(), ast_mark(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, pthread_mutex_lock, pthread_mutex_t, pthread_mutex_trylock, ast_lock_track::reentrancy, ROFFSET, ast_mutex_info::track, and ast_mutex_info::tracking.

Referenced by __ao2_lock().

00162 {
00163    int res;
00164 
00165 #ifdef DEBUG_THREADS
00166    struct ast_lock_track *lt;
00167    int canlog = strcmp(filename, "logger.c") & t->tracking;
00168 #ifdef HAVE_BKTR
00169    struct ast_bt *bt = NULL;
00170 #endif
00171 
00172 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00173    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00174       /* Don't warn abount uninitialized mutex.
00175        * Simple try to initialize it.
00176        * May be not needed in linux system.
00177        */
00178       res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00179       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00180          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00181                 filename, lineno, func, mutex_name);
00182          return res;
00183       }
00184    }
00185 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00186 
00187    if (t->tracking && !t->track) {
00188       ast_reentrancy_init(&t->track);
00189    }
00190    lt = t->track;
00191 
00192    if (t->tracking) {
00193 #ifdef HAVE_BKTR
00194       ast_reentrancy_lock(lt);
00195       if (lt->reentrancy != AST_MAX_REENTRANCY) {
00196          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
00197          bt = &lt->backtrace[lt->reentrancy];
00198       }
00199       ast_reentrancy_unlock(lt);
00200       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
00201 #else
00202       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
00203 #endif
00204    }
00205 #endif /* DEBUG_THREADS */
00206 
00207 #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS)
00208    {
00209       time_t seconds = time(NULL);
00210       time_t wait_time, reported_wait = 0;
00211       do {
00212 #ifdef   HAVE_MTX_PROFILE
00213          ast_mark(mtx_prof, 1);
00214 #endif
00215          res = pthread_mutex_trylock(&t->mutex);
00216 #ifdef   HAVE_MTX_PROFILE
00217          ast_mark(mtx_prof, 0);
00218 #endif
00219          if (res == EBUSY) {
00220             wait_time = time(NULL) - seconds;
00221             if (wait_time > reported_wait && (wait_time % 5) == 0) {
00222                __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
00223                         filename, lineno, func, (int) wait_time, mutex_name);
00224                ast_reentrancy_lock(lt);
00225 #ifdef HAVE_BKTR
00226                __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
00227 #endif
00228                __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00229                         lt->file[ROFFSET], lt->lineno[ROFFSET],
00230                         lt->func[ROFFSET], mutex_name);
00231 #ifdef HAVE_BKTR
00232                __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
00233 #endif
00234                ast_reentrancy_unlock(lt);
00235                reported_wait = wait_time;
00236             }
00237             usleep(200);
00238          }
00239       } while (res == EBUSY);
00240    }
00241 #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
00242 #ifdef   HAVE_MTX_PROFILE
00243    ast_mark(mtx_prof, 1);
00244    res = pthread_mutex_trylock(&t->mutex);
00245    ast_mark(mtx_prof, 0);
00246    if (res)
00247 #endif
00248    res = pthread_mutex_lock(&t->mutex);
00249 #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
00250 
00251 #ifdef DEBUG_THREADS
00252    if (t->tracking && !res) {
00253       ast_reentrancy_lock(lt);
00254       if (lt->reentrancy < AST_MAX_REENTRANCY) {
00255          lt->file[lt->reentrancy] = filename;
00256          lt->lineno[lt->reentrancy] = lineno;
00257          lt->func[lt->reentrancy] = func;
00258          lt->thread[lt->reentrancy] = pthread_self();
00259          lt->reentrancy++;
00260       } else {
00261          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00262                         filename, lineno, func, mutex_name);
00263       }
00264       ast_reentrancy_unlock(lt);
00265       if (t->tracking) {
00266          ast_mark_lock_acquired(t);
00267       }
00268    } else if (t->tracking) {
00269 #ifdef HAVE_BKTR
00270       if (lt->reentrancy) {
00271          ast_reentrancy_lock(lt);
00272          bt = &lt->backtrace[lt->reentrancy-1];
00273          ast_reentrancy_unlock(lt);
00274       } else {
00275          bt = NULL;
00276       }
00277       ast_remove_lock_info(t, bt);
00278 #else
00279       ast_remove_lock_info(t);
00280 #endif
00281    }
00282    if (res) {
00283       __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
00284                filename, lineno, func, strerror(res));
00285       DO_THREAD_CRASH;
00286    }
00287 #endif /* DEBUG_THREADS */
00288 
00289    return res;
00290 }

int __ast_pthread_mutex_trylock ( const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 292 of file lock.c.

References __ast_pthread_mutex_init(), ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_mutex_info::mutex, pthread_mutex_t, pthread_mutex_trylock, ast_lock_track::reentrancy, ast_mutex_info::track, and ast_mutex_info::tracking.

Referenced by __ao2_trylock().

00294 {
00295    int res;
00296 
00297 #ifdef DEBUG_THREADS
00298    struct ast_lock_track *lt;
00299    int canlog = strcmp(filename, "logger.c") & t->tracking;
00300 #ifdef HAVE_BKTR
00301    struct ast_bt *bt = NULL;
00302 #endif
00303 
00304 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00305    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00306       /* Don't warn abount uninitialized mutex.
00307        * Simple try to initialize it.
00308        * May be not needed in linux system.
00309        */
00310       res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00311       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00312          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00313                 filename, lineno, func, mutex_name);
00314          return res;
00315       }
00316    }
00317 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00318 
00319    if (t->tracking && !t->track) {
00320       ast_reentrancy_init(&t->track);
00321    }
00322    lt = t->track;
00323 
00324    if (t->tracking) {
00325 #ifdef HAVE_BKTR
00326       ast_reentrancy_lock(lt);
00327       if (lt->reentrancy != AST_MAX_REENTRANCY) {
00328          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
00329          bt = &lt->backtrace[lt->reentrancy];
00330       }
00331       ast_reentrancy_unlock(lt);
00332       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
00333 #else
00334       ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
00335 #endif
00336    }
00337 #endif /* DEBUG_THREADS */
00338 
00339    res = pthread_mutex_trylock(&t->mutex);
00340 
00341 #ifdef DEBUG_THREADS
00342    if (t->tracking && !res) {
00343       ast_reentrancy_lock(lt);
00344       if (lt->reentrancy < AST_MAX_REENTRANCY) {
00345          lt->file[lt->reentrancy] = filename;
00346          lt->lineno[lt->reentrancy] = lineno;
00347          lt->func[lt->reentrancy] = func;
00348          lt->thread[lt->reentrancy] = pthread_self();
00349          lt->reentrancy++;
00350       } else {
00351          __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00352                   filename, lineno, func, mutex_name);
00353       }
00354       ast_reentrancy_unlock(lt);
00355       if (t->tracking) {
00356          ast_mark_lock_acquired(t);
00357       }
00358    } else if (t->tracking) {
00359       ast_mark_lock_failed(t);
00360    }
00361 #endif /* DEBUG_THREADS */
00362 
00363    return res;
00364 }

int __ast_pthread_mutex_unlock ( const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 366 of file lock.c.

References __ast_pthread_mutex_init(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, pthread_mutex_t, pthread_mutex_unlock, ast_lock_track::reentrancy, ROFFSET, ast_lock_track::thread, ast_mutex_info::track, and ast_mutex_info::tracking.

Referenced by __ao2_unlock().

00368 {
00369    int res;
00370 
00371 #ifdef DEBUG_THREADS
00372    struct ast_lock_track *lt;
00373    int canlog = strcmp(filename, "logger.c") & t->tracking;
00374 #ifdef HAVE_BKTR
00375    struct ast_bt *bt = NULL;
00376 #endif
00377 
00378 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00379    if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00380       __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00381                filename, lineno, func, mutex_name);
00382       res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00383       if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00384          __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00385                 filename, lineno, func, mutex_name);
00386       }
00387       return res;
00388    }
00389 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00390 
00391    if (t->tracking && !t->track) {
00392       ast_reentrancy_init(&t->track);
00393    }
00394    lt = t->track;
00395 
00396    if (t->tracking) {
00397       ast_reentrancy_lock(lt);
00398       if (lt->reentrancy && (lt->thread[ROFFSET] != 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                   lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
00403 #ifdef HAVE_BKTR
00404          __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
00405 #endif
00406          DO_THREAD_CRASH;
00407       }
00408 
00409       if (--lt->reentrancy < 0) {
00410          __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00411                   filename, lineno, func, mutex_name);
00412          lt->reentrancy = 0;
00413       }
00414 
00415       if (lt->reentrancy < AST_MAX_REENTRANCY) {
00416          lt->file[lt->reentrancy] = NULL;
00417          lt->lineno[lt->reentrancy] = 0;
00418          lt->func[lt->reentrancy] = NULL;
00419          lt->thread[lt->reentrancy] = 0;
00420       }
00421 
00422 #ifdef HAVE_BKTR
00423       if (lt->reentrancy) {
00424          bt = &lt->backtrace[lt->reentrancy - 1];
00425       }
00426 #endif
00427       ast_reentrancy_unlock(lt);
00428 
00429 #ifdef HAVE_BKTR
00430       ast_remove_lock_info(t, bt);
00431 #else
00432       ast_remove_lock_info(t);
00433 #endif
00434    }
00435 #endif /* DEBUG_THREADS */
00436 
00437    res = pthread_mutex_unlock(&t->mutex);
00438 
00439 #ifdef DEBUG_THREADS
00440    if (res) {
00441       __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
00442                filename, lineno, func, strerror(res));
00443       DO_THREAD_CRASH;
00444    }
00445 #endif /* DEBUG_THREADS */
00446 
00447    return res;
00448 }

int __ast_rwlock_destroy ( const char *  filename,
int  lineno,
const char *  func,
const char *  rwlock_name,
ast_rwlock_t t 
)

Definition at line 723 of file lock.c.

References __AST_RWLOCK_INIT_VALUE, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_lock_track::thread, ast_rwlock_info::track, and ast_rwlock_info::tracking.

00724 {
00725    int res;
00726 
00727 #ifdef DEBUG_THREADS
00728    struct ast_lock_track *lt = t->track;
00729    int canlog = strcmp(filename, "logger.c") & t->tracking;
00730 
00731 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00732    if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
00733       __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
00734                filename, lineno, func, rwlock_name);
00735       return 0;
00736    }
00737 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00738 
00739 #endif /* DEBUG_THREADS */
00740 
00741    res = pthread_rwlock_destroy(&t->lock);
00742 
00743 #ifdef DEBUG_THREADS
00744    if (res) {
00745       __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
00746             filename, lineno, func, rwlock_name, strerror(res));
00747    }
00748    if (t->tracking) {
00749       ast_reentrancy_lock(lt);
00750       lt->file[0] = filename;
00751       lt->lineno[0] = lineno;
00752       lt->func[0] = func;
00753       lt->reentrancy = 0;
00754       lt->thread[0] = 0;
00755 #ifdef HAVE_BKTR
00756       memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
00757 #endif
00758       ast_reentrancy_unlock(lt);
00759       delete_reentrancy_cs(&t->track);
00760    }
00761 #endif /* DEBUG_THREADS */
00762 
00763    return res;
00764 }

int __ast_rwlock_init ( int  tracking,
const char *  filename,
int  lineno,
const char *  func,
const char *  rwlock_name,
ast_rwlock_t t 
)

Definition at line 690 of file lock.c.

References __AST_RWLOCK_INIT_VALUE, ast_rwlock_info::lock, ast_rwlock_info::track, and ast_rwlock_info::tracking.

Referenced by __ast_rwlock_rdlock(), __ast_rwlock_timedrdlock(), __ast_rwlock_timedwrlock(), __ast_rwlock_tryrdlock(), __ast_rwlock_trywrlock(), __ast_rwlock_unlock(), and __ast_rwlock_wrlock().

00691 {
00692    int res;
00693    pthread_rwlockattr_t attr;
00694 
00695 #ifdef DEBUG_THREADS
00696 
00697 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00698    int canlog = strcmp(filename, "logger.c") & t->tracking;
00699 
00700    if (t->lock != ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
00701       __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
00702             filename, lineno, func, rwlock_name);
00703       return 0;
00704    }
00705 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00706 
00707    if ((t->tracking = tracking)) {
00708       ast_reentrancy_init(&t->track);
00709    }
00710 #endif /* DEBUG_THREADS */
00711 
00712    pthread_rwlockattr_init(&attr);
00713 
00714 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
00715    pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
00716 #endif
00717 
00718    res = pthread_rwlock_init(&t->lock, &attr);
00719    pthread_rwlockattr_destroy(&attr);
00720    return res;
00721 }

int __ast_rwlock_rdlock ( const char *  filename,
int  line,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 852 of file lock.c.

References __ast_rwlock_init(), __AST_RWLOCK_INIT_VALUE, ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_lock_track::thread, ast_rwlock_info::track, and ast_rwlock_info::tracking.

Referenced by __ast_heap_rdlock().

00853 {
00854    int res;
00855 
00856 #ifdef DEBUG_THREADS
00857    struct ast_lock_track *lt;
00858    int canlog = strcmp(filename, "logger.c") & t->tracking;
00859 #ifdef HAVE_BKTR
00860    struct ast_bt *bt = NULL;
00861 #endif
00862 
00863 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00864    if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
00865        /* Don't warn abount uninitialized lock.
00866         * Simple try to initialize it.
00867         * May be not needed in linux system.
00868         */
00869       res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
00870       if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
00871          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
00872                filename, line, func, name);
00873          return res;
00874       }
00875    }
00876 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00877 
00878    if (t->tracking && !t->track) {
00879       ast_reentrancy_init(&t->track);
00880    }
00881    lt = t->track;
00882 
00883    if (t->tracking) {
00884 #ifdef HAVE_BKTR
00885       ast_reentrancy_lock(lt);
00886       if (lt->reentrancy != AST_MAX_REENTRANCY) {
00887          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
00888          bt = &lt->backtrace[lt->reentrancy];
00889       }
00890       ast_reentrancy_unlock(lt);
00891       ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
00892 #else
00893       ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
00894 #endif
00895    }
00896 #endif /* DEBUG_THREADS */
00897 
00898 #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS)
00899    {
00900       time_t seconds = time(NULL);
00901       time_t wait_time, reported_wait = 0;
00902       do {
00903          res = pthread_rwlock_tryrdlock(&t->lock);
00904          if (res == EBUSY) {
00905             wait_time = time(NULL) - seconds;
00906             if (wait_time > reported_wait && (wait_time % 5) == 0) {
00907                __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
00908                   filename, line, func, (int)wait_time, name);
00909                if (t->tracking) {
00910                   ast_reentrancy_lock(lt);
00911 #ifdef HAVE_BKTR
00912                   __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
00913 #endif
00914                   __ast_mutex_logger("%s line %d (%s): '%s' was locked  here.\n",
00915                         lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
00916                         lt->func[lt->reentrancy-1], name);
00917 #ifdef HAVE_BKTR
00918                   __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
00919 #endif
00920                   ast_reentrancy_unlock(lt);
00921                }
00922                reported_wait = wait_time;
00923             }
00924             usleep(200);
00925          }
00926       } while (res == EBUSY);
00927    }
00928 #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
00929    res = pthread_rwlock_rdlock(&t->lock);
00930 #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
00931 
00932 #ifdef DEBUG_THREADS
00933    if (!res && t->tracking) {
00934       ast_reentrancy_lock(lt);
00935       if (lt->reentrancy < AST_MAX_REENTRANCY) {
00936          lt->file[lt->reentrancy] = filename;
00937          lt->lineno[lt->reentrancy] = line;
00938          lt->func[lt->reentrancy] = func;
00939          lt->thread[lt->reentrancy] = pthread_self();
00940          lt->reentrancy++;
00941       }
00942       ast_reentrancy_unlock(lt);
00943       if (t->tracking) {
00944          ast_mark_lock_acquired(t);
00945       }
00946    } else if (t->tracking) {
00947 #ifdef HAVE_BKTR
00948       if (lt->reentrancy) {
00949          ast_reentrancy_lock(lt);
00950          bt = &lt->backtrace[lt->reentrancy-1];
00951          ast_reentrancy_unlock(lt);
00952       } else {
00953          bt = NULL;
00954       }
00955       ast_remove_lock_info(t, bt);
00956 #else
00957       ast_remove_lock_info(t);
00958 #endif
00959    }
00960 
00961    if (res) {
00962       __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
00963             filename, line, func, strerror(res));
00964       DO_THREAD_CRASH;
00965    }
00966 #endif /* DEBUG_THREADS */
00967 
00968    return res;
00969 }

int __ast_rwlock_timedrdlock ( const char *  filename,
int  line,
const char *  func,
ast_rwlock_t t,
const char *  name,
const struct timespec *  abs_timeout 
)

Definition at line 1093 of file lock.c.

References __ast_rwlock_init(), __AST_RWLOCK_INIT_VALUE, ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_tvnow(), ast_tvsub(), ast_lock_track::backtrace, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_rwlock_info::track, and ast_rwlock_info::tracking.

01095 {
01096    int res;
01097 
01098 #ifdef DEBUG_THREADS
01099    struct ast_lock_track *lt;
01100    int canlog = strcmp(filename, "logger.c") & t->tracking;
01101 #ifdef HAVE_BKTR
01102    struct ast_bt *bt = NULL;
01103 #endif
01104 
01105 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
01106    if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01107        /* Don't warn abount uninitialized lock.
01108         * Simple try to initialize it.
01109         * May be not needed in linux system.
01110         */
01111       res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01112       if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01113          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01114                filename, line, func, name);
01115          return res;
01116       }
01117    }
01118 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
01119 
01120    if (t->tracking && !t->track) {
01121       ast_reentrancy_init(&t->track);
01122    }
01123    lt = t->track;
01124 
01125    if (t->tracking) {
01126 #ifdef HAVE_BKTR
01127       ast_reentrancy_lock(lt);
01128       if (lt->reentrancy != AST_MAX_REENTRANCY) {
01129          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
01130          bt = &lt->backtrace[lt->reentrancy];
01131       }
01132       ast_reentrancy_unlock(lt);
01133       ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
01134 #else
01135       ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
01136 #endif
01137    }
01138 #endif /* DEBUG_THREADS */
01139 
01140 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
01141    res = pthread_rwlock_timedrdlock(&t->lock, abs_timeout);
01142 #else
01143    do {
01144       struct timeval _start = ast_tvnow(), _diff;
01145       for (;;) {
01146          if (!(res = pthread_rwlock_tryrdlock(&t->lock))) {
01147             break;
01148          }
01149          _diff = ast_tvsub(ast_tvnow(), _start);
01150          if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
01151             break;
01152          }
01153          usleep(1);
01154       }
01155    } while (0);
01156 #endif
01157 
01158 #ifdef DEBUG_THREADS
01159    if (!res && t->tracking) {
01160       ast_reentrancy_lock(lt);
01161       if (lt->reentrancy < AST_MAX_REENTRANCY) {
01162          lt->file[lt->reentrancy] = filename;
01163          lt->lineno[lt->reentrancy] = line;
01164          lt->func[lt->reentrancy] = func;
01165          lt->thread[lt->reentrancy] = pthread_self();
01166          lt->reentrancy++;
01167       }
01168       ast_reentrancy_unlock(lt);
01169       if (t->tracking) {
01170          ast_mark_lock_acquired(t);
01171       }
01172    } else if (t->tracking) {
01173 #ifdef HAVE_BKTR
01174       if (lt->reentrancy) {
01175          ast_reentrancy_lock(lt);
01176          bt = &lt->backtrace[lt->reentrancy-1];
01177          ast_reentrancy_unlock(lt);
01178       } else {
01179          bt = NULL;
01180       }
01181       ast_remove_lock_info(t, bt);
01182 #else
01183       ast_remove_lock_info(t);
01184 #endif
01185    }
01186    if (res) {
01187       __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
01188             filename, line, func, strerror(res));
01189       DO_THREAD_CRASH;
01190    }
01191 #endif /* DEBUG_THREADS */
01192 
01193    return res;
01194 }

int __ast_rwlock_timedwrlock ( const char *  filename,
int  line,
const char *  func,
ast_rwlock_t t,
const char *  name,
const struct timespec *  abs_timeout 
)

Definition at line 1196 of file lock.c.

References __ast_rwlock_init(), __AST_RWLOCK_INIT_VALUE, ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_tvnow(), ast_tvsub(), ast_lock_track::backtrace, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_rwlock_info::track, and ast_rwlock_info::tracking.

01198 {
01199    int res;
01200 
01201 #ifdef DEBUG_THREADS
01202    struct ast_lock_track *lt;
01203    int canlog = strcmp(filename, "logger.c") & t->tracking;
01204 #ifdef HAVE_BKTR
01205    struct ast_bt *bt = NULL;
01206 #endif
01207 
01208 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
01209    if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01210        /* Don't warn abount uninitialized lock.
01211         * Simple try to initialize it.
01212         * May be not needed in linux system.
01213         */
01214       res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01215       if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01216          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01217                filename, line, func, name);
01218          return res;
01219       }
01220    }
01221 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
01222 
01223    if (t->tracking && !t->track) {
01224       ast_reentrancy_init(&t->track);
01225    }
01226    lt = t->track;
01227 
01228    if (t->tracking) {
01229 #ifdef HAVE_BKTR
01230       ast_reentrancy_lock(lt);
01231       if (lt->reentrancy != AST_MAX_REENTRANCY) {
01232          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
01233          bt = &lt->backtrace[lt->reentrancy];
01234       }
01235       ast_reentrancy_unlock(lt);
01236       ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
01237 #else
01238       ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
01239 #endif
01240    }
01241 #endif /* DEBUG_THREADS */
01242 
01243 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
01244    res = pthread_rwlock_timedwrlock(&t->lock, abs_timeout);
01245 #else
01246    do {
01247       struct timeval _start = ast_tvnow(), _diff;
01248       for (;;) {
01249          if (!(res = pthread_rwlock_trywrlock(&t->lock))) {
01250             break;
01251          }
01252          _diff = ast_tvsub(ast_tvnow(), _start);
01253          if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) {
01254             break;
01255          }
01256          usleep(1);
01257       }
01258    } while (0);
01259 #endif
01260 
01261 #ifdef DEBUG_THREADS
01262    if (!res && t->tracking) {
01263       ast_reentrancy_lock(lt);
01264       if (lt->reentrancy < AST_MAX_REENTRANCY) {
01265          lt->file[lt->reentrancy] = filename;
01266          lt->lineno[lt->reentrancy] = line;
01267          lt->func[lt->reentrancy] = func;
01268          lt->thread[lt->reentrancy] = pthread_self();
01269          lt->reentrancy++;
01270       }
01271       ast_reentrancy_unlock(lt);
01272       if (t->tracking) {
01273          ast_mark_lock_acquired(t);
01274       }
01275    } else if (t->tracking) {
01276 #ifdef HAVE_BKTR
01277       if (lt->reentrancy) {
01278          ast_reentrancy_lock(lt);
01279          bt = &lt->backtrace[lt->reentrancy-1];
01280          ast_reentrancy_unlock(lt);
01281       } else {
01282          bt = NULL;
01283       }
01284       if (t->tracking) {
01285          ast_remove_lock_info(t, bt);
01286       }
01287 #else
01288       if (t->tracking) {
01289          ast_remove_lock_info(t);
01290       }
01291 #endif
01292    }
01293    if (res) {
01294       __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
01295             filename, line, func, strerror(res));
01296       DO_THREAD_CRASH;
01297    }
01298 #endif /* DEBUG_THREADS */
01299 
01300    return res;
01301 }

int __ast_rwlock_tryrdlock ( const char *  filename,
int  line,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 1303 of file lock.c.

References __ast_rwlock_init(), __AST_RWLOCK_INIT_VALUE, ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_lock_track::thread, ast_rwlock_info::track, and ast_rwlock_info::tracking.

01304 {
01305    int res;
01306 
01307 #ifdef DEBUG_THREADS
01308    struct ast_lock_track *lt;
01309 #ifdef HAVE_BKTR
01310    struct ast_bt *bt = NULL;
01311 #endif
01312 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
01313    int canlog = strcmp(filename, "logger.c") & t->tracking;
01314 
01315    if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01316        /* Don't warn abount uninitialized lock.
01317         * Simple try to initialize it.
01318         * May be not needed in linux system.
01319         */
01320       res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01321       if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01322          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01323                filename, line, func, name);
01324          return res;
01325       }
01326    }
01327 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
01328 
01329    if (t->tracking && !t->track) {
01330       ast_reentrancy_init(&t->track);
01331    }
01332    lt = t->track;
01333 
01334    if (t->tracking) {
01335 #ifdef HAVE_BKTR
01336       ast_reentrancy_lock(lt);
01337       if (lt->reentrancy != AST_MAX_REENTRANCY) {
01338          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
01339          bt = &lt->backtrace[lt->reentrancy];
01340       }
01341       ast_reentrancy_unlock(lt);
01342       ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
01343 #else
01344       ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
01345 #endif
01346    }
01347 #endif /* DEBUG_THREADS */
01348 
01349    res = pthread_rwlock_tryrdlock(&t->lock);
01350 
01351 #ifdef DEBUG_THREADS
01352    if (!res && t->tracking) {
01353       ast_reentrancy_lock(lt);
01354       if (lt->reentrancy < AST_MAX_REENTRANCY) {
01355          lt->file[lt->reentrancy] = filename;
01356          lt->lineno[lt->reentrancy] = line;
01357          lt->func[lt->reentrancy] = func;
01358          lt->thread[lt->reentrancy] = pthread_self();
01359          lt->reentrancy++;
01360       }
01361       ast_reentrancy_unlock(lt);
01362       if (t->tracking) {
01363          ast_mark_lock_acquired(t);
01364       }
01365    } else if (t->tracking) {
01366       ast_mark_lock_failed(t);
01367    }
01368 #endif /* DEBUG_THREADS */
01369 
01370    return res;
01371 }

int __ast_rwlock_trywrlock ( const char *  filename,
int  line,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 1373 of file lock.c.

References __ast_rwlock_init(), __AST_RWLOCK_INIT_VALUE, ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_lock_track::thread, ast_rwlock_info::track, and ast_rwlock_info::tracking.

01374 {
01375    int res;
01376 
01377 #ifdef DEBUG_THREADS
01378    struct ast_lock_track *lt;
01379 #ifdef HAVE_BKTR
01380    struct ast_bt *bt = NULL;
01381 #endif
01382 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
01383    int canlog = strcmp(filename, "logger.c") & t->tracking;
01384 
01385    if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01386        /* Don't warn abount uninitialized lock.
01387         * Simple try to initialize it.
01388         * May be not needed in linux system.
01389         */
01390       res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01391       if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01392          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01393                filename, line, func, name);
01394          return res;
01395       }
01396    }
01397 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
01398 
01399    if (t->tracking && !t->track) {
01400       ast_reentrancy_init(&t->track);
01401    }
01402    lt = t->track;
01403 
01404    if (t->tracking) {
01405 #ifdef HAVE_BKTR
01406       ast_reentrancy_lock(lt);
01407       if (lt->reentrancy != AST_MAX_REENTRANCY) {
01408          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
01409          bt = &lt->backtrace[lt->reentrancy];
01410       }
01411       ast_reentrancy_unlock(lt);
01412       ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
01413 #else
01414       ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
01415 #endif
01416    }
01417 #endif /* DEBUG_THREADS */
01418 
01419    res = pthread_rwlock_trywrlock(&t->lock);
01420 
01421 #ifdef DEBUG_THREADS
01422    if (!res && t->tracking) {
01423       ast_reentrancy_lock(lt);
01424       if (lt->reentrancy < AST_MAX_REENTRANCY) {
01425          lt->file[lt->reentrancy] = filename;
01426          lt->lineno[lt->reentrancy] = line;
01427          lt->func[lt->reentrancy] = func;
01428          lt->thread[lt->reentrancy] = pthread_self();
01429          lt->reentrancy++;
01430       }
01431       ast_reentrancy_unlock(lt);
01432       ast_mark_lock_acquired(t);
01433    } else if (t->tracking) {
01434       ast_mark_lock_failed(t);
01435    }
01436 #endif /* DEBUG_THREADS */
01437 
01438    return res;
01439 }

int __ast_rwlock_unlock ( const char *  filename,
int  line,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 766 of file lock.c.

References __ast_rwlock_init(), __AST_RWLOCK_INIT_VALUE, AST_PTHREADT_NULL, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_lock_track::thread, ast_rwlock_info::track, and ast_rwlock_info::tracking.

Referenced by __ast_heap_unlock().

00767 {
00768    int res;
00769 
00770 #ifdef DEBUG_THREADS
00771    struct ast_lock_track *lt;
00772    int canlog = strcmp(filename, "logger.c") & t->tracking;
00773 #ifdef HAVE_BKTR
00774    struct ast_bt *bt = NULL;
00775 #endif
00776    int lock_found = 0;
00777 
00778 
00779 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00780    if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
00781       __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
00782                filename, line, func, name);
00783       res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
00784       if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
00785          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
00786                filename, line, func, name);
00787       }
00788       return res;
00789    }
00790 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00791 
00792    if (t->tracking && !t->track) {
00793       ast_reentrancy_init(&t->track);
00794    }
00795    lt = t->track;
00796 
00797    if (t->tracking) {
00798       ast_reentrancy_lock(lt);
00799       if (lt->reentrancy) {
00800          int i;
00801          pthread_t self = pthread_self();
00802          for (i = lt->reentrancy - 1; i >= 0; --i) {
00803             if (lt->thread[i] == self) {
00804                lock_found = 1;
00805                if (i != lt->reentrancy - 1) {
00806                   lt->file[i] = lt->file[lt->reentrancy - 1];
00807                   lt->lineno[i] = lt->lineno[lt->reentrancy - 1];
00808                   lt->func[i] = lt->func[lt->reentrancy - 1];
00809                   lt->thread[i] = lt->thread[lt->reentrancy - 1];
00810                }
00811 #ifdef HAVE_BKTR
00812                bt = &lt->backtrace[i];
00813 #endif
00814                lt->file[lt->reentrancy - 1] = NULL;
00815                lt->lineno[lt->reentrancy - 1] = 0;
00816                lt->func[lt->reentrancy - 1] = NULL;
00817                lt->thread[lt->reentrancy - 1] = AST_PTHREADT_NULL;
00818                break;
00819             }
00820          }
00821       }
00822 
00823       if (lock_found && --lt->reentrancy < 0) {
00824          __ast_mutex_logger("%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
00825                filename, line, func, name);
00826          lt->reentrancy = 0;
00827       }
00828 
00829       ast_reentrancy_unlock(lt);
00830 
00831 #ifdef HAVE_BKTR
00832       ast_remove_lock_info(t, bt);
00833 #else
00834       ast_remove_lock_info(t);
00835 #endif
00836    }
00837 #endif /* DEBUG_THREADS */
00838 
00839    res = pthread_rwlock_unlock(&t->lock);
00840 
00841 #ifdef DEBUG_THREADS
00842    if (res) {
00843       __ast_mutex_logger("%s line %d (%s): Error releasing rwlock: %s\n",
00844             filename, line, func, strerror(res));
00845       DO_THREAD_CRASH;
00846    }
00847 #endif /* DEBUG_THREADS */
00848 
00849    return res;
00850 }

int __ast_rwlock_wrlock ( const char *  filename,
int  line,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 971 of file lock.c.

References __ast_rwlock_init(), __AST_RWLOCK_INIT_VALUE, ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_lock_track::thread, ast_rwlock_info::track, and ast_rwlock_info::tracking.

Referenced by __ast_heap_wrlock().

00972 {
00973    int res;
00974 
00975 #ifdef DEBUG_THREADS
00976    struct ast_lock_track *lt;
00977    int canlog = strcmp(filename, "logger.c") & t->tracking;
00978 #ifdef HAVE_BKTR
00979    struct ast_bt *bt = NULL;
00980 #endif
00981 
00982 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
00983    if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
00984        /* Don't warn abount uninitialized lock.
00985         * Simple try to initialize it.
00986         * May be not needed in linux system.
00987         */
00988       res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
00989       if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
00990          __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
00991                filename, line, func, name);
00992          return res;
00993       }
00994    }
00995 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
00996 
00997    if (t->tracking && !t->track) {
00998       ast_reentrancy_init(&t->track);
00999    }
01000    lt = t->track;
01001 
01002    if (t->tracking) {
01003 #ifdef HAVE_BKTR
01004       ast_reentrancy_lock(lt);
01005       if (lt->reentrancy != AST_MAX_REENTRANCY) {
01006          ast_bt_get_addresses(&lt->backtrace[lt->reentrancy]);
01007          bt = &lt->backtrace[lt->reentrancy];
01008       }
01009       ast_reentrancy_unlock(lt);
01010       ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
01011 #else
01012       ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
01013 #endif
01014    }
01015 #endif /* DEBUG_THREADS */
01016 
01017 #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS)
01018    {
01019       time_t seconds = time(NULL);
01020       time_t wait_time, reported_wait = 0;
01021       do {
01022          res = pthread_rwlock_trywrlock(&t->lock);
01023          if (res == EBUSY) {
01024             wait_time = time(NULL) - seconds;
01025             if (wait_time > reported_wait && (wait_time % 5) == 0) {
01026                __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
01027                   filename, line, func, (int)wait_time, name);
01028                if (t->tracking) {
01029                   ast_reentrancy_lock(lt);
01030 #ifdef HAVE_BKTR
01031                   __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
01032 #endif
01033                   __ast_mutex_logger("%s line %d (%s): '%s' was locked  here.\n",
01034                         lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
01035                         lt->func[lt->reentrancy-1], name);
01036 #ifdef HAVE_BKTR
01037                   __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
01038 #endif
01039                   ast_reentrancy_unlock(lt);
01040                }
01041                reported_wait = wait_time;
01042             }
01043             usleep(200);
01044          }
01045       } while (res == EBUSY);
01046    }
01047 #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
01048    res = pthread_rwlock_wrlock(&t->lock);
01049 #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
01050 
01051 #ifdef DEBUG_THREADS
01052    if (!res && t->tracking) {
01053       ast_reentrancy_lock(lt);
01054       if (lt->reentrancy < AST_MAX_REENTRANCY) {
01055          lt->file[lt->reentrancy] = filename;
01056          lt->lineno[lt->reentrancy] = line;
01057          lt->func[lt->reentrancy] = func;
01058          lt->thread[lt->reentrancy] = pthread_self();
01059          lt->reentrancy++;
01060       }
01061       ast_reentrancy_unlock(lt);
01062       if (t->tracking) {
01063          ast_mark_lock_acquired(t);
01064       }
01065    } else if (t->tracking) {
01066 #ifdef HAVE_BKTR
01067       if (lt->reentrancy) {
01068          ast_reentrancy_lock(lt);
01069          bt = &lt->backtrace[lt->reentrancy-1];
01070          ast_reentrancy_unlock(lt);
01071       } else {
01072          bt = NULL;
01073       }
01074       if (t->tracking) {
01075          ast_remove_lock_info(t, bt);
01076       }
01077 #else
01078       if (t->tracking) {
01079          ast_remove_lock_info(t);
01080       }
01081 #endif
01082    }
01083    if (res) {
01084       __ast_mutex_logger("%s line %d (%s): Error obtaining write lock: %s\n",
01085             filename, line, func, strerror(res));
01086       DO_THREAD_CRASH;
01087    }
01088 #endif /* DEBUG_THREADS */
01089 
01090    return res;
01091 }


Generated on Mon Oct 8 12:39:24 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7