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