00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 #ifndef _ASTERISK_LOCK_H
00049 #define _ASTERISK_LOCK_H
00050
00051 #include <pthread.h>
00052 #include <sys/param.h>
00053 #ifdef HAVE_BKTR
00054 #include <execinfo.h>
00055 #endif
00056 #include "asterisk/logger.h"
00057
00058
00059
00060
00061 #ifndef HAVE_MTX_PROFILE
00062 #define __MTX_PROF(a) return pthread_mutex_lock((a))
00063 #else
00064 #define __MTX_PROF(a) do { \
00065 int i; \
00066 \
00067 ast_mark(mtx_prof, 1); \
00068 i = pthread_mutex_trylock((a)); \
00069 ast_mark(mtx_prof, 0); \
00070 if (!i) \
00071 return i; \
00072 else \
00073 return pthread_mutex_lock((a)); \
00074 } while (0)
00075 #endif
00076
00077 #define AST_PTHREADT_NULL (pthread_t) -1
00078 #define AST_PTHREADT_STOP (pthread_t) -2
00079
00080 #if defined(SOLARIS) || defined(BSD)
00081 #define AST_MUTEX_INIT_W_CONSTRUCTORS
00082 #endif
00083
00084
00085
00086 #if defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(HAVE_PTHREAD_MUTEX_RECURSIVE_NP)
00087 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00088 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP
00089 #else
00090 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
00091 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE
00092 #endif
00093
00094
00095
00096
00097
00098
00099
00100
00101 #ifdef DEBUG_THREADS
00102
00103 #define __ast_mutex_logger(...) do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
00104
00105 #ifdef THREAD_CRASH
00106 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
00107 #else
00108 #define DO_THREAD_CRASH do { } while (0)
00109 #endif
00110
00111 #include <errno.h>
00112
00113 #ifdef HAVE_BKTR
00114 #define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
00115
00116 #else
00117 #define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
00118 #endif
00119
00120 #define AST_MUTEX_INIT_VALUE { AST_LOCK_TRACK_INIT_VALUE, 1, PTHREAD_MUTEX_INIT_VALUE }
00121 #define AST_MUTEX_INIT_VALUE_NOTRACKING { AST_LOCK_TRACK_INIT_VALUE, 0, PTHREAD_MUTEX_INIT_VALUE }
00122
00123 #define AST_MAX_REENTRANCY 10
00124
00125 struct ast_channel;
00126
00127 struct ast_lock_track {
00128 const char *file[AST_MAX_REENTRANCY];
00129 int lineno[AST_MAX_REENTRANCY];
00130 int reentrancy;
00131 const char *func[AST_MAX_REENTRANCY];
00132 pthread_t thread[AST_MAX_REENTRANCY];
00133 #ifdef HAVE_BKTR
00134 struct ast_bt backtrace[AST_MAX_REENTRANCY];
00135 #endif
00136 pthread_mutex_t reentr_mutex;
00137 };
00138
00139 struct ast_mutex_info {
00140
00141 struct ast_lock_track track;
00142 unsigned int tracking:1;
00143 pthread_mutex_t mutex;
00144 };
00145
00146 typedef struct ast_mutex_info ast_mutex_t;
00147
00148 typedef pthread_cond_t ast_cond_t;
00149
00150 enum ast_lock_type {
00151 AST_MUTEX,
00152 AST_RDLOCK,
00153 AST_WRLOCK,
00154 };
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 #if !defined(LOW_MEMORY)
00165 #ifdef HAVE_BKTR
00166 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00167 int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt);
00168 #else
00169 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00170 int line_num, const char *func, const char *lock_name, void *lock_addr);
00171 #endif
00172
00173 #else
00174
00175 #ifdef HAVE_BKTR
00176 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS,BUD)
00177 #else
00178 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
00179 #endif
00180 #endif
00181
00182
00183
00184
00185 #if !defined(LOW_MEMORY)
00186 void ast_mark_lock_acquired(void *lock_addr);
00187 #else
00188 #define ast_mark_lock_acquired(ignore)
00189 #endif
00190
00191
00192
00193
00194 #if !defined(LOW_MEMORY)
00195 void ast_mark_lock_failed(void *lock_addr);
00196 #else
00197 #define ast_mark_lock_failed(ignore)
00198 #endif
00199
00200
00201
00202
00203
00204
00205
00206 #if !defined(LOW_MEMORY)
00207 #ifdef HAVE_BKTR
00208 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt);
00209 #else
00210 void ast_remove_lock_info(void *lock_addr);
00211 #endif
00212 #else
00213 #ifdef HAVE_BKTR
00214 #define ast_remove_lock_info(ignore,me)
00215 #else
00216 #define ast_remove_lock_info(ignore)
00217 #endif
00218 #endif
00219
00220 #ifdef HAVE_BKTR
00221 static inline void __dump_backtrace(struct ast_bt *bt, int canlog)
00222 {
00223 char **strings;
00224
00225 ssize_t i;
00226
00227 strings = backtrace_symbols(bt->addresses, bt->num_frames);
00228
00229 for (i = 0; i < bt->num_frames; i++)
00230 __ast_mutex_logger("%s\n", strings[i]);
00231
00232 free(strings);
00233 }
00234 #endif
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 void log_show_lock(void *this_lock_addr);
00247
00248
00249
00250
00251
00252
00253
00254 #if !defined(LOW_MEMORY)
00255 int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, int *lineno, char *func, size_t func_size, char *mutex_name, size_t mutex_name_size);
00256 #else
00257 #define ast_find_lock_info(a,b,c,d,e,f,g,h) -1
00258 #endif
00259
00260
00261
00262
00263
00264
00265
00266 #define CHANNEL_DEADLOCK_AVOIDANCE(chan) \
00267 do { \
00268 char __filename[80], __func[80], __mutex_name[80]; \
00269 int __lineno; \
00270 int __res = ast_find_lock_info(&chan->lock_dont_use, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
00271 ast_channel_unlock(chan); \
00272 usleep(1); \
00273 if (__res < 0) { \
00274 ast_channel_lock(chan); \
00275 } else { \
00276 __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, &chan->lock_dont_use); \
00277 } \
00278 } while (0)
00279
00280 #define DEADLOCK_AVOIDANCE(lock) \
00281 do { \
00282 char __filename[80], __func[80], __mutex_name[80]; \
00283 int __lineno; \
00284 int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
00285 ast_mutex_unlock(lock); \
00286 usleep(1); \
00287 if (__res < 0) { \
00288 ast_mutex_lock(lock); \
00289 } else { \
00290 __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
00291 } \
00292 } while (0)
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 #define DLA_UNLOCK(lock) \
00307 do { \
00308 char __filename[80], __func[80], __mutex_name[80]; \
00309 int __lineno; \
00310 int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
00311 ast_mutex_unlock(lock);
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 #define DLA_LOCK(lock) \
00326 if (__res < 0) { \
00327 ast_mutex_lock(lock); \
00328 } else { \
00329 __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
00330 } \
00331 } while (0)
00332
00333 static inline void ast_reentrancy_lock(struct ast_lock_track *lt)
00334 {
00335 pthread_mutex_lock(<->reentr_mutex);
00336 }
00337
00338 static inline void ast_reentrancy_unlock(struct ast_lock_track *lt)
00339 {
00340 pthread_mutex_unlock(<->reentr_mutex);
00341 }
00342
00343 static inline void ast_reentrancy_init(struct ast_lock_track *lt)
00344 {
00345 int i;
00346 pthread_mutexattr_t reentr_attr;
00347
00348 for (i = 0; i < AST_MAX_REENTRANCY; i++) {
00349 lt->file[i] = NULL;
00350 lt->lineno[i] = 0;
00351 lt->func[i] = NULL;
00352 lt->thread[i] = 0;
00353 #ifdef HAVE_BKTR
00354 memset(<->backtrace[i], 0, sizeof(lt->backtrace[i]));
00355 #endif
00356 }
00357
00358 lt->reentrancy = 0;
00359
00360 pthread_mutexattr_init(&reentr_attr);
00361 pthread_mutexattr_settype(&reentr_attr, AST_MUTEX_KIND);
00362 pthread_mutex_init(<->reentr_mutex, &reentr_attr);
00363 pthread_mutexattr_destroy(&reentr_attr);
00364 }
00365
00366 static inline void delete_reentrancy_cs(struct ast_lock_track *lt)
00367 {
00368 pthread_mutex_destroy(<->reentr_mutex);
00369 }
00370
00371 static inline int __ast_pthread_mutex_init(int tracking, const char *filename, int lineno, const char *func,
00372 const char *mutex_name, ast_mutex_t *t)
00373 {
00374 int res;
00375 pthread_mutexattr_t attr;
00376
00377 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00378
00379 if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00380
00381
00382
00383
00384
00385
00386 return 0;
00387 }
00388
00389 #endif
00390
00391 ast_reentrancy_init(&t->track);
00392 t->tracking = tracking;
00393
00394 pthread_mutexattr_init(&attr);
00395 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00396
00397 res = pthread_mutex_init(&t->mutex, &attr);
00398 pthread_mutexattr_destroy(&attr);
00399 return res;
00400 }
00401
00402 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
00403 #define ast_mutex_init_notracking(pmutex) \
00404 __ast_pthread_mutex_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
00405
00406 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
00407 const char *mutex_name, ast_mutex_t *t)
00408 {
00409 int res;
00410 struct ast_lock_track *lt;
00411 int canlog = strcmp(filename, "logger.c") & t->tracking;
00412
00413 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00414 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00415
00416
00417
00418
00419
00420
00421 __ast_mutex_logger("%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
00422 filename, lineno, func, mutex_name);
00423 return 0;
00424 }
00425 #endif
00426
00427 lt = &t->track;
00428
00429 res = pthread_mutex_trylock(&t->mutex);
00430 switch (res) {
00431 case 0:
00432 pthread_mutex_unlock(&t->mutex);
00433 break;
00434 case EINVAL:
00435 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
00436 filename, lineno, func, mutex_name);
00437 break;
00438 case EBUSY:
00439 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
00440 filename, lineno, func, mutex_name);
00441 ast_reentrancy_lock(lt);
00442 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
00443 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
00444 #ifdef HAVE_BKTR
00445 __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
00446 #endif
00447 ast_reentrancy_unlock(lt);
00448 break;
00449 }
00450
00451
00452 if ((res = pthread_mutex_destroy(&t->mutex))) {
00453 __ast_mutex_logger("%s line %d (%s): Error destroying mutex %s: %s\n",
00454 filename, lineno, func, mutex_name, strerror(res));
00455 }
00456 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00457 else
00458 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
00459 #endif
00460 ast_reentrancy_lock(lt);
00461 lt->file[0] = filename;
00462 lt->lineno[0] = lineno;
00463 lt->func[0] = func;
00464 lt->reentrancy = 0;
00465 lt->thread[0] = 0;
00466 #ifdef HAVE_BKTR
00467 memset(<->backtrace[0], 0, sizeof(lt->backtrace[0]));
00468 #endif
00469 ast_reentrancy_unlock(lt);
00470 delete_reentrancy_cs(lt);
00471
00472 return res;
00473 }
00474
00475 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
00476 const char* mutex_name, ast_mutex_t *t)
00477 {
00478 int res;
00479 struct ast_lock_track *lt = &t->track;
00480 int canlog = strcmp(filename, "logger.c") & t->tracking;
00481 #ifdef HAVE_BKTR
00482 struct ast_bt *bt = NULL;
00483 #endif
00484
00485 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00486 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00487
00488
00489
00490
00491 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00492 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00493 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00494 filename, lineno, func, mutex_name);
00495 return res;
00496 }
00497 }
00498 #endif
00499
00500 if (t->tracking) {
00501 #ifdef HAVE_BKTR
00502 ast_reentrancy_lock(lt);
00503 if (lt->reentrancy != AST_MAX_REENTRANCY) {
00504 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
00505 bt = <->backtrace[lt->reentrancy];
00506 }
00507 ast_reentrancy_unlock(lt);
00508 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
00509 #else
00510 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
00511 #endif
00512 }
00513
00514 #ifdef DETECT_DEADLOCKS
00515 {
00516 time_t seconds = time(NULL);
00517 time_t wait_time, reported_wait = 0;
00518 do {
00519 #ifdef HAVE_MTX_PROFILE
00520 ast_mark(mtx_prof, 1);
00521 #endif
00522 res = pthread_mutex_trylock(&t->mutex);
00523 #ifdef HAVE_MTX_PROFILE
00524 ast_mark(mtx_prof, 0);
00525 #endif
00526 if (res == EBUSY) {
00527 wait_time = time(NULL) - seconds;
00528 if (wait_time > reported_wait && (wait_time % 5) == 0) {
00529 __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
00530 filename, lineno, func, (int) wait_time, mutex_name);
00531 ast_reentrancy_lock(lt);
00532 #ifdef HAVE_BKTR
00533 __dump_backtrace(<->backtrace[lt->reentrancy], canlog);
00534 #endif
00535 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00536 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
00537 lt->func[lt->reentrancy-1], mutex_name);
00538 #ifdef HAVE_BKTR
00539 __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
00540 #endif
00541 ast_reentrancy_unlock(lt);
00542 reported_wait = wait_time;
00543 }
00544 usleep(200);
00545 }
00546 } while (res == EBUSY);
00547 }
00548 #else
00549 #ifdef HAVE_MTX_PROFILE
00550 ast_mark(mtx_prof, 1);
00551 res = pthread_mutex_trylock(&t->mutex);
00552 ast_mark(mtx_prof, 0);
00553 if (res)
00554 #endif
00555 res = pthread_mutex_lock(&t->mutex);
00556 #endif
00557
00558 if (!res) {
00559 ast_reentrancy_lock(lt);
00560 if (lt->reentrancy < AST_MAX_REENTRANCY) {
00561 lt->file[lt->reentrancy] = filename;
00562 lt->lineno[lt->reentrancy] = lineno;
00563 lt->func[lt->reentrancy] = func;
00564 lt->thread[lt->reentrancy] = pthread_self();
00565 lt->reentrancy++;
00566 } else {
00567 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00568 filename, lineno, func, mutex_name);
00569 }
00570 ast_reentrancy_unlock(lt);
00571 if (t->tracking) {
00572 ast_mark_lock_acquired(t);
00573 }
00574 } else {
00575 #ifdef HAVE_BKTR
00576 if (lt->reentrancy) {
00577 ast_reentrancy_lock(lt);
00578 bt = <->backtrace[lt->reentrancy-1];
00579 ast_reentrancy_unlock(lt);
00580 } else {
00581 bt = NULL;
00582 }
00583 if (t->tracking) {
00584 ast_remove_lock_info(t, bt);
00585 }
00586 #else
00587 if (t->tracking) {
00588 ast_remove_lock_info(t);
00589 }
00590 #endif
00591 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
00592 filename, lineno, func, strerror(res));
00593 DO_THREAD_CRASH;
00594 }
00595
00596 return res;
00597 }
00598
00599 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
00600 const char* mutex_name, ast_mutex_t *t)
00601 {
00602 int res;
00603 struct ast_lock_track *lt= &t->track;
00604 int canlog = strcmp(filename, "logger.c") & t->tracking;
00605 #ifdef HAVE_BKTR
00606 struct ast_bt *bt = NULL;
00607 #endif
00608
00609 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00610 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00611
00612
00613
00614
00615 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00616 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00617 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00618 filename, lineno, func, mutex_name);
00619 return res;
00620 }
00621 }
00622 #endif
00623
00624 if (t->tracking) {
00625 #ifdef HAVE_BKTR
00626 ast_reentrancy_lock(lt);
00627 if (lt->reentrancy != AST_MAX_REENTRANCY) {
00628 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
00629 bt = <->backtrace[lt->reentrancy];
00630 }
00631 ast_reentrancy_unlock(lt);
00632 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
00633 #else
00634 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
00635 #endif
00636 }
00637
00638 if (!(res = pthread_mutex_trylock(&t->mutex))) {
00639 ast_reentrancy_lock(lt);
00640 if (lt->reentrancy < AST_MAX_REENTRANCY) {
00641 lt->file[lt->reentrancy] = filename;
00642 lt->lineno[lt->reentrancy] = lineno;
00643 lt->func[lt->reentrancy] = func;
00644 lt->thread[lt->reentrancy] = pthread_self();
00645 lt->reentrancy++;
00646 } else {
00647 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00648 filename, lineno, func, mutex_name);
00649 }
00650 ast_reentrancy_unlock(lt);
00651 if (t->tracking) {
00652 ast_mark_lock_acquired(t);
00653 }
00654 } else if (t->tracking) {
00655 ast_mark_lock_failed(t);
00656 }
00657
00658 return res;
00659 }
00660
00661 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
00662 const char *mutex_name, ast_mutex_t *t)
00663 {
00664 int res;
00665 struct ast_lock_track *lt = &t->track;
00666 int canlog = strcmp(filename, "logger.c") & t->tracking;
00667 #ifdef HAVE_BKTR
00668 struct ast_bt *bt = NULL;
00669 #endif
00670
00671 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00672 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00673 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00674 filename, lineno, func, mutex_name);
00675 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00676 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00677 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00678 filename, lineno, func, mutex_name);
00679 }
00680 return res;
00681 }
00682 #endif
00683
00684 ast_reentrancy_lock(lt);
00685 if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
00686 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00687 filename, lineno, func, mutex_name);
00688 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00689 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
00690 #ifdef HAVE_BKTR
00691 __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
00692 #endif
00693 DO_THREAD_CRASH;
00694 }
00695
00696 if (--lt->reentrancy < 0) {
00697 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00698 filename, lineno, func, mutex_name);
00699 lt->reentrancy = 0;
00700 }
00701
00702 if (lt->reentrancy < AST_MAX_REENTRANCY) {
00703 lt->file[lt->reentrancy] = NULL;
00704 lt->lineno[lt->reentrancy] = 0;
00705 lt->func[lt->reentrancy] = NULL;
00706 lt->thread[lt->reentrancy] = 0;
00707 }
00708
00709 #ifdef HAVE_BKTR
00710 if (lt->reentrancy) {
00711 bt = <->backtrace[lt->reentrancy - 1];
00712 }
00713 #endif
00714 ast_reentrancy_unlock(lt);
00715
00716 if (t->tracking) {
00717 #ifdef HAVE_BKTR
00718 ast_remove_lock_info(t, bt);
00719 #else
00720 ast_remove_lock_info(t);
00721 #endif
00722 }
00723
00724 if ((res = pthread_mutex_unlock(&t->mutex))) {
00725 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
00726 filename, lineno, func, strerror(res));
00727 DO_THREAD_CRASH;
00728 }
00729
00730 return res;
00731 }
00732
00733 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
00734 const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
00735 {
00736 return pthread_cond_init(cond, cond_attr);
00737 }
00738
00739 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
00740 const char *cond_name, ast_cond_t *cond)
00741 {
00742 return pthread_cond_signal(cond);
00743 }
00744
00745 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
00746 const char *cond_name, ast_cond_t *cond)
00747 {
00748 return pthread_cond_broadcast(cond);
00749 }
00750
00751 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
00752 const char *cond_name, ast_cond_t *cond)
00753 {
00754 return pthread_cond_destroy(cond);
00755 }
00756
00757 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
00758 const char *cond_name, const char *mutex_name,
00759 ast_cond_t *cond, ast_mutex_t *t)
00760 {
00761 int res;
00762 struct ast_lock_track *lt= &t->track;
00763 int canlog = strcmp(filename, "logger.c") & t->tracking;
00764 #ifdef HAVE_BKTR
00765 struct ast_bt *bt = NULL;
00766 #endif
00767
00768 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00769 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00770 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00771 filename, lineno, func, mutex_name);
00772 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00773 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00774 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00775 filename, lineno, func, mutex_name);
00776 }
00777 return res;
00778 }
00779 #endif
00780
00781 ast_reentrancy_lock(lt);
00782 if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
00783 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00784 filename, lineno, func, mutex_name);
00785 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00786 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
00787 #ifdef HAVE_BKTR
00788 __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
00789 #endif
00790 DO_THREAD_CRASH;
00791 }
00792
00793 if (--lt->reentrancy < 0) {
00794 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00795 filename, lineno, func, mutex_name);
00796 lt->reentrancy = 0;
00797 }
00798
00799 if (lt->reentrancy < AST_MAX_REENTRANCY) {
00800 lt->file[lt->reentrancy] = NULL;
00801 lt->lineno[lt->reentrancy] = 0;
00802 lt->func[lt->reentrancy] = NULL;
00803 lt->thread[lt->reentrancy] = 0;
00804 }
00805
00806 #ifdef HAVE_BKTR
00807 if (lt->reentrancy) {
00808 bt = <->backtrace[lt->reentrancy - 1];
00809 }
00810 #endif
00811 ast_reentrancy_unlock(lt);
00812
00813 if (t->tracking) {
00814 #ifdef HAVE_BKTR
00815 ast_remove_lock_info(t, bt);
00816 #else
00817 ast_remove_lock_info(t);
00818 #endif
00819 }
00820
00821 if ((res = pthread_cond_wait(cond, &t->mutex))) {
00822 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
00823 filename, lineno, func, strerror(res));
00824 DO_THREAD_CRASH;
00825 } else {
00826 ast_reentrancy_lock(lt);
00827 if (lt->reentrancy < AST_MAX_REENTRANCY) {
00828 lt->file[lt->reentrancy] = filename;
00829 lt->lineno[lt->reentrancy] = lineno;
00830 lt->func[lt->reentrancy] = func;
00831 lt->thread[lt->reentrancy] = pthread_self();
00832 #ifdef HAVE_BKTR
00833 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
00834 bt = <->backtrace[lt->reentrancy];
00835 #endif
00836 lt->reentrancy++;
00837 } else {
00838 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00839 filename, lineno, func, mutex_name);
00840 }
00841 ast_reentrancy_unlock(lt);
00842
00843 if (t->tracking) {
00844 #ifdef HAVE_BKTR
00845 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
00846 #else
00847 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
00848 #endif
00849 }
00850 }
00851
00852 return res;
00853 }
00854
00855 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
00856 const char *cond_name, const char *mutex_name, ast_cond_t *cond,
00857 ast_mutex_t *t, const struct timespec *abstime)
00858 {
00859 int res;
00860 struct ast_lock_track *lt = &t->track;
00861 int canlog = strcmp(filename, "logger.c") & t->tracking;
00862 #ifdef HAVE_BKTR
00863 struct ast_bt *bt = NULL;
00864 #endif
00865
00866 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00867 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00868 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00869 filename, lineno, func, mutex_name);
00870 res = __ast_pthread_mutex_init(t->tracking, filename, lineno, func, mutex_name, t);
00871 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00872 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized and unable to initialize.\n",
00873 filename, lineno, func, mutex_name);
00874 }
00875 return res;
00876 }
00877 #endif
00878
00879 ast_reentrancy_lock(lt);
00880 if (lt->reentrancy && (lt->thread[lt->reentrancy-1] != pthread_self())) {
00881 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00882 filename, lineno, func, mutex_name);
00883 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00884 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1], lt->func[lt->reentrancy-1], mutex_name);
00885 #ifdef HAVE_BKTR
00886 __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
00887 #endif
00888 DO_THREAD_CRASH;
00889 }
00890
00891 if (--lt->reentrancy < 0) {
00892 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00893 filename, lineno, func, mutex_name);
00894 lt->reentrancy = 0;
00895 }
00896
00897 if (lt->reentrancy < AST_MAX_REENTRANCY) {
00898 lt->file[lt->reentrancy] = NULL;
00899 lt->lineno[lt->reentrancy] = 0;
00900 lt->func[lt->reentrancy] = NULL;
00901 lt->thread[lt->reentrancy] = 0;
00902 }
00903 #ifdef HAVE_BKTR
00904 if (lt->reentrancy) {
00905 bt = <->backtrace[lt->reentrancy - 1];
00906 }
00907 #endif
00908 ast_reentrancy_unlock(lt);
00909
00910 if (t->tracking) {
00911 #ifdef HAVE_BKTR
00912 ast_remove_lock_info(t, bt);
00913 #else
00914 ast_remove_lock_info(t);
00915 #endif
00916 }
00917
00918 if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
00919 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
00920 filename, lineno, func, strerror(res));
00921 DO_THREAD_CRASH;
00922 } else {
00923 ast_reentrancy_lock(lt);
00924 if (lt->reentrancy < AST_MAX_REENTRANCY) {
00925 lt->file[lt->reentrancy] = filename;
00926 lt->lineno[lt->reentrancy] = lineno;
00927 lt->func[lt->reentrancy] = func;
00928 lt->thread[lt->reentrancy] = pthread_self();
00929 #ifdef HAVE_BKTR
00930 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
00931 bt = <->backtrace[lt->reentrancy];
00932 #endif
00933 lt->reentrancy++;
00934 } else {
00935 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00936 filename, lineno, func, mutex_name);
00937 }
00938 ast_reentrancy_unlock(lt);
00939
00940 if (t->tracking) {
00941 #ifdef HAVE_BKTR
00942 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
00943 #else
00944 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t);
00945 #endif
00946 }
00947 }
00948
00949 return res;
00950 }
00951
00952 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00953 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00954 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00955 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00956 #define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
00957 #define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00958 #define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00959 #define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00960 #define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
00961 #define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
00962
00963 struct ast_rwlock_info {
00964
00965 struct ast_lock_track track;
00966 unsigned int tracking:1;
00967 pthread_rwlock_t lock;
00968 };
00969
00970 typedef struct ast_rwlock_info ast_rwlock_t;
00971
00972
00973
00974
00975
00976
00977 #define ast_rwlock_init(rwlock) __ast_rwlock_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
00978
00979
00980
00981
00982
00983
00984 #define ast_rwlock_init_notracking(rwlock) __ast_rwlock_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
00985
00986 #define ast_rwlock_destroy(rwlock) __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
00987 #define ast_rwlock_unlock(a) _ast_rwlock_unlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00988 #define ast_rwlock_rdlock(a) _ast_rwlock_rdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00989 #define ast_rwlock_wrlock(a) _ast_rwlock_wrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00990 #define ast_rwlock_tryrdlock(a) _ast_rwlock_tryrdlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00991 #define ast_rwlock_trywrlock(a) _ast_rwlock_trywrlock(a, # a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
00992
00993
00994 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
00995 #define __AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
00996 #else
00997 #define __AST_RWLOCK_INIT_VALUE {0}
00998 #endif
00999
01000 #define AST_RWLOCK_INIT_VALUE \
01001 { AST_LOCK_TRACK_INIT_VALUE, 1, __AST_RWLOCK_INIT_VALUE }
01002 #define AST_RWLOCK_INIT_VALUE_NOTRACKING \
01003 { AST_LOCK_TRACK_INIT_VALUE, 0, __AST_RWLOCK_INIT_VALUE }
01004
01005 static inline int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
01006 {
01007 int res;
01008 struct ast_lock_track *lt= &t->track;
01009 pthread_rwlockattr_t attr;
01010
01011 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01012 int canlog = strcmp(filename, "logger.c") & t->tracking;
01013
01014 if (t->lock != ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01015 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
01016 filename, lineno, func, rwlock_name);
01017 return 0;
01018 }
01019 #endif
01020
01021 ast_reentrancy_init(lt);
01022 t->tracking = tracking;
01023 pthread_rwlockattr_init(&attr);
01024
01025 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
01026 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
01027 #endif
01028
01029 res = pthread_rwlock_init(&t->lock, &attr);
01030 pthread_rwlockattr_destroy(&attr);
01031 return res;
01032 }
01033
01034 static inline int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
01035 {
01036 int res;
01037 struct ast_lock_track *lt = &t->track;
01038 int canlog = strcmp(filename, "logger.c") & t->tracking;
01039
01040 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01041 if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01042 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
01043 filename, lineno, func, rwlock_name);
01044 return 0;
01045 }
01046 #endif
01047
01048 if ((res = pthread_rwlock_destroy(&t->lock))) {
01049 __ast_mutex_logger("%s line %d (%s): Error destroying rwlock %s: %s\n",
01050 filename, lineno, func, rwlock_name, strerror(res));
01051 }
01052 ast_reentrancy_lock(lt);
01053 lt->file[0] = filename;
01054 lt->lineno[0] = lineno;
01055 lt->func[0] = func;
01056 lt->reentrancy = 0;
01057 lt->thread[0] = 0;
01058 #ifdef HAVE_BKTR
01059 memset(<->backtrace[0], 0, sizeof(lt->backtrace[0]));
01060 #endif
01061 ast_reentrancy_unlock(lt);
01062 delete_reentrancy_cs(lt);
01063
01064 return res;
01065 }
01066
01067 static inline int _ast_rwlock_unlock(ast_rwlock_t *t, const char *name,
01068 const char *filename, int line, const char *func)
01069 {
01070 int res;
01071 struct ast_lock_track *lt = &t->track;
01072 int canlog = strcmp(filename, "logger.c") & t->tracking;
01073 #ifdef HAVE_BKTR
01074 struct ast_bt *bt = NULL;
01075 #endif
01076 int lock_found = 0;
01077
01078
01079 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01080 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01081 __ast_mutex_logger("%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
01082 filename, line, func, name);
01083 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01084 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01085 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01086 filename, line, func, name);
01087 }
01088 return res;
01089 }
01090 #endif
01091
01092 ast_reentrancy_lock(lt);
01093 if (lt->reentrancy) {
01094 int i;
01095 pthread_t self = pthread_self();
01096 for (i = lt->reentrancy - 1; i >= 0; --i) {
01097 if (lt->thread[i] == self) {
01098 lock_found = 1;
01099 if (i != lt->reentrancy - 1) {
01100 lt->file[i] = lt->file[lt->reentrancy - 1];
01101 lt->lineno[i] = lt->lineno[lt->reentrancy - 1];
01102 lt->func[i] = lt->func[lt->reentrancy - 1];
01103 lt->thread[i] = lt->thread[lt->reentrancy - 1];
01104 }
01105 #ifdef HAVE_BKTR
01106 bt = <->backtrace[i];
01107 #endif
01108 lt->file[lt->reentrancy - 1] = NULL;
01109 lt->lineno[lt->reentrancy - 1] = 0;
01110 lt->func[lt->reentrancy - 1] = NULL;
01111 lt->thread[lt->reentrancy - 1] = AST_PTHREADT_NULL;
01112 break;
01113 }
01114 }
01115 }
01116
01117 if (lock_found && --lt->reentrancy < 0) {
01118 __ast_mutex_logger("%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
01119 filename, line, func, name);
01120 lt->reentrancy = 0;
01121 }
01122
01123 ast_reentrancy_unlock(lt);
01124
01125 if (t->tracking) {
01126 #ifdef HAVE_BKTR
01127 ast_remove_lock_info(t, bt);
01128 #else
01129 ast_remove_lock_info(t);
01130 #endif
01131 }
01132
01133 if ((res = pthread_rwlock_unlock(&t->lock))) {
01134 __ast_mutex_logger("%s line %d (%s): Error releasing rwlock: %s\n",
01135 filename, line, func, strerror(res));
01136 DO_THREAD_CRASH;
01137 }
01138
01139 return res;
01140 }
01141
01142 static inline int _ast_rwlock_rdlock(ast_rwlock_t *t, const char *name,
01143 const char *filename, int line, const char *func)
01144 {
01145 int res;
01146 struct ast_lock_track *lt = &t->track;
01147 int canlog = strcmp(filename, "logger.c") & t->tracking;
01148 #ifdef HAVE_BKTR
01149 struct ast_bt *bt = NULL;
01150 #endif
01151
01152 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01153 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01154
01155
01156
01157
01158 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01159 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01160 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01161 filename, line, func, name);
01162 return res;
01163 }
01164 }
01165 #endif
01166
01167 if (t->tracking) {
01168 #ifdef HAVE_BKTR
01169 ast_reentrancy_lock(lt);
01170 if (lt->reentrancy != AST_MAX_REENTRANCY) {
01171 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
01172 bt = <->backtrace[lt->reentrancy];
01173 }
01174 ast_reentrancy_unlock(lt);
01175 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
01176 #else
01177 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
01178 #endif
01179 }
01180
01181 #ifdef DETECT_DEADLOCKS
01182 {
01183 time_t seconds = time(NULL);
01184 time_t wait_time, reported_wait = 0;
01185 do {
01186 res = pthread_rwlock_tryrdlock(&t->lock);
01187 if (res == EBUSY) {
01188 wait_time = time(NULL) - seconds;
01189 if (wait_time > reported_wait && (wait_time % 5) == 0) {
01190 __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
01191 filename, line, func, (int)wait_time, name);
01192 ast_reentrancy_lock(lt);
01193 #ifdef HAVE_BKTR
01194 __dump_backtrace(<->backtrace[lt->reentrancy], canlog);
01195 #endif
01196 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
01197 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
01198 lt->func[lt->reentrancy-1], name);
01199 #ifdef HAVE_BKTR
01200 __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
01201 #endif
01202 ast_reentrancy_unlock(lt);
01203 reported_wait = wait_time;
01204 }
01205 usleep(200);
01206 }
01207 } while (res == EBUSY);
01208 }
01209 #else
01210 res = pthread_rwlock_rdlock(&t->lock);
01211 #endif
01212
01213 if (!res) {
01214 ast_reentrancy_lock(lt);
01215 if (lt->reentrancy < AST_MAX_REENTRANCY) {
01216 lt->file[lt->reentrancy] = filename;
01217 lt->lineno[lt->reentrancy] = line;
01218 lt->func[lt->reentrancy] = func;
01219 lt->thread[lt->reentrancy] = pthread_self();
01220 lt->reentrancy++;
01221 }
01222 ast_reentrancy_unlock(lt);
01223 if (t->tracking) {
01224 ast_mark_lock_acquired(t);
01225 }
01226 } else {
01227 #ifdef HAVE_BKTR
01228 if (lt->reentrancy) {
01229 ast_reentrancy_lock(lt);
01230 bt = <->backtrace[lt->reentrancy-1];
01231 ast_reentrancy_unlock(lt);
01232 } else {
01233 bt = NULL;
01234 }
01235 if (t->tracking) {
01236 ast_remove_lock_info(t, bt);
01237 }
01238 #else
01239 if (t->tracking) {
01240 ast_remove_lock_info(t);
01241 }
01242 #endif
01243 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
01244 filename, line, func, strerror(res));
01245 DO_THREAD_CRASH;
01246 }
01247 return res;
01248 }
01249
01250 static inline int _ast_rwlock_wrlock(ast_rwlock_t *t, const char *name,
01251 const char *filename, int line, const char *func)
01252 {
01253 int res;
01254 struct ast_lock_track *lt = &t->track;
01255 int canlog = strcmp(filename, "logger.c") & t->tracking;
01256 #ifdef HAVE_BKTR
01257 struct ast_bt *bt = NULL;
01258 #endif
01259
01260 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01261 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01262
01263
01264
01265
01266 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01267 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01268 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01269 filename, line, func, name);
01270 return res;
01271 }
01272 }
01273 #endif
01274
01275 if (t->tracking) {
01276 #ifdef HAVE_BKTR
01277 ast_reentrancy_lock(lt);
01278 if (lt->reentrancy != AST_MAX_REENTRANCY) {
01279 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
01280 bt = <->backtrace[lt->reentrancy];
01281 }
01282 ast_reentrancy_unlock(lt);
01283 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
01284 #else
01285 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
01286 #endif
01287 }
01288 #ifdef DETECT_DEADLOCKS
01289 {
01290 time_t seconds = time(NULL);
01291 time_t wait_time, reported_wait = 0;
01292 do {
01293 res = pthread_rwlock_trywrlock(&t->lock);
01294 if (res == EBUSY) {
01295 wait_time = time(NULL) - seconds;
01296 if (wait_time > reported_wait && (wait_time % 5) == 0) {
01297 __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
01298 filename, line, func, (int)wait_time, name);
01299 ast_reentrancy_lock(lt);
01300 #ifdef HAVE_BKTR
01301 __dump_backtrace(<->backtrace[lt->reentrancy], canlog);
01302 #endif
01303 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
01304 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
01305 lt->func[lt->reentrancy-1], name);
01306 #ifdef HAVE_BKTR
01307 __dump_backtrace(<->backtrace[lt->reentrancy-1], canlog);
01308 #endif
01309 ast_reentrancy_unlock(lt);
01310 reported_wait = wait_time;
01311 }
01312 usleep(200);
01313 }
01314 } while (res == EBUSY);
01315 }
01316 #else
01317 res = pthread_rwlock_wrlock(&t->lock);
01318 #endif
01319
01320 if (!res) {
01321 ast_reentrancy_lock(lt);
01322 if (lt->reentrancy < AST_MAX_REENTRANCY) {
01323 lt->file[lt->reentrancy] = filename;
01324 lt->lineno[lt->reentrancy] = line;
01325 lt->func[lt->reentrancy] = func;
01326 lt->thread[lt->reentrancy] = pthread_self();
01327 lt->reentrancy++;
01328 }
01329 ast_reentrancy_unlock(lt);
01330 if (t->tracking) {
01331 ast_mark_lock_acquired(t);
01332 }
01333 } else {
01334 #ifdef HAVE_BKTR
01335 if (lt->reentrancy) {
01336 ast_reentrancy_lock(lt);
01337 bt = <->backtrace[lt->reentrancy-1];
01338 ast_reentrancy_unlock(lt);
01339 } else {
01340 bt = NULL;
01341 }
01342 if (t->tracking) {
01343 ast_remove_lock_info(t, bt);
01344 }
01345 #else
01346 if (t->tracking) {
01347 ast_remove_lock_info(t);
01348 }
01349 #endif
01350 __ast_mutex_logger("%s line %d (%s): Error obtaining write lock: %s\n",
01351 filename, line, func, strerror(res));
01352 DO_THREAD_CRASH;
01353 }
01354 return res;
01355 }
01356
01357 #define ast_rwlock_timedrdlock(a, b) \
01358 _ast_rwlock_timedrdlock(a, # a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01359
01360 static inline int _ast_rwlock_timedrdlock(ast_rwlock_t *t, const char *name,
01361 const struct timespec *abs_timeout, const char *filename, int line, const char *func)
01362 {
01363 int res;
01364 struct ast_lock_track *lt = &t->track;
01365 int canlog = strcmp(filename, "logger.c") & t->tracking;
01366 #ifdef HAVE_BKTR
01367 struct ast_bt *bt = NULL;
01368 #endif
01369
01370 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01371 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01372
01373
01374
01375
01376 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01377 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01378 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01379 filename, line, func, name);
01380 return res;
01381 }
01382 }
01383 #endif
01384
01385 if (t->tracking) {
01386 #ifdef HAVE_BKTR
01387 ast_reentrancy_lock(lt);
01388 if (lt->reentrancy != AST_MAX_REENTRANCY) {
01389 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
01390 bt = <->backtrace[lt->reentrancy];
01391 }
01392 ast_reentrancy_unlock(lt);
01393 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
01394 #else
01395 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
01396 #endif
01397 }
01398 res = pthread_rwlock_timedrdlock(&t->lock, abs_timeout);
01399 if (!res) {
01400 ast_reentrancy_lock(lt);
01401 if (lt->reentrancy < AST_MAX_REENTRANCY) {
01402 lt->file[lt->reentrancy] = filename;
01403 lt->lineno[lt->reentrancy] = line;
01404 lt->func[lt->reentrancy] = func;
01405 lt->thread[lt->reentrancy] = pthread_self();
01406 lt->reentrancy++;
01407 }
01408 ast_reentrancy_unlock(lt);
01409 if (t->tracking) {
01410 ast_mark_lock_acquired(t);
01411 }
01412 } else {
01413 #ifdef HAVE_BKTR
01414 if (lt->reentrancy) {
01415 ast_reentrancy_lock(lt);
01416 bt = <->backtrace[lt->reentrancy-1];
01417 ast_reentrancy_unlock(lt);
01418 } else {
01419 bt = NULL;
01420 }
01421 if (t->tracking) {
01422 ast_remove_lock_info(t, bt);
01423 }
01424 #else
01425 if (t->tracking) {
01426 ast_remove_lock_info(t);
01427 }
01428 #endif
01429 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
01430 filename, line, func, strerror(res));
01431 DO_THREAD_CRASH;
01432 }
01433 return res;
01434 }
01435
01436 #define ast_rwlock_timedwrlock(a, b) \
01437 _ast_rwlock_timedwrlock(a, # a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01438
01439 static inline int _ast_rwlock_timedwrlock(ast_rwlock_t *t, const char *name,
01440 const struct timespec *abs_timeout, const char *filename, int line, const char *func)
01441 {
01442 int res;
01443 struct ast_lock_track *lt = &t->track;
01444 int canlog = strcmp(filename, "logger.c") & t->tracking;
01445 #ifdef HAVE_BKTR
01446 struct ast_bt *bt = NULL;
01447 #endif
01448
01449 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01450 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01451
01452
01453
01454
01455 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01456 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01457 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01458 filename, line, func, name);
01459 return res;
01460 }
01461 }
01462 #endif
01463
01464 if (t->tracking) {
01465 #ifdef HAVE_BKTR
01466 ast_reentrancy_lock(lt);
01467 if (lt->reentrancy != AST_MAX_REENTRANCY) {
01468 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
01469 bt = <->backtrace[lt->reentrancy];
01470 }
01471 ast_reentrancy_unlock(lt);
01472 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
01473 #else
01474 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
01475 #endif
01476 }
01477 res = pthread_rwlock_timedwrlock(&t->lock, abs_timeout);
01478 if (!res) {
01479 ast_reentrancy_lock(lt);
01480 if (lt->reentrancy < AST_MAX_REENTRANCY) {
01481 lt->file[lt->reentrancy] = filename;
01482 lt->lineno[lt->reentrancy] = line;
01483 lt->func[lt->reentrancy] = func;
01484 lt->thread[lt->reentrancy] = pthread_self();
01485 lt->reentrancy++;
01486 }
01487 ast_reentrancy_unlock(lt);
01488 if (t->tracking) {
01489 ast_mark_lock_acquired(t);
01490 }
01491 } else {
01492 #ifdef HAVE_BKTR
01493 if (lt->reentrancy) {
01494 ast_reentrancy_lock(lt);
01495 bt = <->backtrace[lt->reentrancy-1];
01496 ast_reentrancy_unlock(lt);
01497 } else {
01498 bt = NULL;
01499 }
01500 if (t->tracking) {
01501 ast_remove_lock_info(t, bt);
01502 }
01503 #else
01504 if (t->tracking) {
01505 ast_remove_lock_info(t);
01506 }
01507 #endif
01508 __ast_mutex_logger("%s line %d (%s): Error obtaining read lock: %s\n",
01509 filename, line, func, strerror(res));
01510 DO_THREAD_CRASH;
01511 }
01512 return res;
01513 }
01514
01515 static inline int _ast_rwlock_tryrdlock(ast_rwlock_t *t, const char *name,
01516 const char *filename, int line, const char *func)
01517 {
01518 int res;
01519 struct ast_lock_track *lt = &t->track;
01520 #ifdef HAVE_BKTR
01521 struct ast_bt *bt = NULL;
01522 #endif
01523
01524
01525 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01526 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01527
01528
01529
01530
01531 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01532 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01533 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01534 filename, line, func, name);
01535 return res;
01536 }
01537 }
01538 #endif
01539
01540 if (t->tracking) {
01541 #ifdef HAVE_BKTR
01542 ast_reentrancy_lock(lt);
01543 if (lt->reentrancy != AST_MAX_REENTRANCY) {
01544 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
01545 bt = <->backtrace[lt->reentrancy];
01546 }
01547 ast_reentrancy_unlock(lt);
01548 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
01549 #else
01550 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t);
01551 #endif
01552 }
01553
01554 if (!(res = pthread_rwlock_tryrdlock(&t->lock))) {
01555 ast_reentrancy_lock(lt);
01556 if (lt->reentrancy < AST_MAX_REENTRANCY) {
01557 lt->file[lt->reentrancy] = filename;
01558 lt->lineno[lt->reentrancy] = line;
01559 lt->func[lt->reentrancy] = func;
01560 lt->thread[lt->reentrancy] = pthread_self();
01561 lt->reentrancy++;
01562 }
01563 ast_reentrancy_unlock(lt);
01564 if (t->tracking) {
01565 ast_mark_lock_acquired(t);
01566 }
01567 } else if (t->tracking) {
01568 ast_mark_lock_failed(t);
01569 }
01570 return res;
01571 }
01572
01573 static inline int _ast_rwlock_trywrlock(ast_rwlock_t *t, const char *name,
01574 const char *filename, int line, const char *func)
01575 {
01576 int res;
01577 struct ast_lock_track *lt= &t->track;
01578 #ifdef HAVE_BKTR
01579 struct ast_bt *bt = NULL;
01580 #endif
01581
01582
01583 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01584 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01585
01586
01587
01588
01589 res = __ast_rwlock_init(t->tracking, filename, line, func, name, t);
01590 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
01591 __ast_mutex_logger("%s line %d (%s): Error: rwlock '%s' is uninitialized and unable to initialize.\n",
01592 filename, line, func, name);
01593 return res;
01594 }
01595 }
01596 #endif
01597
01598 if (t->tracking) {
01599 #ifdef HAVE_BKTR
01600 ast_reentrancy_lock(lt);
01601 if (lt->reentrancy != AST_MAX_REENTRANCY) {
01602 ast_bt_get_addresses(<->backtrace[lt->reentrancy]);
01603 bt = <->backtrace[lt->reentrancy];
01604 }
01605 ast_reentrancy_unlock(lt);
01606 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
01607 #else
01608 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t);
01609 #endif
01610 }
01611
01612 if (!(res = pthread_rwlock_trywrlock(&t->lock))) {
01613 ast_reentrancy_lock(lt);
01614 if (lt->reentrancy < AST_MAX_REENTRANCY) {
01615 lt->file[lt->reentrancy] = filename;
01616 lt->lineno[lt->reentrancy] = line;
01617 lt->func[lt->reentrancy] = func;
01618 lt->thread[lt->reentrancy] = pthread_self();
01619 lt->reentrancy++;
01620 }
01621 ast_reentrancy_unlock(lt);
01622 if (t->tracking) {
01623 ast_mark_lock_acquired(t);
01624 }
01625 } else if (t->tracking) {
01626 ast_mark_lock_failed(t);
01627 }
01628 return res;
01629 }
01630
01631 #else
01632
01633 #define CHANNEL_DEADLOCK_AVOIDANCE(chan) \
01634 ast_channel_unlock(chan); \
01635 usleep(1); \
01636 ast_channel_lock(chan);
01637
01638 #define DEADLOCK_AVOIDANCE(lock) \
01639 ast_mutex_unlock(lock); \
01640 usleep(1); \
01641 ast_mutex_lock(lock);
01642
01643 #define DLA_UNLOCK(lock) ast_mutex_unlock(lock)
01644
01645 #define DLA_LOCK(lock) ast_mutex_lock(lock)
01646
01647 typedef pthread_mutex_t ast_mutex_t;
01648
01649 #define AST_MUTEX_INIT_VALUE ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
01650 #define AST_MUTEX_INIT_VALUE_NOTRACKING ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
01651
01652 #define ast_mutex_init_notracking(m) ast_mutex_init(m)
01653
01654 static inline int ast_mutex_init(ast_mutex_t *pmutex)
01655 {
01656 int res;
01657 pthread_mutexattr_t attr;
01658
01659 pthread_mutexattr_init(&attr);
01660 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
01661
01662 res = pthread_mutex_init(pmutex, &attr);
01663 pthread_mutexattr_destroy(&attr);
01664 return res;
01665 }
01666
01667 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
01668
01669 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
01670 {
01671 return pthread_mutex_unlock(pmutex);
01672 }
01673
01674 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
01675 {
01676 return pthread_mutex_destroy(pmutex);
01677 }
01678
01679 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
01680 {
01681 __MTX_PROF(pmutex);
01682 }
01683
01684 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
01685 {
01686 return pthread_mutex_trylock(pmutex);
01687 }
01688
01689 typedef pthread_cond_t ast_cond_t;
01690
01691 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
01692 {
01693 return pthread_cond_init(cond, cond_attr);
01694 }
01695
01696 static inline int ast_cond_signal(ast_cond_t *cond)
01697 {
01698 return pthread_cond_signal(cond);
01699 }
01700
01701 static inline int ast_cond_broadcast(ast_cond_t *cond)
01702 {
01703 return pthread_cond_broadcast(cond);
01704 }
01705
01706 static inline int ast_cond_destroy(ast_cond_t *cond)
01707 {
01708 return pthread_cond_destroy(cond);
01709 }
01710
01711 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
01712 {
01713 return pthread_cond_wait(cond, t);
01714 }
01715
01716 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
01717 {
01718 return pthread_cond_timedwait(cond, t, abstime);
01719 }
01720
01721
01722 typedef pthread_rwlock_t ast_rwlock_t;
01723
01724 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
01725 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
01726 #else
01727 #define AST_RWLOCK_INIT_VALUE { 0 }
01728 #endif
01729
01730 #define ast_rwlock_init_notracking(a) ast_rwlock_init(a)
01731
01732 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
01733 {
01734 int res;
01735 pthread_rwlockattr_t attr;
01736
01737 pthread_rwlockattr_init(&attr);
01738
01739 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
01740 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
01741 #endif
01742
01743 res = pthread_rwlock_init(prwlock, &attr);
01744 pthread_rwlockattr_destroy(&attr);
01745 return res;
01746 }
01747
01748 static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
01749 {
01750 return pthread_rwlock_destroy(prwlock);
01751 }
01752
01753 static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
01754 {
01755 return pthread_rwlock_unlock(prwlock);
01756 }
01757
01758 static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
01759 {
01760 return pthread_rwlock_rdlock(prwlock);
01761 }
01762
01763 static inline int ast_rwlock_timedrdlock(ast_rwlock_t *prwlock, const struct timespec *abs_timeout)
01764 {
01765 return pthread_rwlock_timedrdlock(prwlock, abs_timeout);
01766 }
01767
01768 static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
01769 {
01770 return pthread_rwlock_tryrdlock(prwlock);
01771 }
01772
01773 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
01774 {
01775 return pthread_rwlock_wrlock(prwlock);
01776 }
01777
01778 static inline int ast_rwlock_timedwrlock(ast_rwlock_t *prwlock, const struct timespec *abs_timeout)
01779 {
01780 return pthread_rwlock_timedwrlock(prwlock, abs_timeout);
01781 }
01782
01783 static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
01784 {
01785 return pthread_rwlock_trywrlock(prwlock);
01786 }
01787
01788 #endif
01789
01790 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
01791
01792
01793
01794
01795 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track) \
01796 scope ast_mutex_t mutex = init_val; \
01797 static void __attribute__((constructor)) init_##mutex(void) \
01798 { \
01799 if (track) \
01800 ast_mutex_init(&mutex); \
01801 else \
01802 ast_mutex_init_notracking(&mutex); \
01803 } \
01804 \
01805 static void __attribute__((destructor)) fini_##mutex(void) \
01806 { \
01807 ast_mutex_destroy(&mutex); \
01808 }
01809 #else
01810
01811 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track) scope ast_mutex_t mutex = init_val
01812 #endif
01813
01814 #ifndef __CYGWIN__
01815 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
01816 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
01817 #endif
01818 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
01819 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
01820 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
01821 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
01822 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
01823 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
01824 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
01825 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
01826 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
01827 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
01828 #define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
01829
01830 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
01831 #define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
01832
01833 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
01834
01835 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
01836
01837 #ifndef __linux__
01838 #define pthread_create __use_ast_pthread_create_instead__
01839 #endif
01840
01841
01842
01843 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
01844 #define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) \
01845 scope ast_rwlock_t rwlock = init_val; \
01846 static void __attribute__((constructor)) init_##rwlock(void) \
01847 { \
01848 if (track) \
01849 ast_rwlock_init(&rwlock); \
01850 else \
01851 ast_rwlock_init_notracking(&rwlock); \
01852 } \
01853 static void __attribute__((destructor)) fini_##rwlock(void) \
01854 { \
01855 ast_rwlock_destroy(&rwlock); \
01856 }
01857 #else
01858 #define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) \
01859 scope ast_rwlock_t rwlock = init_val
01860 #endif
01861
01862 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE, 1)
01863 #define AST_RWLOCK_DEFINE_STATIC_NOTRACKING(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE_NOTRACKING, 0)
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
01876
01877 #include "asterisk/inline_api.h"
01878
01879 #if defined(HAVE_OSX_ATOMICS)
01880 #include "libkern/OSAtomic.h"
01881 #endif
01882
01883
01884
01885
01886
01887
01888 #if defined(HAVE_GCC_ATOMICS)
01889 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01890 {
01891 return __sync_fetch_and_add(p, v);
01892 })
01893 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
01894 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01895 {
01896 return OSAtomicAdd32(v, (int32_t *) p) - v;
01897 })
01898 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
01899 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01900 {
01901 return OSAtomicAdd64(v, (int64_t *) p) - v;
01902 #elif defined (__i386__) || defined(__x86_64__)
01903 #ifdef sun
01904 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01905 {
01906 __asm __volatile (
01907 " lock; xaddl %0, %1 ; "
01908 : "+r" (v),
01909 "=m" (*p)
01910 : "m" (*p));
01911 return (v);
01912 })
01913 #else
01914 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01915 {
01916 __asm __volatile (
01917 " lock xaddl %0, %1 ; "
01918 : "+r" (v),
01919 "=m" (*p)
01920 : "m" (*p));
01921 return (v);
01922 })
01923 #endif
01924 #else
01925 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
01926 {
01927 return ast_atomic_fetchadd_int_slow(p, v);
01928 })
01929 #endif
01930
01931
01932
01933
01934 #if defined(HAVE_GCC_ATOMICS)
01935 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
01936 {
01937 return __sync_sub_and_fetch(p, 1) == 0;
01938 })
01939 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
01940 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
01941 {
01942 return OSAtomicAdd32( -1, (int32_t *) p) == 0;
01943 })
01944 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
01945 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
01946 {
01947 return OSAtomicAdd64( -1, (int64_t *) p) == 0;
01948 #else
01949 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
01950 {
01951 int a = ast_atomic_fetchadd_int(p, -1);
01952 return a == 1;
01953 })
01954 #endif
01955
01956 #ifndef DEBUG_CHANNEL_LOCKS
01957
01958
01959 #define ast_channel_lock(x) ast_mutex_lock(&x->lock_dont_use)
01960
01961
01962 #define ast_channel_unlock(x) ast_mutex_unlock(&x->lock_dont_use)
01963
01964
01965 #define ast_channel_trylock(x) ast_mutex_trylock(&x->lock_dont_use)
01966 #else
01967
01968 #define ast_channel_lock(a) __ast_channel_lock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01969
01970
01971 int __ast_channel_lock(struct ast_channel *chan, const char *file, int lineno, const char *func);
01972
01973 #define ast_channel_unlock(a) __ast_channel_unlock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01974
01975
01976
01977 int __ast_channel_unlock(struct ast_channel *chan, const char *file, int lineno, const char *func);
01978
01979 #define ast_channel_trylock(a) __ast_channel_trylock(a, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01980
01981
01982 int __ast_channel_trylock(struct ast_channel *chan, const char *file, int lineno, const char *func);
01983 #endif
01984
01985 #endif