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
00062 #include "asterisk/logger.h"
00063 #include "asterisk/compiler.h"
00064
00065 #define AST_PTHREADT_NULL (pthread_t) -1
00066 #define AST_PTHREADT_STOP (pthread_t) -2
00067
00068 #if (defined(SOLARIS) || defined(BSD))
00069 #define AST_MUTEX_INIT_W_CONSTRUCTORS
00070 #endif
00071
00072
00073
00074 #if defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(HAVE_PTHREAD_MUTEX_RECURSIVE_NP)
00075 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00076 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP
00077 #else
00078 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
00079 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE
00080 #endif
00081
00082 #ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
00083 #define __AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
00084 #else
00085 #define __AST_RWLOCK_INIT_VALUE {0}
00086 #endif
00087
00088 #ifdef HAVE_BKTR
00089 #define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
00090 #else
00091 #define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
00092 #endif
00093
00094 #define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, NULL, 1 }
00095 #define AST_MUTEX_INIT_VALUE_NOTRACKING { PTHREAD_MUTEX_INIT_VALUE, NULL, 0 }
00096
00097 #define AST_RWLOCK_INIT_VALUE { __AST_RWLOCK_INIT_VALUE, NULL, 1 }
00098 #define AST_RWLOCK_INIT_VALUE_NOTRACKING { __AST_RWLOCK_INIT_VALUE, NULL, 0 }
00099
00100 #define AST_MAX_REENTRANCY 10
00101
00102 struct ast_channel;
00103
00104 struct ast_lock_track {
00105 const char *file[AST_MAX_REENTRANCY];
00106 int lineno[AST_MAX_REENTRANCY];
00107 int reentrancy;
00108 const char *func[AST_MAX_REENTRANCY];
00109 pthread_t thread[AST_MAX_REENTRANCY];
00110 #ifdef HAVE_BKTR
00111 struct ast_bt backtrace[AST_MAX_REENTRANCY];
00112 #endif
00113 pthread_mutex_t reentr_mutex;
00114 };
00115
00116
00117
00118
00119
00120
00121 struct ast_mutex_info {
00122 pthread_mutex_t mutex;
00123
00124 struct ast_lock_track *track;
00125 unsigned int tracking:1;
00126 };
00127
00128
00129
00130
00131
00132
00133 struct ast_rwlock_info {
00134 pthread_rwlock_t lock;
00135
00136 struct ast_lock_track *track;
00137 unsigned int tracking:1;
00138 };
00139
00140 typedef struct ast_mutex_info ast_mutex_t;
00141
00142 typedef struct ast_rwlock_info ast_rwlock_t;
00143
00144 typedef pthread_cond_t ast_cond_t;
00145
00146 int __ast_pthread_mutex_init(int tracking, const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t);
00147 int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t);
00148 int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func, const char* mutex_name, ast_mutex_t *t);
00149 int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, const char* mutex_name, ast_mutex_t *t);
00150 int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t);
00151
00152 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
00153 #define ast_mutex_init_notracking(pmutex) __ast_pthread_mutex_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
00154 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00155 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00156 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00157 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00158
00159
00160 int __ast_cond_init(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr);
00161 int __ast_cond_signal(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond);
00162 int __ast_cond_broadcast(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond);
00163 int __ast_cond_destroy(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond);
00164 int __ast_cond_wait(const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t);
00165 int __ast_cond_timedwait(const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime);
00166
00167 #define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
00168 #define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00169 #define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00170 #define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00171 #define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
00172 #define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
00173
00174
00175 int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t);
00176 int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t);
00177 int __ast_rwlock_unlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
00178 int __ast_rwlock_rdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
00179 int __ast_rwlock_wrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
00180 int __ast_rwlock_timedrdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout);
00181 int __ast_rwlock_timedwrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout);
00182 int __ast_rwlock_tryrdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
00183 int __ast_rwlock_trywrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
00184
00185
00186
00187
00188
00189
00190 #define ast_rwlock_init(rwlock) __ast_rwlock_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
00191
00192
00193
00194
00195
00196
00197 #define ast_rwlock_init_notracking(rwlock) __ast_rwlock_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
00198
00199 #define ast_rwlock_destroy(rwlock) __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
00200 #define ast_rwlock_unlock(a) __ast_rwlock_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
00201 #define ast_rwlock_rdlock(a) __ast_rwlock_rdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
00202 #define ast_rwlock_wrlock(a) __ast_rwlock_wrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
00203 #define ast_rwlock_tryrdlock(a) __ast_rwlock_tryrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
00204 #define ast_rwlock_trywrlock(a) __ast_rwlock_trywrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
00205 #define ast_rwlock_timedrdlock(a, b) __ast_rwlock_timedrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)
00206 #define ast_rwlock_timedwrlock(a, b) __ast_rwlock_timedwrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)
00207
00208 #define ROFFSET ((lt->reentrancy > 0) ? (lt->reentrancy-1) : 0)
00209
00210 #ifdef DEBUG_THREADS
00211
00212 #define __ast_mutex_logger(...) do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
00213
00214 #ifdef THREAD_CRASH
00215 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
00216 #else
00217 #define DO_THREAD_CRASH do { } while (0)
00218 #endif
00219
00220 #include <errno.h>
00221
00222 enum ast_lock_type {
00223 AST_MUTEX,
00224 AST_RDLOCK,
00225 AST_WRLOCK,
00226 };
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 #if !defined(LOW_MEMORY)
00237 #ifdef HAVE_BKTR
00238 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00239 int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt);
00240 #else
00241 void ast_store_lock_info(enum ast_lock_type type, const char *filename,
00242 int line_num, const char *func, const char *lock_name, void *lock_addr);
00243 #endif
00244
00245 #else
00246
00247 #ifdef HAVE_BKTR
00248 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS,BUD)
00249 #else
00250 #define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
00251 #endif
00252 #endif
00253
00254
00255
00256
00257 #if !defined(LOW_MEMORY)
00258 void ast_mark_lock_acquired(void *lock_addr);
00259 #else
00260 #define ast_mark_lock_acquired(ignore)
00261 #endif
00262
00263
00264
00265
00266 #if !defined(LOW_MEMORY)
00267 void ast_mark_lock_failed(void *lock_addr);
00268 #else
00269 #define ast_mark_lock_failed(ignore)
00270 #endif
00271
00272
00273
00274
00275
00276
00277
00278 #if !defined(LOW_MEMORY)
00279 #ifdef HAVE_BKTR
00280 void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt);
00281 #else
00282 void ast_remove_lock_info(void *lock_addr);
00283 #endif
00284 #else
00285 #ifdef HAVE_BKTR
00286 #define ast_remove_lock_info(ignore,me)
00287 #else
00288 #define ast_remove_lock_info(ignore)
00289 #endif
00290 #endif
00291
00292 #ifdef HAVE_BKTR
00293 static inline void __dump_backtrace(struct ast_bt *bt, int canlog)
00294 {
00295 char **strings;
00296
00297 ssize_t i;
00298
00299 strings = backtrace_symbols(bt->addresses, bt->num_frames);
00300
00301 for (i = 0; i < bt->num_frames; i++)
00302 __ast_mutex_logger("%s\n", strings[i]);
00303
00304 free(strings);
00305 }
00306 #endif
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 void log_show_lock(void *this_lock_addr);
00319
00320
00321
00322
00323
00324
00325
00326 #if !defined(LOW_MEMORY)
00327 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);
00328 #else
00329 #define ast_find_lock_info(a,b,c,d,e,f,g,h) -1
00330 #endif
00331
00332
00333
00334
00335
00336
00337
00338 #define CHANNEL_DEADLOCK_AVOIDANCE(chan) \
00339 do { \
00340 char __filename[80], __func[80], __mutex_name[80]; \
00341 int __lineno; \
00342 int __res = ast_find_lock_info(ao2_object_get_lockaddr(chan), __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
00343 int __res2 = ast_channel_unlock(chan); \
00344 usleep(1); \
00345 if (__res < 0) { \
00346 if (__res2) { \
00347 ast_log(LOG_WARNING, "Could not unlock channel '%s': %s and no lock info found! I will NOT try to relock.\n", #chan, strerror(__res2)); \
00348 } else { \
00349 ast_channel_lock(chan); \
00350 } \
00351 } else { \
00352 if (__res2) { \
00353 ast_log(LOG_WARNING, "Could not unlock channel '%s': %s. {{{Originally locked at %s line %d: (%s) '%s'}}} I will NOT try to relock.\n", #chan, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
00354 } else { \
00355 __ao2_lock(chan, __filename, __func, __lineno, __mutex_name); \
00356 } \
00357 } \
00358 } while (0)
00359
00360 #define DEADLOCK_AVOIDANCE(lock) \
00361 do { \
00362 char __filename[80], __func[80], __mutex_name[80]; \
00363 int __lineno; \
00364 int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
00365 int __res2 = ast_mutex_unlock(lock); \
00366 usleep(1); \
00367 if (__res < 0) { \
00368 if (__res2 == 0) { \
00369 ast_mutex_lock(lock); \
00370 } else { \
00371 ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s and no lock info found! I will NOT try to relock.\n", #lock, strerror(__res2)); \
00372 } \
00373 } else { \
00374 if (__res2 == 0) { \
00375 __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
00376 } else { \
00377 ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s. {{{Originally locked at %s line %d: (%s) '%s'}}} I will NOT try to relock.\n", #lock, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
00378 } \
00379 } \
00380 } while (0)
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 #define DLA_UNLOCK(lock) \
00395 do { \
00396 char __filename[80], __func[80], __mutex_name[80]; \
00397 int __lineno; \
00398 int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
00399 int __res2 = ast_mutex_unlock(lock);
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 #define DLA_LOCK(lock) \
00414 if (__res < 0) { \
00415 if (__res2) { \
00416 ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s and no lock info found! I will NOT try to relock.\n", #lock, strerror(__res2)); \
00417 } else { \
00418 ast_mutex_lock(lock); \
00419 } \
00420 } else { \
00421 if (__res2) { \
00422 ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s. {{{Originally locked at %s line %d: (%s) '%s'}}} I will NOT try to relock.\n", #lock, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
00423 } else { \
00424 __ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
00425 } \
00426 } \
00427 } while (0)
00428
00429 static inline void ast_reentrancy_lock(struct ast_lock_track *lt)
00430 {
00431 int res;
00432 if ((res = pthread_mutex_lock(<->reentr_mutex))) {
00433 fprintf(stderr, "ast_reentrancy_lock failed: '%s' (%d)\n", strerror(res), res);
00434 #if defined(DO_CRASH) || defined(THREAD_CRASH)
00435 abort();
00436 #endif
00437 }
00438 }
00439
00440 static inline void ast_reentrancy_unlock(struct ast_lock_track *lt)
00441 {
00442 int res;
00443 if ((res = pthread_mutex_unlock(<->reentr_mutex))) {
00444 fprintf(stderr, "ast_reentrancy_unlock failed: '%s' (%d)\n", strerror(res), res);
00445 #if defined(DO_CRASH) || defined(THREAD_CRASH)
00446 abort();
00447 #endif
00448 }
00449 }
00450
00451 static inline void ast_reentrancy_init(struct ast_lock_track **plt)
00452 {
00453 int i;
00454 pthread_mutexattr_t reentr_attr;
00455 struct ast_lock_track *lt = *plt;
00456
00457 if (!lt) {
00458 lt = *plt = (struct ast_lock_track *) calloc(1, sizeof(*lt));
00459 }
00460
00461 for (i = 0; i < AST_MAX_REENTRANCY; i++) {
00462 lt->file[i] = NULL;
00463 lt->lineno[i] = 0;
00464 lt->func[i] = NULL;
00465 lt->thread[i] = 0;
00466 #ifdef HAVE_BKTR
00467 memset(<->backtrace[i], 0, sizeof(lt->backtrace[i]));
00468 #endif
00469 }
00470
00471 lt->reentrancy = 0;
00472
00473 pthread_mutexattr_init(&reentr_attr);
00474 pthread_mutexattr_settype(&reentr_attr, AST_MUTEX_KIND);
00475 pthread_mutex_init(<->reentr_mutex, &reentr_attr);
00476 pthread_mutexattr_destroy(&reentr_attr);
00477 }
00478
00479 static inline void delete_reentrancy_cs(struct ast_lock_track **plt)
00480 {
00481 struct ast_lock_track *lt;
00482 if (*plt) {
00483 lt = *plt;
00484 pthread_mutex_destroy(<->reentr_mutex);
00485 free(lt);
00486 *plt = NULL;
00487 }
00488 }
00489
00490 #else
00491
00492 #define CHANNEL_DEADLOCK_AVOIDANCE(chan) \
00493 ast_channel_unlock(chan); \
00494 usleep(1); \
00495 ast_channel_lock(chan);
00496
00497 #define DEADLOCK_AVOIDANCE(lock) \
00498 do { \
00499 int __res; \
00500 if (!(__res = ast_mutex_unlock(lock))) { \
00501 usleep(1); \
00502 ast_mutex_lock(lock); \
00503 } else { \
00504 ast_log(LOG_WARNING, "Failed to unlock mutex '%s' (%s). I will NOT try to relock. {{{ THIS IS A BUG. }}}\n", #lock, strerror(__res)); \
00505 } \
00506 } while (0)
00507
00508 #define DLA_UNLOCK(lock) ast_mutex_unlock(lock)
00509
00510 #define DLA_LOCK(lock) ast_mutex_lock(lock)
00511
00512 #endif
00513
00514 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00515
00516
00517
00518
00519 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track) \
00520 scope ast_mutex_t mutex = init_val; \
00521 static void __attribute__((constructor)) init_##mutex(void) \
00522 { \
00523 if (track) \
00524 ast_mutex_init(&mutex); \
00525 else \
00526 ast_mutex_init_notracking(&mutex); \
00527 } \
00528 \
00529 static void __attribute__((destructor)) fini_##mutex(void) \
00530 { \
00531 ast_mutex_destroy(&mutex); \
00532 }
00533 #else
00534
00535 #define __AST_MUTEX_DEFINE(scope, mutex, init_val, track) scope ast_mutex_t mutex = init_val
00536 #endif
00537
00538 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
00539 #define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
00540
00541
00542
00543 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00544 #define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) \
00545 scope ast_rwlock_t rwlock = init_val; \
00546 static void __attribute__((constructor)) init_##rwlock(void) \
00547 { \
00548 if (track) \
00549 ast_rwlock_init(&rwlock); \
00550 else \
00551 ast_rwlock_init_notracking(&rwlock); \
00552 } \
00553 static void __attribute__((destructor)) fini_##rwlock(void) \
00554 { \
00555 ast_rwlock_destroy(&rwlock); \
00556 }
00557 #else
00558 #define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) scope ast_rwlock_t rwlock = init_val
00559 #endif
00560
00561 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE, 1)
00562 #define AST_RWLOCK_DEFINE_STATIC_NOTRACKING(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE_NOTRACKING, 0)
00563
00564 #ifndef __CYGWIN__
00565 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
00566 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
00567 #endif
00568 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
00569 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
00570 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
00571 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
00572 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
00573 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
00574 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
00575 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
00576 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
00577 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
00578 #define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
00579
00580 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
00581
00582 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
00583
00584 #ifndef __linux__
00585 #define pthread_create __use_ast_pthread_create_instead__
00586 #endif
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
00599
00600 #include "asterisk/inline_api.h"
00601
00602 #if defined(HAVE_OSX_ATOMICS)
00603 #include "libkern/OSAtomic.h"
00604 #endif
00605
00606
00607
00608
00609
00610
00611 #if defined(HAVE_GCC_ATOMICS)
00612 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00613 {
00614 return __sync_fetch_and_add(p, v);
00615 })
00616 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
00617 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00618 {
00619 return OSAtomicAdd32(v, (int32_t *) p) - v;
00620 })
00621 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
00622 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00623 {
00624 return OSAtomicAdd64(v, (int64_t *) p) - v;
00625 #elif defined (__i386__) || defined(__x86_64__)
00626 #ifdef sun
00627 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00628 {
00629 __asm __volatile (
00630 " lock; xaddl %0, %1 ; "
00631 : "+r" (v),
00632 "=m" (*p)
00633 : "m" (*p));
00634 return (v);
00635 })
00636 #else
00637 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00638 {
00639 __asm __volatile (
00640 " lock xaddl %0, %1 ; "
00641 : "+r" (v),
00642 "=m" (*p)
00643 : "m" (*p));
00644 return (v);
00645 })
00646 #endif
00647 #else
00648 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00649 {
00650 return ast_atomic_fetchadd_int_slow(p, v);
00651 })
00652 #endif
00653
00654
00655
00656
00657 #if defined(HAVE_GCC_ATOMICS)
00658 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
00659 {
00660 return __sync_sub_and_fetch(p, 1) == 0;
00661 })
00662 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
00663 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
00664 {
00665 return OSAtomicAdd32( -1, (int32_t *) p) == 0;
00666 })
00667 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
00668 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
00669 {
00670 return OSAtomicAdd64( -1, (int64_t *) p) == 0;
00671 #else
00672 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
00673 {
00674 int a = ast_atomic_fetchadd_int(p, -1);
00675 return a == 1;
00676 })
00677 #endif
00678
00679 #endif