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