#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) |
Definition in file lock.c.
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(<->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 = <->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(<->backtrace[lt->reentrancy]); 00670 bt = <->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(<->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 = <->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(<->backtrace[lt->reentrancy]); 00563 bt = <->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(<->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(<->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(<->backtrace[lt->reentrancy]); 00197 bt = <->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(<->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(<->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 = <->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(<->backtrace[lt->reentrancy]); 00329 bt = <->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(<->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 = <->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(<->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(<->backtrace[lt->reentrancy]); 00888 bt = <->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(<->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(<->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 = <->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(<->backtrace[lt->reentrancy]); 01130 bt = <->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 = <->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(<->backtrace[lt->reentrancy]); 01233 bt = <->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 = <->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(<->backtrace[lt->reentrancy]); 01339 bt = <->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(<->backtrace[lt->reentrancy]); 01409 bt = <->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 = <->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(<->backtrace[lt->reentrancy]); 01007 bt = <->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(<->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(<->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 = <->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 }