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