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