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