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, { NULL }, { 0 }, 0, { NULL }, { 0 } }
00107
00108 #define AST_MAX_REENTRANCY 10
00109
00110 struct ast_mutex_info {
00111 pthread_mutex_t mutex;
00112 const char *file[AST_MAX_REENTRANCY];
00113 int lineno[AST_MAX_REENTRANCY];
00114 int reentrancy;
00115 const char *func[AST_MAX_REENTRANCY];
00116 pthread_t thread[AST_MAX_REENTRANCY];
00117 };
00118
00119 typedef struct ast_mutex_info ast_mutex_t;
00120
00121 typedef pthread_cond_t ast_cond_t;
00122
00123 static pthread_mutex_t empty_mutex;
00124
00125 static void __attribute__((constructor)) init_empty_mutex(void)
00126 {
00127 memset(&empty_mutex, 0, sizeof(empty_mutex));
00128 }
00129
00130 static inline int __ast_pthread_mutex_init_attr(const char *filename, int lineno, const char *func,
00131 const char *mutex_name, ast_mutex_t *t,
00132 pthread_mutexattr_t *attr)
00133 {
00134 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00135 int canlog = strcmp(filename, "logger.c");
00136
00137 if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00138 if ((t->mutex) != (empty_mutex)) {
00139 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is already initialized.\n",
00140 filename, lineno, func, mutex_name);
00141 __ast_mutex_logger("%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
00142 t->file[0], t->lineno[0], t->func[0], mutex_name);
00143 DO_THREAD_CRASH;
00144 return 0;
00145 }
00146 }
00147 #endif
00148
00149 t->file[0] = filename;
00150 t->lineno[0] = lineno;
00151 t->func[0] = func;
00152 t->thread[0] = 0;
00153 t->reentrancy = 0;
00154
00155 return pthread_mutex_init(&t->mutex, attr);
00156 }
00157
00158 static inline int __ast_pthread_mutex_init(const char *filename, int lineno, const char *func,
00159 const char *mutex_name, ast_mutex_t *t)
00160 {
00161 static pthread_mutexattr_t attr;
00162
00163 pthread_mutexattr_init(&attr);
00164 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00165
00166 return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
00167 }
00168 #define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
00169
00170 static inline int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func,
00171 const char *mutex_name, ast_mutex_t *t)
00172 {
00173 int res;
00174 int canlog = strcmp(filename, "logger.c");
00175
00176 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00177 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00178 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00179 filename, lineno, func, mutex_name);
00180 }
00181 #endif
00182
00183 res = pthread_mutex_trylock(&t->mutex);
00184 switch (res) {
00185 case 0:
00186 pthread_mutex_unlock(&t->mutex);
00187 break;
00188 case EINVAL:
00189 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
00190 filename, lineno, func, mutex_name);
00191 break;
00192 case EBUSY:
00193 __ast_mutex_logger("%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
00194 filename, lineno, func, mutex_name);
00195 __ast_mutex_logger("%s line %d (%s): Error: '%s' was locked here.\n",
00196 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00197 break;
00198 }
00199
00200 if ((res = pthread_mutex_destroy(&t->mutex)))
00201 __ast_mutex_logger("%s line %d (%s): Error destroying mutex: %s\n",
00202 filename, lineno, func, strerror(res));
00203 #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00204 else
00205 t->mutex = PTHREAD_MUTEX_INIT_VALUE;
00206 #endif
00207 t->file[0] = filename;
00208 t->lineno[0] = lineno;
00209 t->func[0] = func;
00210
00211 return res;
00212 }
00213
00214 static inline int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func,
00215 const char* mutex_name, ast_mutex_t *t)
00216 {
00217 int res;
00218 int canlog = strcmp(filename, "logger.c");
00219
00220 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00221 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00222 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00223 filename, lineno, func, mutex_name);
00224 ast_mutex_init(t);
00225 }
00226 #endif
00227
00228 #ifdef DETECT_DEADLOCKS
00229 {
00230 time_t seconds = time(NULL);
00231 time_t current;
00232 do {
00233 #ifdef HAVE_MTX_PROFILE
00234 ast_mark(mtx_prof, 1);
00235 #endif
00236 res = pthread_mutex_trylock(&t->mutex);
00237 #ifdef HAVE_MTX_PROFILE
00238 ast_mark(mtx_prof, 0);
00239 #endif
00240 if (res == EBUSY) {
00241 current = time(NULL);
00242 if ((current - seconds) && (!((current - seconds) % 5))) {
00243 __ast_mutex_logger("%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
00244 filename, lineno, func, (int)(current - seconds), mutex_name);
00245 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00246 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1],
00247 t->func[t->reentrancy-1], mutex_name);
00248 }
00249 usleep(200);
00250 }
00251 } while (res == EBUSY);
00252 }
00253 #else
00254 #ifdef HAVE_MTX_PROFILE
00255 ast_mark(mtx_prof, 1);
00256 res = pthread_mutex_trylock(&t->mutex);
00257 ast_mark(mtx_prof, 0);
00258 if (res)
00259 #endif
00260 res = pthread_mutex_lock(&t->mutex);
00261 #endif
00262
00263 if (!res) {
00264 if (t->reentrancy < AST_MAX_REENTRANCY) {
00265 t->file[t->reentrancy] = filename;
00266 t->lineno[t->reentrancy] = lineno;
00267 t->func[t->reentrancy] = func;
00268 t->thread[t->reentrancy] = pthread_self();
00269 t->reentrancy++;
00270 } else {
00271 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00272 filename, lineno, func, mutex_name);
00273 }
00274 } else {
00275 __ast_mutex_logger("%s line %d (%s): Error obtaining mutex: %s\n",
00276 filename, lineno, func, strerror(errno));
00277 DO_THREAD_CRASH;
00278 }
00279
00280 return res;
00281 }
00282
00283 static inline int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func,
00284 const char* mutex_name, ast_mutex_t *t)
00285 {
00286 int res;
00287 int canlog = strcmp(filename, "logger.c");
00288
00289 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00290 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00291 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00292 filename, lineno, func, mutex_name);
00293 ast_mutex_init(t);
00294 }
00295 #endif
00296
00297 if (!(res = pthread_mutex_trylock(&t->mutex))) {
00298 if (t->reentrancy < AST_MAX_REENTRANCY) {
00299 t->file[t->reentrancy] = filename;
00300 t->lineno[t->reentrancy] = lineno;
00301 t->func[t->reentrancy] = func;
00302 t->thread[t->reentrancy] = pthread_self();
00303 t->reentrancy++;
00304 } else {
00305 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00306 filename, lineno, func, mutex_name);
00307 }
00308 }
00309
00310 return res;
00311 }
00312
00313 static inline int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func,
00314 const char *mutex_name, ast_mutex_t *t)
00315 {
00316 int res;
00317 int canlog = strcmp(filename, "logger.c");
00318
00319 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00320 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00321 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00322 filename, lineno, func, mutex_name);
00323 }
00324 #endif
00325
00326 if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
00327 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00328 filename, lineno, func, mutex_name);
00329 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00330 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00331 DO_THREAD_CRASH;
00332 }
00333
00334 if (--t->reentrancy < 0) {
00335 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00336 filename, lineno, func, mutex_name);
00337 t->reentrancy = 0;
00338 }
00339
00340 if (t->reentrancy < AST_MAX_REENTRANCY) {
00341 t->file[t->reentrancy] = NULL;
00342 t->lineno[t->reentrancy] = 0;
00343 t->func[t->reentrancy] = NULL;
00344 t->thread[t->reentrancy] = 0;
00345 }
00346
00347 if ((res = pthread_mutex_unlock(&t->mutex))) {
00348 __ast_mutex_logger("%s line %d (%s): Error releasing mutex: %s\n",
00349 filename, lineno, func, strerror(res));
00350 DO_THREAD_CRASH;
00351 }
00352
00353 return res;
00354 }
00355
00356 static inline int __ast_cond_init(const char *filename, int lineno, const char *func,
00357 const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr)
00358 {
00359 return pthread_cond_init(cond, cond_attr);
00360 }
00361
00362 static inline int __ast_cond_signal(const char *filename, int lineno, const char *func,
00363 const char *cond_name, ast_cond_t *cond)
00364 {
00365 return pthread_cond_signal(cond);
00366 }
00367
00368 static inline int __ast_cond_broadcast(const char *filename, int lineno, const char *func,
00369 const char *cond_name, ast_cond_t *cond)
00370 {
00371 return pthread_cond_broadcast(cond);
00372 }
00373
00374 static inline int __ast_cond_destroy(const char *filename, int lineno, const char *func,
00375 const char *cond_name, ast_cond_t *cond)
00376 {
00377 return pthread_cond_destroy(cond);
00378 }
00379
00380 static inline int __ast_cond_wait(const char *filename, int lineno, const char *func,
00381 const char *cond_name, const char *mutex_name,
00382 ast_cond_t *cond, ast_mutex_t *t)
00383 {
00384 int res;
00385 int canlog = strcmp(filename, "logger.c");
00386
00387 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00388 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00389 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00390 filename, lineno, func, mutex_name);
00391 }
00392 #endif
00393
00394 if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
00395 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00396 filename, lineno, func, mutex_name);
00397 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00398 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00399 DO_THREAD_CRASH;
00400 }
00401
00402 if (--t->reentrancy < 0) {
00403 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00404 filename, lineno, func, mutex_name);
00405 t->reentrancy = 0;
00406 }
00407
00408 if (t->reentrancy < AST_MAX_REENTRANCY) {
00409 t->file[t->reentrancy] = NULL;
00410 t->lineno[t->reentrancy] = 0;
00411 t->func[t->reentrancy] = NULL;
00412 t->thread[t->reentrancy] = 0;
00413 }
00414
00415 if ((res = pthread_cond_wait(cond, &t->mutex))) {
00416 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
00417 filename, lineno, func, strerror(res));
00418 DO_THREAD_CRASH;
00419 } else {
00420 if (t->reentrancy < AST_MAX_REENTRANCY) {
00421 t->file[t->reentrancy] = filename;
00422 t->lineno[t->reentrancy] = lineno;
00423 t->func[t->reentrancy] = func;
00424 t->thread[t->reentrancy] = pthread_self();
00425 t->reentrancy++;
00426 } else {
00427 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00428 filename, lineno, func, mutex_name);
00429 }
00430 }
00431
00432 return res;
00433 }
00434
00435 static inline int __ast_cond_timedwait(const char *filename, int lineno, const char *func,
00436 const char *cond_name, const char *mutex_name, ast_cond_t *cond,
00437 ast_mutex_t *t, const struct timespec *abstime)
00438 {
00439 int res;
00440 int canlog = strcmp(filename, "logger.c");
00441
00442 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00443 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
00444 __ast_mutex_logger("%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00445 filename, lineno, func, mutex_name);
00446 }
00447 #endif
00448
00449 if (t->reentrancy && (t->thread[t->reentrancy-1] != pthread_self())) {
00450 __ast_mutex_logger("%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
00451 filename, lineno, func, mutex_name);
00452 __ast_mutex_logger("%s line %d (%s): '%s' was locked here.\n",
00453 t->file[t->reentrancy-1], t->lineno[t->reentrancy-1], t->func[t->reentrancy-1], mutex_name);
00454 DO_THREAD_CRASH;
00455 }
00456
00457 if (--t->reentrancy < 0) {
00458 __ast_mutex_logger("%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
00459 filename, lineno, func, mutex_name);
00460 t->reentrancy = 0;
00461 }
00462
00463 if (t->reentrancy < AST_MAX_REENTRANCY) {
00464 t->file[t->reentrancy] = NULL;
00465 t->lineno[t->reentrancy] = 0;
00466 t->func[t->reentrancy] = NULL;
00467 t->thread[t->reentrancy] = 0;
00468 }
00469
00470 if ((res = pthread_cond_timedwait(cond, &t->mutex, abstime)) && (res != ETIMEDOUT)) {
00471 __ast_mutex_logger("%s line %d (%s): Error waiting on condition mutex '%s'\n",
00472 filename, lineno, func, strerror(res));
00473 DO_THREAD_CRASH;
00474 } else {
00475 if (t->reentrancy < AST_MAX_REENTRANCY) {
00476 t->file[t->reentrancy] = filename;
00477 t->lineno[t->reentrancy] = lineno;
00478 t->func[t->reentrancy] = func;
00479 t->thread[t->reentrancy] = pthread_self();
00480 t->reentrancy++;
00481 } else {
00482 __ast_mutex_logger("%s line %d (%s): '%s' really deep reentrancy!\n",
00483 filename, lineno, func, mutex_name);
00484 }
00485 }
00486
00487 return res;
00488 }
00489
00490 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00491 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00492 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00493 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00494 #define ast_cond_init(cond, attr) __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
00495 #define ast_cond_destroy(cond) __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00496 #define ast_cond_signal(cond) __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00497 #define ast_cond_broadcast(cond) __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
00498 #define ast_cond_wait(cond, mutex) __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
00499 #define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
00500
00501 #else
00502
00503
00504 typedef pthread_mutex_t ast_mutex_t;
00505
00506 #define AST_MUTEX_INIT_VALUE ((ast_mutex_t) PTHREAD_MUTEX_INIT_VALUE)
00507
00508 static inline int ast_mutex_init(ast_mutex_t *pmutex)
00509 {
00510 pthread_mutexattr_t attr;
00511
00512 pthread_mutexattr_init(&attr);
00513 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00514
00515 return pthread_mutex_init(pmutex, &attr);
00516 }
00517
00518 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
00519
00520 static inline int ast_mutex_unlock(ast_mutex_t *pmutex)
00521 {
00522 return pthread_mutex_unlock(pmutex);
00523 }
00524
00525 static inline int ast_mutex_destroy(ast_mutex_t *pmutex)
00526 {
00527 return pthread_mutex_destroy(pmutex);
00528 }
00529
00530 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
00531 {
00532 __MTX_PROF(pmutex);
00533 }
00534
00535 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
00536 {
00537 return pthread_mutex_trylock(pmutex);
00538 }
00539
00540 typedef pthread_cond_t ast_cond_t;
00541
00542 static inline int ast_cond_init(ast_cond_t *cond, pthread_condattr_t *cond_attr)
00543 {
00544 return pthread_cond_init(cond, cond_attr);
00545 }
00546
00547 static inline int ast_cond_signal(ast_cond_t *cond)
00548 {
00549 return pthread_cond_signal(cond);
00550 }
00551
00552 static inline int ast_cond_broadcast(ast_cond_t *cond)
00553 {
00554 return pthread_cond_broadcast(cond);
00555 }
00556
00557 static inline int ast_cond_destroy(ast_cond_t *cond)
00558 {
00559 return pthread_cond_destroy(cond);
00560 }
00561
00562 static inline int ast_cond_wait(ast_cond_t *cond, ast_mutex_t *t)
00563 {
00564 return pthread_cond_wait(cond, t);
00565 }
00566
00567 static inline int ast_cond_timedwait(ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime)
00568 {
00569 return pthread_cond_timedwait(cond, t, abstime);
00570 }
00571
00572 #endif
00573
00574 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00575
00576
00577 #define __AST_MUTEX_DEFINE(scope, mutex) \
00578 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
00579 static void __attribute__ ((constructor)) init_##mutex(void) \
00580 { \
00581 ast_mutex_init(&mutex); \
00582 } \
00583 static void __attribute__ ((destructor)) fini_##mutex(void) \
00584 { \
00585 ast_mutex_destroy(&mutex); \
00586 }
00587 #else
00588
00589 #define __AST_MUTEX_DEFINE(scope, mutex) \
00590 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00591 #endif
00592
00593 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
00594 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
00595 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
00596 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
00597 #define pthread_mutex_init use_ast_mutex_init_instead_of_pthread_mutex_init
00598 #define pthread_mutex_destroy use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
00599 #define pthread_cond_t use_ast_cond_t_instead_of_pthread_cond_t
00600 #define pthread_cond_init use_ast_cond_init_instead_of_pthread_cond_init
00601 #define pthread_cond_destroy use_ast_cond_destroy_instead_of_pthread_cond_destroy
00602 #define pthread_cond_signal use_ast_cond_signal_instead_of_pthread_cond_signal
00603 #define pthread_cond_broadcast use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
00604 #define pthread_cond_wait use_ast_cond_wait_instead_of_pthread_cond_wait
00605 #define pthread_cond_timedwait use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
00606
00607 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex)
00608
00609 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
00610
00611 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
00612
00613 #ifndef __linux__
00614 #define pthread_create __use_ast_pthread_create_instead__
00615 #endif
00616
00617 typedef pthread_rwlock_t ast_rwlock_t;
00618
00619 static inline int ast_rwlock_init(ast_rwlock_t *prwlock)
00620 {
00621 pthread_rwlockattr_t attr;
00622
00623 pthread_rwlockattr_init(&attr);
00624
00625 #ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
00626 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
00627 #endif
00628
00629 return pthread_rwlock_init(prwlock, &attr);
00630 }
00631
00632 static inline int ast_rwlock_destroy(ast_rwlock_t *prwlock)
00633 {
00634 return pthread_rwlock_destroy(prwlock);
00635 }
00636
00637 static inline int ast_rwlock_unlock(ast_rwlock_t *prwlock)
00638 {
00639 return pthread_rwlock_unlock(prwlock);
00640 }
00641
00642 static inline int ast_rwlock_rdlock(ast_rwlock_t *prwlock)
00643 {
00644 return pthread_rwlock_rdlock(prwlock);
00645 }
00646
00647 static inline int ast_rwlock_tryrdlock(ast_rwlock_t *prwlock)
00648 {
00649 return pthread_rwlock_tryrdlock(prwlock);
00650 }
00651
00652 static inline int ast_rwlock_wrlock(ast_rwlock_t *prwlock)
00653 {
00654 return pthread_rwlock_wrlock(prwlock);
00655 }
00656
00657 static inline int ast_rwlock_trywrlock(ast_rwlock_t *prwlock)
00658 {
00659 return pthread_rwlock_trywrlock(prwlock);
00660 }
00661
00662
00663
00664 #ifndef HAVE_PTHREAD_RWLOCK_INITIALIZER
00665 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
00666 scope ast_rwlock_t rwlock; \
00667 static void __attribute__ ((constructor)) init_##rwlock(void) \
00668 { \
00669 ast_rwlock_init(&rwlock); \
00670 } \
00671 static void __attribute__ ((destructor)) fini_##rwlock(void) \
00672 { \
00673 ast_rwlock_destroy(&rwlock); \
00674 }
00675 #else
00676 #define AST_RWLOCK_INIT_VALUE PTHREAD_RWLOCK_INITIALIZER
00677 #define __AST_RWLOCK_DEFINE(scope, rwlock) \
00678 scope ast_rwlock_t rwlock = AST_RWLOCK_INIT_VALUE
00679 #endif
00680
00681 #define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock)
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693 int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
00694
00695 #include "asterisk/inline_api.h"
00696
00697 #if defined(HAVE_OSX_ATOMICS)
00698 #include "libkern/OSAtomic.h"
00699 #endif
00700
00701
00702
00703
00704
00705
00706 #if defined(HAVE_GCC_ATOMICS)
00707 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00708 {
00709 return __sync_fetch_and_add(p, v);
00710 })
00711 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
00712 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00713 {
00714 return OSAtomicAdd32(v, (int32_t *) p);
00715 })
00716 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
00717 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00718 {
00719 return OSAtomicAdd64(v, (int64_t *) p);
00720 #elif defined (__i386__)
00721 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00722 {
00723 __asm __volatile (
00724 " lock xaddl %0, %1 ; "
00725 : "+r" (v),
00726 "=m" (*p)
00727 : "m" (*p));
00728 return (v);
00729 })
00730 #else
00731 AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
00732 {
00733 return ast_atomic_fetchadd_int_slow(p, v);
00734 })
00735 #endif
00736
00737
00738
00739
00740 #if defined(HAVE_GCC_ATOMICS)
00741 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
00742 {
00743 return __sync_sub_and_fetch(p, 1) == 0;
00744 })
00745 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
00746 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
00747 {
00748 return OSAtomicAdd32( -1, (int32_t *) p) == 0;
00749 })
00750 #elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
00751 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
00752 {
00753 return OSAtomicAdd64( -1, (int64_t *) p) == 0;
00754 #else
00755 AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
00756 {
00757 int a = ast_atomic_fetchadd_int(p, -1);
00758 return a == 1;
00759 })
00760 #endif
00761
00762 #ifndef DEBUG_CHANNEL_LOCKS
00763
00764
00765 #define ast_channel_lock(x) ast_mutex_lock(&x->lock)
00766
00767
00768 #define ast_channel_unlock(x) ast_mutex_unlock(&x->lock)
00769
00770
00771 #define ast_channel_trylock(x) ast_mutex_trylock(&x->lock)
00772 #else
00773
00774 struct ast_channel;
00775
00776
00777
00778 int ast_channel_lock(struct ast_channel *chan);
00779
00780
00781
00782
00783 int ast_channel_unlock(struct ast_channel *chan);
00784
00785
00786
00787 int ast_channel_trylock(struct ast_channel *chan);
00788 #endif
00789
00790 #endif