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: 269569 $")
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 #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
00055
00056
00057
00058
00059 return 0;
00060 }
00061
00062 #endif
00063
00064 ast_reentrancy_init(&t->track);
00065 t->tracking = tracking;
00066 #endif
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 }
00075
00076 int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
00077 const char *mutex_name, ast_mutex_t *t)
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
00088
00089
00090
00091
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
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
00143
00144 return res;
00145 }
00146
00147 int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
00148 const char* mutex_name, ast_mutex_t *t)
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
00162
00163
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
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
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
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
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
00272
00273 return res;
00274 }
00275
00276 int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
00277 const char* mutex_name, ast_mutex_t *t)
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
00291
00292
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
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
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
00341
00342 return res;
00343 }
00344
00345 int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
00346 const char *mutex_name, ast_mutex_t *t)
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
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
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
00420
00421 return res;
00422 }
00423
00424
00425 int __ast_cond_init(const char *filename, int lineno, const char *func,
00426 const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
00427 {
00428 return pthread_cond_init(cond, cond_attr);
00429 }
00430
00431 int __ast_cond_signal(const char *filename, int lineno, const char *func,
00432 const char *cond_name, ast_cond_t *cond)
00433 {
00434 return pthread_cond_signal(cond);
00435 }
00436
00437 int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
00438 const char *cond_name, ast_cond_t *cond)
00439 {
00440 return pthread_cond_broadcast(cond);
00441 }
00442
00443 int __ast_cond_destroy(const char *filename, int lineno, const char *func,
00444 const char *cond_name, ast_cond_t *cond)
00445 {
00446 return pthread_cond_destroy(cond);
00447 }
00448
00449 int __ast_cond_wait(const char *filename, int lineno, const char *func,
00450 const char *cond_name, const char *mutex_name,
00451 ast_cond_t *cond, ast_mutex_t *t)
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
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
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
00550
00551 return res;
00552 }
00553
00554 int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
00555 const char *cond_name, const char *mutex_name, ast_cond_t *cond,
00556 ast_mutex_t *t, const struct timespec *abstime)
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
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
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
00654
00655 return res;
00656 }
00657
00658 int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
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
00675
00676 ast_reentrancy_init(lt);
00677 t->tracking = tracking;
00678 #endif
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 }
00690
00691 int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
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
00706
00707 #endif
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
00728
00729 return res;
00730 }
00731
00732 int __ast_rwlock_unlock(ast_rwlock_t *t, const char *name,
00733 const char *filename, int line, const char *func)
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
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
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
00810
00811 return res;
00812 }
00813
00814 int __ast_rwlock_rdlock(ast_rwlock_t *t, const char *name,
00815 const char *filename, int line, const char *func)
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
00829
00830
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
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
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
00885 res = pthread_rwlock_rdlock(&t->lock);
00886 #endif
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
00924
00925 return res;
00926 }
00927
00928 int __ast_rwlock_wrlock(ast_rwlock_t *t, const char *name,
00929 const char *filename, int line, const char *func)
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
00943
00944
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
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
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
00999 res = pthread_rwlock_wrlock(&t->lock);
01000 #endif
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
01038
01039 return res;
01040 }
01041
01042 int __ast_rwlock_timedrdlock(ast_rwlock_t *t, const char *name,
01043 const struct timespec *abs_timeout, const char *filename, int line, const char *func)
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
01057
01058
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
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
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
01138
01139 return res;
01140 }
01141
01142 int __ast_rwlock_timedwrlock(ast_rwlock_t *t, const char *name,
01143 const struct timespec *abs_timeout, const char *filename, int line, const char *func)
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
01157
01158
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
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
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
01238
01239 return res;
01240 }
01241
01242 int __ast_rwlock_tryrdlock(ast_rwlock_t *t, const char *name,
01243 const char *filename, int line, const char *func)
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
01257
01258
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
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
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
01304
01305 return res;
01306 }
01307
01308 int __ast_rwlock_trywrlock(ast_rwlock_t *t, const char *name,
01309 const char *filename, int line, const char *func)
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
01323
01324
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
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
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
01370
01371 return res;
01372 }