#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 (ast_rwlock_t *t, const char *name, const char *filename, int line, const char *func) |
int | __ast_rwlock_timedrdlock (ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout, const char *filename, int line, const char *func) |
int | __ast_rwlock_timedwrlock (ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout, const char *filename, int line, const char *func) |
int | __ast_rwlock_tryrdlock (ast_rwlock_t *t, const char *name, const char *filename, int line, const char *func) |
int | __ast_rwlock_trywrlock (ast_rwlock_t *t, const char *name, const char *filename, int line, const char *func) |
int | __ast_rwlock_unlock (ast_rwlock_t *t, const char *name, const char *filename, int line, const char *func) |
int | __ast_rwlock_wrlock (ast_rwlock_t *t, const char *name, const char *filename, int line, const char *func) |
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 437 of file lock.c.
References pthread_cond_broadcast.
00439 { 00440 return pthread_cond_broadcast(cond); 00441 }
int __ast_cond_destroy | ( | const char * | filename, | |
int | lineno, | |||
const char * | func, | |||
const char * | cond_name, | |||
ast_cond_t * | cond | |||
) |
Definition at line 443 of file lock.c.
References pthread_cond_destroy.
00445 { 00446 return pthread_cond_destroy(cond); 00447 }
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 425 of file lock.c.
References pthread_cond_init.
00427 { 00428 return pthread_cond_init(cond, cond_attr); 00429 }
int __ast_cond_signal | ( | const char * | filename, | |
int | lineno, | |||
const char * | func, | |||
const char * | cond_name, | |||
ast_cond_t * | cond | |||
) |
Definition at line 431 of file lock.c.
References pthread_cond_signal.
00433 { 00434 return pthread_cond_signal(cond); 00435 }
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 554 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.
00557 { 00558 int res; 00559 00560 #ifdef DEBUG_THREADS 00561 struct ast_lock_track *lt = &t->track; 00562 int canlog = strcmp(filename, "logger.c") & t->tracking; 00563 #ifdef HAVE_BKTR 00564 struct ast_bt *bt = NULL; 00565 #endif 00566 00567 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00568 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00569 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n", 00570 filename, lineno, func, mutex_name); 00571 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t); 00572 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00573 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n", 00574 filename, lineno, func, mutex_name); 00575 } 00576 return res; 00577 } 00578 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00579 00580 ast_reentrancy_lock(lt); 00581 if (lt->reentrancy && (lt->thread[ROFFSET] != pthread_self())) { 00582 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n", 00583 filename, lineno, func, mutex_name); 00584 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n", 00585 lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name); 00586 #ifdef HAVE_BKTR 00587 __dump_backtrace(<->backtrace[ROFFSET], canlog); 00588 #endif 00589 DO_THREAD_CRASH; 00590 } 00591 00592 if (--lt->reentrancy < 0) { 00593 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n", 00594 filename, lineno, func, mutex_name); 00595 lt->reentrancy = 0; 00596 } 00597 00598 if (lt->reentrancy < AST_MAX_REENTRANCY) { 00599 lt->file[lt->reentrancy] = NULL; 00600 lt->lineno[lt->reentrancy] = 0; 00601 lt->func[lt->reentrancy] = NULL; 00602 lt->thread[lt->reentrancy] = 0; 00603 } 00604 #ifdef HAVE_BKTR 00605 if (lt->reentrancy) { 00606 bt = <->backtrace[lt->reentrancy - 1]; 00607 } 00608 #endif 00609 ast_reentrancy_unlock(lt); 00610 00611 if (t->tracking) { 00612 #ifdef HAVE_BKTR 00613 ast_remove_lock_info(t, bt); 00614 #else 00615 ast_remove_lock_info(t); 00616 #endif 00617 } 00618 #endif /* DEBUG_THREADS */ 00619 00620 res = pthread_cond_timedwait(cond, &t->mutex, abstime); 00621 00622 #ifdef DEBUG_THREADS 00623 if (res && (res != ETIMEDOUT)) { 00624 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 00625 filename, lineno, func, strerror(res)); 00626 DO_THREAD_CRASH; 00627 } else { 00628 ast_reentrancy_lock(lt); 00629 if (lt->reentrancy < AST_MAX_REENTRANCY) { 00630 lt->file[lt->reentrancy] = filename; 00631 lt->lineno[lt->reentrancy] = lineno; 00632 lt->func[lt->reentrancy] = func; 00633 lt->thread[lt->reentrancy] = pthread_self(); 00634 #ifdef HAVE_BKTR 00635 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 00636 bt = <->backtrace[lt->reentrancy]; 00637 #endif 00638 lt->reentrancy++; 00639 } else { 00640 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n", 00641 filename, lineno, func, mutex_name); 00642 } 00643 ast_reentrancy_unlock(lt); 00644 00645 if (t->tracking) { 00646 #ifdef HAVE_BKTR 00647 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt); 00648 #else 00649 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t); 00650 #endif 00651 } 00652 } 00653 #endif /* DEBUG_THREADS */ 00654 00655 return res; 00656 }
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 449 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.
00452 { 00453 int res; 00454 00455 #ifdef DEBUG_THREADS 00456 struct ast_lock_track *lt= &t->track; 00457 int canlog = strcmp(filename, "logger.c") & t->tracking; 00458 #ifdef HAVE_BKTR 00459 struct ast_bt *bt = NULL; 00460 #endif 00461 00462 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00463 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00464 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n", 00465 filename, lineno, func, mutex_name); 00466 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t); 00467 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00468 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n", 00469 filename, lineno, func, mutex_name); 00470 } 00471 return res; 00472 } 00473 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00474 00475 ast_reentrancy_lock(lt); 00476 if (lt->reentrancy && (lt->thread[ROFFSET] != pthread_self())) { 00477 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n", 00478 filename, lineno, func, mutex_name); 00479 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n", 00480 lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name); 00481 #ifdef HAVE_BKTR 00482 __dump_backtrace(<->backtrace[ROFFSET], canlog); 00483 #endif 00484 DO_THREAD_CRASH; 00485 } 00486 00487 if (--lt->reentrancy < 0) { 00488 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n", 00489 filename, lineno, func, mutex_name); 00490 lt->reentrancy = 0; 00491 } 00492 00493 if (lt->reentrancy < AST_MAX_REENTRANCY) { 00494 lt->file[lt->reentrancy] = NULL; 00495 lt->lineno[lt->reentrancy] = 0; 00496 lt->func[lt->reentrancy] = NULL; 00497 lt->thread[lt->reentrancy] = 0; 00498 } 00499 00500 #ifdef HAVE_BKTR 00501 if (lt->reentrancy) { 00502 bt = <->backtrace[lt->reentrancy - 1]; 00503 } 00504 #endif 00505 ast_reentrancy_unlock(lt); 00506 00507 if (t->tracking) { 00508 #ifdef HAVE_BKTR 00509 ast_remove_lock_info(t, bt); 00510 #else 00511 ast_remove_lock_info(t); 00512 #endif 00513 } 00514 #endif /* DEBUG_THREADS */ 00515 00516 res = pthread_cond_wait(cond, &t->mutex); 00517 00518 #ifdef DEBUG_THREADS 00519 if (res) { 00520 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n", 00521 filename, lineno, func, strerror(res)); 00522 DO_THREAD_CRASH; 00523 } else { 00524 ast_reentrancy_lock(lt); 00525 if (lt->reentrancy < AST_MAX_REENTRANCY) { 00526 lt->file[lt->reentrancy] = filename; 00527 lt->lineno[lt->reentrancy] = lineno; 00528 lt->func[lt->reentrancy] = func; 00529 lt->thread[lt->reentrancy] = pthread_self(); 00530 #ifdef HAVE_BKTR 00531 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 00532 bt = <->backtrace[lt->reentrancy]; 00533 #endif 00534 lt->reentrancy++; 00535 } else { 00536 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n", 00537 filename, lineno, func, mutex_name); 00538 } 00539 ast_reentrancy_unlock(lt); 00540 00541 if (t->tracking) { 00542 #ifdef HAVE_BKTR 00543 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt); 00544 #else 00545 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t); 00546 #endif 00547 } 00548 } 00549 #endif /* DEBUG_THREADS */ 00550 00551 return res; 00552 }
int __ast_pthread_mutex_destroy | ( | const char * | filename, | |
int | lineno, | |||
const char * | func, | |||
const char * | mutex_name, | |||
ast_mutex_t * | t | |||
) |
Definition at line 76 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.
00078 { 00079 int res; 00080 00081 #ifdef DEBUG_THREADS 00082 struct ast_lock_track *lt; 00083 int canlog = strcmp(filename, "logger.c") & t->tracking; 00084 00085 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00086 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00087 /* Don't try to uninitialize non initialized mutex 00088 * This may no effect on linux 00089 * And always ganerate core on *BSD with 00090 * linked libpthread 00091 * This not error condition if the mutex created on the fly. 00092 */ 00093 __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n", 00094 filename, lineno, func, mutex_name); 00095 return 0; 00096 } 00097 #endif 00098 00099 lt = &t->track; 00100 00101 res = pthread_mutex_trylock(&t->mutex); 00102 switch (res) { 00103 case 0: 00104 pthread_mutex_unlock(&t->mutex); 00105 break; 00106 case EINVAL: 00107 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n", 00108 filename, lineno, func, mutex_name); 00109 break; 00110 case EBUSY: 00111 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n", 00112 filename, lineno, func, mutex_name); 00113 ast_reentrancy_lock(lt); 00114 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n", 00115 lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name); 00116 #ifdef HAVE_BKTR 00117 __dump_backtrace(<->backtrace[ROFFSET], canlog); 00118 #endif 00119 ast_reentrancy_unlock(lt); 00120 break; 00121 } 00122 #endif /* DEBUG_THREADS */ 00123 00124 res = pthread_mutex_destroy(&t->mutex); 00125 00126 #ifdef DEBUG_THREADS 00127 if (res) { 00128 __ast_mutex_logger("%s line %d (%s): Error destroying mutex %s: %s\n", 00129 filename, lineno, func, mutex_name, strerror(res)); 00130 } 00131 ast_reentrancy_lock(lt); 00132 lt->file[0] = filename; 00133 lt->lineno[0] = lineno; 00134 lt->func[0] = func; 00135 lt->reentrancy = 0; 00136 lt->thread[0] = 0; 00137 #ifdef HAVE_BKTR 00138 memset(<->backtrace[0], 0, sizeof(lt->backtrace[0])); 00139 #endif 00140 ast_reentrancy_unlock(lt); 00141 delete_reentrancy_cs(lt); 00142 #endif /* DEBUG_THREADS */ 00143 00144 return res; 00145 }
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 44 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().
00046 { 00047 int res; 00048 pthread_mutexattr_t attr; 00049 00050 #ifdef DEBUG_THREADS 00051 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00052 if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00053 /* 00054 int canlog = strcmp(filename, "logger.c") & track; 00055 __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n", 00056 filename, lineno, func, mutex_name); 00057 DO_THREAD_CRASH; 00058 */ 00059 return 0; 00060 } 00061 00062 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00063 00064 ast_reentrancy_init(&t->track); 00065 t->tracking = tracking; 00066 #endif /* DEBUG_THREADS */ 00067 00068 pthread_mutexattr_init(&attr); 00069 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND); 00070 00071 res = pthread_mutex_init(&t->mutex, &attr); 00072 pthread_mutexattr_destroy(&attr); 00073 return res; 00074 }
int __ast_pthread_mutex_lock | ( | const char * | filename, | |
int | lineno, | |||
const char * | func, | |||
const char * | mutex_name, | |||
ast_mutex_t * | t | |||
) |
Definition at line 147 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().
00149 { 00150 int res; 00151 00152 #ifdef DEBUG_THREADS 00153 struct ast_lock_track *lt = &t->track; 00154 int canlog = strcmp(filename, "logger.c") & t->tracking; 00155 #ifdef HAVE_BKTR 00156 struct ast_bt *bt = NULL; 00157 #endif 00158 00159 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00160 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00161 /* Don't warn abount uninitialized mutex. 00162 * Simple try to initialize it. 00163 * May be not needed in linux system. 00164 */ 00165 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t); 00166 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00167 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n", 00168 filename, lineno, func, mutex_name); 00169 return res; 00170 } 00171 } 00172 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00173 00174 if (t->tracking) { 00175 #ifdef HAVE_BKTR 00176 ast_reentrancy_lock(lt); 00177 if (lt->reentrancy != AST_MAX_REENTRANCY) { 00178 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 00179 bt = <->backtrace[lt->reentrancy]; 00180 } 00181 ast_reentrancy_unlock(lt); 00182 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt); 00183 #else 00184 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t); 00185 #endif 00186 } 00187 #endif /* DEBUG_THREADS */ 00188 00189 #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS) 00190 { 00191 time_t seconds = time(NULL); 00192 time_t wait_time, reported_wait = 0; 00193 do { 00194 #ifdef HAVE_MTX_PROFILE 00195 ast_mark(mtx_prof, 1); 00196 #endif 00197 res = pthread_mutex_trylock(&t->mutex); 00198 #ifdef HAVE_MTX_PROFILE 00199 ast_mark(mtx_prof, 0); 00200 #endif 00201 if (res == EBUSY) { 00202 wait_time = time(NULL) - seconds; 00203 if (wait_time > reported_wait && (wait_time % 5) == 0) { 00204 __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n", 00205 filename, lineno, func, (int) wait_time, mutex_name); 00206 ast_reentrancy_lock(lt); 00207 #ifdef HAVE_BKTR 00208 __dump_backtrace(<->backtrace[lt->reentrancy], canlog); 00209 #endif 00210 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n", 00211 lt->file[ROFFSET], lt->lineno[ROFFSET], 00212 lt->func[ROFFSET], mutex_name); 00213 #ifdef HAVE_BKTR 00214 __dump_backtrace(<->backtrace[ROFFSET], canlog); 00215 #endif 00216 ast_reentrancy_unlock(lt); 00217 reported_wait = wait_time; 00218 } 00219 usleep(200); 00220 } 00221 } while (res == EBUSY); 00222 } 00223 #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */ 00224 #ifdef HAVE_MTX_PROFILE 00225 ast_mark(mtx_prof, 1); 00226 res = pthread_mutex_trylock(&t->mutex); 00227 ast_mark(mtx_prof, 0); 00228 if (res) 00229 #endif 00230 res = pthread_mutex_lock(&t->mutex); 00231 #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */ 00232 00233 #ifdef DEBUG_THREADS 00234 if (!res) { 00235 ast_reentrancy_lock(lt); 00236 if (lt->reentrancy < AST_MAX_REENTRANCY) { 00237 lt->file[lt->reentrancy] = filename; 00238 lt->lineno[lt->reentrancy] = lineno; 00239 lt->func[lt->reentrancy] = func; 00240 lt->thread[lt->reentrancy] = pthread_self(); 00241 lt->reentrancy++; 00242 } else { 00243 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n", 00244 filename, lineno, func, mutex_name); 00245 } 00246 ast_reentrancy_unlock(lt); 00247 if (t->tracking) { 00248 ast_mark_lock_acquired(t); 00249 } 00250 } else { 00251 #ifdef HAVE_BKTR 00252 if (lt->reentrancy) { 00253 ast_reentrancy_lock(lt); 00254 bt = <->backtrace[lt->reentrancy-1]; 00255 ast_reentrancy_unlock(lt); 00256 } else { 00257 bt = NULL; 00258 } 00259 if (t->tracking) { 00260 ast_remove_lock_info(t, bt); 00261 } 00262 #else 00263 if (t->tracking) { 00264 ast_remove_lock_info(t); 00265 } 00266 #endif 00267 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n", 00268 filename, lineno, func, strerror(res)); 00269 DO_THREAD_CRASH; 00270 } 00271 #endif /* DEBUG_THREADS */ 00272 00273 return res; 00274 }
int __ast_pthread_mutex_trylock | ( | const char * | filename, | |
int | lineno, | |||
const char * | func, | |||
const char * | mutex_name, | |||
ast_mutex_t * | t | |||
) |
Definition at line 276 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().
00278 { 00279 int res; 00280 00281 #ifdef DEBUG_THREADS 00282 struct ast_lock_track *lt= &t->track; 00283 int canlog = strcmp(filename, "logger.c") & t->tracking; 00284 #ifdef HAVE_BKTR 00285 struct ast_bt *bt = NULL; 00286 #endif 00287 00288 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00289 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00290 /* Don't warn abount uninitialized mutex. 00291 * Simple try to initialize it. 00292 * May be not needed in linux system. 00293 */ 00294 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t); 00295 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00296 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n", 00297 filename, lineno, func, mutex_name); 00298 return res; 00299 } 00300 } 00301 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00302 00303 if (t->tracking) { 00304 #ifdef HAVE_BKTR 00305 ast_reentrancy_lock(lt); 00306 if (lt->reentrancy != AST_MAX_REENTRANCY) { 00307 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 00308 bt = <->backtrace[lt->reentrancy]; 00309 } 00310 ast_reentrancy_unlock(lt); 00311 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt); 00312 #else 00313 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t); 00314 #endif 00315 } 00316 #endif /* DEBUG_THREADS */ 00317 00318 res = pthread_mutex_trylock(&t->mutex); 00319 00320 #ifdef DEBUG_THREADS 00321 if (!res) { 00322 ast_reentrancy_lock(lt); 00323 if (lt->reentrancy < AST_MAX_REENTRANCY) { 00324 lt->file[lt->reentrancy] = filename; 00325 lt->lineno[lt->reentrancy] = lineno; 00326 lt->func[lt->reentrancy] = func; 00327 lt->thread[lt->reentrancy] = pthread_self(); 00328 lt->reentrancy++; 00329 } else { 00330 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n", 00331 filename, lineno, func, mutex_name); 00332 } 00333 ast_reentrancy_unlock(lt); 00334 if (t->tracking) { 00335 ast_mark_lock_acquired(t); 00336 } 00337 } else if (t->tracking) { 00338 ast_mark_lock_failed(t); 00339 } 00340 #endif /* DEBUG_THREADS */ 00341 00342 return res; 00343 }
int __ast_pthread_mutex_unlock | ( | const char * | filename, | |
int | lineno, | |||
const char * | func, | |||
const char * | mutex_name, | |||
ast_mutex_t * | t | |||
) |
Definition at line 345 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().
00347 { 00348 int res; 00349 00350 #ifdef DEBUG_THREADS 00351 struct ast_lock_track *lt = &t->track; 00352 int canlog = strcmp(filename, "logger.c") & t->tracking; 00353 #ifdef HAVE_BKTR 00354 struct ast_bt *bt = NULL; 00355 #endif 00356 00357 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00358 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00359 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n", 00360 filename, lineno, func, mutex_name); 00361 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t); 00362 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) { 00363 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n", 00364 filename, lineno, func, mutex_name); 00365 } 00366 return res; 00367 } 00368 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00369 00370 ast_reentrancy_lock(lt); 00371 if (lt->reentrancy && (lt->thread[ROFFSET] != pthread_self())) { 00372 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n", 00373 filename, lineno, func, mutex_name); 00374 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n", 00375 lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name); 00376 #ifdef HAVE_BKTR 00377 __dump_backtrace(<->backtrace[ROFFSET], canlog); 00378 #endif 00379 DO_THREAD_CRASH; 00380 } 00381 00382 if (--lt->reentrancy < 0) { 00383 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n", 00384 filename, lineno, func, mutex_name); 00385 lt->reentrancy = 0; 00386 } 00387 00388 if (lt->reentrancy < AST_MAX_REENTRANCY) { 00389 lt->file[lt->reentrancy] = NULL; 00390 lt->lineno[lt->reentrancy] = 0; 00391 lt->func[lt->reentrancy] = NULL; 00392 lt->thread[lt->reentrancy] = 0; 00393 } 00394 00395 #ifdef HAVE_BKTR 00396 if (lt->reentrancy) { 00397 bt = <->backtrace[lt->reentrancy - 1]; 00398 } 00399 #endif 00400 ast_reentrancy_unlock(lt); 00401 00402 if (t->tracking) { 00403 #ifdef HAVE_BKTR 00404 ast_remove_lock_info(t, bt); 00405 #else 00406 ast_remove_lock_info(t); 00407 #endif 00408 } 00409 #endif /* DEBUG_THREADS */ 00410 00411 res = pthread_mutex_unlock(&t->mutex); 00412 00413 #ifdef DEBUG_THREADS 00414 if (res) { 00415 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n", 00416 filename, lineno, func, strerror(res)); 00417 DO_THREAD_CRASH; 00418 } 00419 #endif /* DEBUG_THREADS */ 00420 00421 return res; 00422 }
int __ast_rwlock_destroy | ( | const char * | filename, | |
int | lineno, | |||
const char * | func, | |||
const char * | rwlock_name, | |||
ast_rwlock_t * | t | |||
) |
Definition at line 691 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.
00692 { 00693 int res; 00694 00695 #ifdef DEBUG_THREADS 00696 struct ast_lock_track *lt = &t->track; 00697 int canlog = strcmp(filename, "logger.c") & t->tracking; 00698 00699 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00700 if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 00701 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n", 00702 filename, lineno, func, rwlock_name); 00703 return 0; 00704 } 00705 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00706 00707 #endif /* DEBUG_THREADS */ 00708 00709 res = pthread_rwlock_destroy(&t->lock); 00710 00711 #ifdef DEBUG_THREADS 00712 if (res) { 00713 __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n", 00714 filename, lineno, func, rwlock_name, strerror(res)); 00715 } 00716 ast_reentrancy_lock(lt); 00717 lt->file[0] = filename; 00718 lt->lineno[0] = lineno; 00719 lt->func[0] = func; 00720 lt->reentrancy = 0; 00721 lt->thread[0] = 0; 00722 #ifdef HAVE_BKTR 00723 memset(<->backtrace[0], 0, sizeof(lt->backtrace[0])); 00724 #endif 00725 ast_reentrancy_unlock(lt); 00726 delete_reentrancy_cs(lt); 00727 #endif /* DEBUG_THREADS */ 00728 00729 return res; 00730 }
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 658 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().
00659 { 00660 int res; 00661 pthread_rwlockattr_t attr; 00662 00663 #ifdef DEBUG_THREADS 00664 struct ast_lock_track *lt= &t->track; 00665 00666 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00667 int canlog = strcmp(filename, "logger.c") & t->tracking; 00668 00669 if (t->lock != ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 00670 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n", 00671 filename, lineno, func, rwlock_name); 00672 return 0; 00673 } 00674 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00675 00676 ast_reentrancy_init(lt); 00677 t->tracking = tracking; 00678 #endif /* DEBUG_THREADS */ 00679 00680 pthread_rwlockattr_init(&attr); 00681 00682 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP 00683 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP); 00684 #endif 00685 00686 res = pthread_rwlock_init(&t->lock, &attr); 00687 pthread_rwlockattr_destroy(&attr); 00688 return res; 00689 }
int __ast_rwlock_rdlock | ( | ast_rwlock_t * | t, | |
const char * | name, | |||
const char * | filename, | |||
int | line, | |||
const char * | func | |||
) |
Definition at line 814 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_rwlock_info::track, and ast_rwlock_info::tracking.
Referenced by __ast_heap_rdlock().
00816 { 00817 int res; 00818 00819 #ifdef DEBUG_THREADS 00820 struct ast_lock_track *lt = &t->track; 00821 int canlog = strcmp(filename, "logger.c") & t->tracking; 00822 #ifdef HAVE_BKTR 00823 struct ast_bt *bt = NULL; 00824 #endif 00825 00826 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00827 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 00828 /* Don't warn abount uninitialized lock. 00829 * Simple try to initialize it. 00830 * May be not needed in linux system. 00831 */ 00832 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t); 00833 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 00834 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", 00835 filename, line, func, name); 00836 return res; 00837 } 00838 } 00839 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00840 00841 if (t->tracking) { 00842 #ifdef HAVE_BKTR 00843 ast_reentrancy_lock(lt); 00844 if (lt->reentrancy != AST_MAX_REENTRANCY) { 00845 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 00846 bt = <->backtrace[lt->reentrancy]; 00847 } 00848 ast_reentrancy_unlock(lt); 00849 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt); 00850 #else 00851 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t); 00852 #endif 00853 } 00854 #endif /* DEBUG_THREADS */ 00855 00856 #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS) 00857 { 00858 time_t seconds = time(NULL); 00859 time_t wait_time, reported_wait = 0; 00860 do { 00861 res = pthread_rwlock_tryrdlock(&t->lock); 00862 if (res == EBUSY) { 00863 wait_time = time(NULL) - seconds; 00864 if (wait_time > reported_wait && (wait_time % 5) == 0) { 00865 __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n", 00866 filename, line, func, (int)wait_time, name); 00867 ast_reentrancy_lock(lt); 00868 #ifdef HAVE_BKTR 00869 __dump_backtrace(<->backtrace[lt->reentrancy], canlog); 00870 #endif 00871 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n", 00872 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], 00873 lt->func[lt->reentrancy-1], name); 00874 #ifdef HAVE_BKTR 00875 __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog); 00876 #endif 00877 ast_reentrancy_unlock(lt); 00878 reported_wait = wait_time; 00879 } 00880 usleep(200); 00881 } 00882 } while (res == EBUSY); 00883 } 00884 #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */ 00885 res = pthread_rwlock_rdlock(&t->lock); 00886 #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */ 00887 00888 #ifdef DEBUG_THREADS 00889 if (!res) { 00890 ast_reentrancy_lock(lt); 00891 if (lt->reentrancy < AST_MAX_REENTRANCY) { 00892 lt->file[lt->reentrancy] = filename; 00893 lt->lineno[lt->reentrancy] = line; 00894 lt->func[lt->reentrancy] = func; 00895 lt->thread[lt->reentrancy] = pthread_self(); 00896 lt->reentrancy++; 00897 } 00898 ast_reentrancy_unlock(lt); 00899 if (t->tracking) { 00900 ast_mark_lock_acquired(t); 00901 } 00902 } else { 00903 #ifdef HAVE_BKTR 00904 if (lt->reentrancy) { 00905 ast_reentrancy_lock(lt); 00906 bt = <->backtrace[lt->reentrancy-1]; 00907 ast_reentrancy_unlock(lt); 00908 } else { 00909 bt = NULL; 00910 } 00911 if (t->tracking) { 00912 ast_remove_lock_info(t, bt); 00913 } 00914 #else 00915 if (t->tracking) { 00916 ast_remove_lock_info(t); 00917 } 00918 #endif 00919 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n", 00920 filename, line, func, strerror(res)); 00921 DO_THREAD_CRASH; 00922 } 00923 #endif /* DEBUG_THREADS */ 00924 00925 return res; 00926 }
int __ast_rwlock_timedrdlock | ( | ast_rwlock_t * | t, | |
const char * | name, | |||
const struct timespec * | abs_timeout, | |||
const char * | filename, | |||
int | line, | |||
const char * | func | |||
) |
Definition at line 1042 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.
01044 { 01045 int res; 01046 01047 #ifdef DEBUG_THREADS 01048 struct ast_lock_track *lt = &t->track; 01049 int canlog = strcmp(filename, "logger.c") & t->tracking; 01050 #ifdef HAVE_BKTR 01051 struct ast_bt *bt = NULL; 01052 #endif 01053 01054 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 01055 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 01056 /* Don't warn abount uninitialized lock. 01057 * Simple try to initialize it. 01058 * May be not needed in linux system. 01059 */ 01060 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t); 01061 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 01062 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", 01063 filename, line, func, name); 01064 return res; 01065 } 01066 } 01067 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 01068 01069 if (t->tracking) { 01070 #ifdef HAVE_BKTR 01071 ast_reentrancy_lock(lt); 01072 if (lt->reentrancy != AST_MAX_REENTRANCY) { 01073 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 01074 bt = <->backtrace[lt->reentrancy]; 01075 } 01076 ast_reentrancy_unlock(lt); 01077 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt); 01078 #else 01079 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t); 01080 #endif 01081 } 01082 #endif /* DEBUG_THREADS */ 01083 01084 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK 01085 res = pthread_rwlock_timedrdlock(&t->lock, abs_timeout); 01086 #else 01087 do { 01088 struct timeval _start = ast_tvnow(), _diff; 01089 for (;;) { 01090 if (!(res = pthread_rwlock_tryrdlock(&t->lock))) { 01091 break; 01092 } 01093 _diff = ast_tvsub(ast_tvnow(), _start); 01094 if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) { 01095 break; 01096 } 01097 usleep(1); 01098 } 01099 } while (0); 01100 #endif 01101 01102 #ifdef DEBUG_THREADS 01103 if (!res) { 01104 ast_reentrancy_lock(lt); 01105 if (lt->reentrancy < AST_MAX_REENTRANCY) { 01106 lt->file[lt->reentrancy] = filename; 01107 lt->lineno[lt->reentrancy] = line; 01108 lt->func[lt->reentrancy] = func; 01109 lt->thread[lt->reentrancy] = pthread_self(); 01110 lt->reentrancy++; 01111 } 01112 ast_reentrancy_unlock(lt); 01113 if (t->tracking) { 01114 ast_mark_lock_acquired(t); 01115 } 01116 } else { 01117 #ifdef HAVE_BKTR 01118 if (lt->reentrancy) { 01119 ast_reentrancy_lock(lt); 01120 bt = <->backtrace[lt->reentrancy-1]; 01121 ast_reentrancy_unlock(lt); 01122 } else { 01123 bt = NULL; 01124 } 01125 if (t->tracking) { 01126 ast_remove_lock_info(t, bt); 01127 } 01128 #else 01129 if (t->tracking) { 01130 ast_remove_lock_info(t); 01131 } 01132 #endif 01133 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n", 01134 filename, line, func, strerror(res)); 01135 DO_THREAD_CRASH; 01136 } 01137 #endif /* DEBUG_THREADS */ 01138 01139 return res; 01140 }
int __ast_rwlock_timedwrlock | ( | ast_rwlock_t * | t, | |
const char * | name, | |||
const struct timespec * | abs_timeout, | |||
const char * | filename, | |||
int | line, | |||
const char * | func | |||
) |
Definition at line 1142 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.
01144 { 01145 int res; 01146 01147 #ifdef DEBUG_THREADS 01148 struct ast_lock_track *lt = &t->track; 01149 int canlog = strcmp(filename, "logger.c") & t->tracking; 01150 #ifdef HAVE_BKTR 01151 struct ast_bt *bt = NULL; 01152 #endif 01153 01154 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 01155 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 01156 /* Don't warn abount uninitialized lock. 01157 * Simple try to initialize it. 01158 * May be not needed in linux system. 01159 */ 01160 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t); 01161 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 01162 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", 01163 filename, line, func, name); 01164 return res; 01165 } 01166 } 01167 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 01168 01169 if (t->tracking) { 01170 #ifdef HAVE_BKTR 01171 ast_reentrancy_lock(lt); 01172 if (lt->reentrancy != AST_MAX_REENTRANCY) { 01173 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 01174 bt = <->backtrace[lt->reentrancy]; 01175 } 01176 ast_reentrancy_unlock(lt); 01177 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt); 01178 #else 01179 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t); 01180 #endif 01181 } 01182 #endif /* DEBUG_THREADS */ 01183 01184 #ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK 01185 res = pthread_rwlock_timedwrlock(&t->lock, abs_timeout); 01186 #else 01187 do { 01188 struct timeval _start = ast_tvnow(), _diff; 01189 for (;;) { 01190 if (!(res = pthread_rwlock_trywrlock(&t->lock))) { 01191 break; 01192 } 01193 _diff = ast_tvsub(ast_tvnow(), _start); 01194 if (_diff.tv_sec > abs_timeout->tv_sec || (_diff.tv_sec == abs_timeout->tv_sec && _diff.tv_usec * 1000 > abs_timeout->tv_nsec)) { 01195 break; 01196 } 01197 usleep(1); 01198 } 01199 } while (0); 01200 #endif 01201 01202 #ifdef DEBUG_THREADS 01203 if (!res) { 01204 ast_reentrancy_lock(lt); 01205 if (lt->reentrancy < AST_MAX_REENTRANCY) { 01206 lt->file[lt->reentrancy] = filename; 01207 lt->lineno[lt->reentrancy] = line; 01208 lt->func[lt->reentrancy] = func; 01209 lt->thread[lt->reentrancy] = pthread_self(); 01210 lt->reentrancy++; 01211 } 01212 ast_reentrancy_unlock(lt); 01213 if (t->tracking) { 01214 ast_mark_lock_acquired(t); 01215 } 01216 } else { 01217 #ifdef HAVE_BKTR 01218 if (lt->reentrancy) { 01219 ast_reentrancy_lock(lt); 01220 bt = <->backtrace[lt->reentrancy-1]; 01221 ast_reentrancy_unlock(lt); 01222 } else { 01223 bt = NULL; 01224 } 01225 if (t->tracking) { 01226 ast_remove_lock_info(t, bt); 01227 } 01228 #else 01229 if (t->tracking) { 01230 ast_remove_lock_info(t); 01231 } 01232 #endif 01233 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n", 01234 filename, line, func, strerror(res)); 01235 DO_THREAD_CRASH; 01236 } 01237 #endif /* DEBUG_THREADS */ 01238 01239 return res; 01240 }
int __ast_rwlock_tryrdlock | ( | ast_rwlock_t * | t, | |
const char * | name, | |||
const char * | filename, | |||
int | line, | |||
const char * | func | |||
) |
Definition at line 1242 of file lock.c.
References __ast_rwlock_init(), __AST_RWLOCK_INIT_VALUE, ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_rwlock_info::track, and ast_rwlock_info::tracking.
01244 { 01245 int res; 01246 01247 #ifdef DEBUG_THREADS 01248 struct ast_lock_track *lt = &t->track; 01249 #ifdef HAVE_BKTR 01250 struct ast_bt *bt = NULL; 01251 #endif 01252 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 01253 int canlog = strcmp(filename, "logger.c") & t->tracking; 01254 01255 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 01256 /* Don't warn abount uninitialized lock. 01257 * Simple try to initialize it. 01258 * May be not needed in linux system. 01259 */ 01260 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t); 01261 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 01262 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", 01263 filename, line, func, name); 01264 return res; 01265 } 01266 } 01267 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 01268 01269 if (t->tracking) { 01270 #ifdef HAVE_BKTR 01271 ast_reentrancy_lock(lt); 01272 if (lt->reentrancy != AST_MAX_REENTRANCY) { 01273 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 01274 bt = <->backtrace[lt->reentrancy]; 01275 } 01276 ast_reentrancy_unlock(lt); 01277 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt); 01278 #else 01279 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t); 01280 #endif 01281 } 01282 #endif /* DEBUG_THREADS */ 01283 01284 res = pthread_rwlock_tryrdlock(&t->lock); 01285 01286 #ifdef DEBUG_THREADS 01287 if (!res) { 01288 ast_reentrancy_lock(lt); 01289 if (lt->reentrancy < AST_MAX_REENTRANCY) { 01290 lt->file[lt->reentrancy] = filename; 01291 lt->lineno[lt->reentrancy] = line; 01292 lt->func[lt->reentrancy] = func; 01293 lt->thread[lt->reentrancy] = pthread_self(); 01294 lt->reentrancy++; 01295 } 01296 ast_reentrancy_unlock(lt); 01297 if (t->tracking) { 01298 ast_mark_lock_acquired(t); 01299 } 01300 } else if (t->tracking) { 01301 ast_mark_lock_failed(t); 01302 } 01303 #endif /* DEBUG_THREADS */ 01304 01305 return res; 01306 }
int __ast_rwlock_trywrlock | ( | ast_rwlock_t * | t, | |
const char * | name, | |||
const char * | filename, | |||
int | line, | |||
const char * | func | |||
) |
Definition at line 1308 of file lock.c.
References __ast_rwlock_init(), __AST_RWLOCK_INIT_VALUE, ast_bt_get_addresses(), AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_rwlock_info::lock, ast_lock_track::reentrancy, ast_rwlock_info::track, and ast_rwlock_info::tracking.
01310 { 01311 int res; 01312 01313 #ifdef DEBUG_THREADS 01314 struct ast_lock_track *lt= &t->track; 01315 #ifdef HAVE_BKTR 01316 struct ast_bt *bt = NULL; 01317 #endif 01318 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 01319 int canlog = strcmp(filename, "logger.c") & t->tracking; 01320 01321 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 01322 /* Don't warn abount uninitialized lock. 01323 * Simple try to initialize it. 01324 * May be not needed in linux system. 01325 */ 01326 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t); 01327 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 01328 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", 01329 filename, line, func, name); 01330 return res; 01331 } 01332 } 01333 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 01334 01335 if (t->tracking) { 01336 #ifdef HAVE_BKTR 01337 ast_reentrancy_lock(lt); 01338 if (lt->reentrancy != AST_MAX_REENTRANCY) { 01339 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 01340 bt = <->backtrace[lt->reentrancy]; 01341 } 01342 ast_reentrancy_unlock(lt); 01343 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt); 01344 #else 01345 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t); 01346 #endif 01347 } 01348 #endif /* DEBUG_THREADS */ 01349 01350 res = pthread_rwlock_trywrlock(&t->lock); 01351 01352 #ifdef DEBUG_THREADS 01353 if (!res) { 01354 ast_reentrancy_lock(lt); 01355 if (lt->reentrancy < AST_MAX_REENTRANCY) { 01356 lt->file[lt->reentrancy] = filename; 01357 lt->lineno[lt->reentrancy] = line; 01358 lt->func[lt->reentrancy] = func; 01359 lt->thread[lt->reentrancy] = pthread_self(); 01360 lt->reentrancy++; 01361 } 01362 ast_reentrancy_unlock(lt); 01363 if (t->tracking) { 01364 ast_mark_lock_acquired(t); 01365 } 01366 } else if (t->tracking) { 01367 ast_mark_lock_failed(t); 01368 } 01369 #endif /* DEBUG_THREADS */ 01370 01371 return res; 01372 }
int __ast_rwlock_unlock | ( | ast_rwlock_t * | t, | |
const char * | name, | |||
const char * | filename, | |||
int | line, | |||
const char * | func | |||
) |
Definition at line 732 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().
00734 { 00735 int res; 00736 00737 #ifdef DEBUG_THREADS 00738 struct ast_lock_track *lt = &t->track; 00739 int canlog = strcmp(filename, "logger.c") & t->tracking; 00740 #ifdef HAVE_BKTR 00741 struct ast_bt *bt = NULL; 00742 #endif 00743 int lock_found = 0; 00744 00745 00746 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00747 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 00748 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n", 00749 filename, line, func, name); 00750 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t); 00751 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 00752 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", 00753 filename, line, func, name); 00754 } 00755 return res; 00756 } 00757 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00758 00759 ast_reentrancy_lock(lt); 00760 if (lt->reentrancy) { 00761 int i; 00762 pthread_t self = pthread_self(); 00763 for (i = lt->reentrancy - 1; i >= 0; --i) { 00764 if (lt->thread[i] == self) { 00765 lock_found = 1; 00766 if (i != lt->reentrancy - 1) { 00767 lt->file[i] = lt->file[lt->reentrancy - 1]; 00768 lt->lineno[i] = lt->lineno[lt->reentrancy - 1]; 00769 lt->func[i] = lt->func[lt->reentrancy - 1]; 00770 lt->thread[i] = lt->thread[lt->reentrancy - 1]; 00771 } 00772 #ifdef HAVE_BKTR 00773 bt = <->backtrace[i]; 00774 #endif 00775 lt->file[lt->reentrancy - 1] = NULL; 00776 lt->lineno[lt->reentrancy - 1] = 0; 00777 lt->func[lt->reentrancy - 1] = NULL; 00778 lt->thread[lt->reentrancy - 1] = AST_PTHREADT_NULL; 00779 break; 00780 } 00781 } 00782 } 00783 00784 if (lock_found && --lt->reentrancy < 0) { 00785 __ast_mutex_logger("%s line %d (%s): rwlock '%s' freed more times than we've locked!\n", 00786 filename, line, func, name); 00787 lt->reentrancy = 0; 00788 } 00789 00790 ast_reentrancy_unlock(lt); 00791 00792 if (t->tracking) { 00793 #ifdef HAVE_BKTR 00794 ast_remove_lock_info(t, bt); 00795 #else 00796 ast_remove_lock_info(t); 00797 #endif 00798 } 00799 #endif /* DEBUG_THREADS */ 00800 00801 res = pthread_rwlock_unlock(&t->lock); 00802 00803 #ifdef DEBUG_THREADS 00804 if (res) { 00805 __ast_mutex_logger("%s line %d (%s): Error releasing rwlock: %s\n", 00806 filename, line, func, strerror(res)); 00807 DO_THREAD_CRASH; 00808 } 00809 #endif /* DEBUG_THREADS */ 00810 00811 return res; 00812 }
int __ast_rwlock_wrlock | ( | ast_rwlock_t * | t, | |
const char * | name, | |||
const char * | filename, | |||
int | line, | |||
const char * | func | |||
) |
Definition at line 928 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_rwlock_info::track, and ast_rwlock_info::tracking.
Referenced by __ast_heap_wrlock().
00930 { 00931 int res; 00932 00933 #ifdef DEBUG_THREADS 00934 struct ast_lock_track *lt = &t->track; 00935 int canlog = strcmp(filename, "logger.c") & t->tracking; 00936 #ifdef HAVE_BKTR 00937 struct ast_bt *bt = NULL; 00938 #endif 00939 00940 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE) 00941 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 00942 /* Don't warn abount uninitialized lock. 00943 * Simple try to initialize it. 00944 * May be not needed in linux system. 00945 */ 00946 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t); 00947 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) { 00948 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n", 00949 filename, line, func, name); 00950 return res; 00951 } 00952 } 00953 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00954 00955 if (t->tracking) { 00956 #ifdef HAVE_BKTR 00957 ast_reentrancy_lock(lt); 00958 if (lt->reentrancy != AST_MAX_REENTRANCY) { 00959 ast_bt_get_addresses(<->backtrace[lt->reentrancy]); 00960 bt = <->backtrace[lt->reentrancy]; 00961 } 00962 ast_reentrancy_unlock(lt); 00963 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt); 00964 #else 00965 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t); 00966 #endif 00967 } 00968 #endif /* DEBUG_THREADS */ 00969 00970 #if defined(DETECT_DEADLOCKS) && defined(DEBUG_THREADS) 00971 { 00972 time_t seconds = time(NULL); 00973 time_t wait_time, reported_wait = 0; 00974 do { 00975 res = pthread_rwlock_trywrlock(&t->lock); 00976 if (res == EBUSY) { 00977 wait_time = time(NULL) - seconds; 00978 if (wait_time > reported_wait && (wait_time % 5) == 0) { 00979 __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n", 00980 filename, line, func, (int)wait_time, name); 00981 ast_reentrancy_lock(lt); 00982 #ifdef HAVE_BKTR 00983 __dump_backtrace(<->backtrace[lt->reentrancy], canlog); 00984 #endif 00985 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n", 00986 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], 00987 lt->func[lt->reentrancy-1], name); 00988 #ifdef HAVE_BKTR 00989 __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog); 00990 #endif 00991 ast_reentrancy_unlock(lt); 00992 reported_wait = wait_time; 00993 } 00994 usleep(200); 00995 } 00996 } while (res == EBUSY); 00997 } 00998 #else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */ 00999 res = pthread_rwlock_wrlock(&t->lock); 01000 #endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */ 01001 01002 #ifdef DEBUG_THREADS 01003 if (!res) { 01004 ast_reentrancy_lock(lt); 01005 if (lt->reentrancy < AST_MAX_REENTRANCY) { 01006 lt->file[lt->reentrancy] = filename; 01007 lt->lineno[lt->reentrancy] = line; 01008 lt->func[lt->reentrancy] = func; 01009 lt->thread[lt->reentrancy] = pthread_self(); 01010 lt->reentrancy++; 01011 } 01012 ast_reentrancy_unlock(lt); 01013 if (t->tracking) { 01014 ast_mark_lock_acquired(t); 01015 } 01016 } else { 01017 #ifdef HAVE_BKTR 01018 if (lt->reentrancy) { 01019 ast_reentrancy_lock(lt); 01020 bt = <->backtrace[lt->reentrancy-1]; 01021 ast_reentrancy_unlock(lt); 01022 } else { 01023 bt = NULL; 01024 } 01025 if (t->tracking) { 01026 ast_remove_lock_info(t, bt); 01027 } 01028 #else 01029 if (t->tracking) { 01030 ast_remove_lock_info(t); 01031 } 01032 #endif 01033 __ast_mutex_logger("%s line %d (%s): Error obtaining write lock: %s\n", 01034 filename, line, func, strerror(res)); 01035 DO_THREAD_CRASH; 01036 } 01037 #endif /* DEBUG_THREADS */ 01038 01039 return res; 01040 }