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