00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
#ifndef _ASTERISK_LOCK_H
00015
#define _ASTERISK_LOCK_H
00016
00017
#include <pthread.h>
00018
#include <netdb.h>
00019
#include <time.h>
00020
#include <sys/param.h>
00021
00022 #define AST_PTHREADT_NULL (pthread_t) -1
00023 #define AST_PTHREADT_STOP (pthread_t) -2
00024
00025
#ifdef __APPLE__
00026
00027
#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
00028
#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP { 0x4d555458, \
00029
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
00030
0x20 } }
00031
#endif
00032
00033
#ifdef BSD
00034
#ifdef __GNUC__
00035
#define AST_MUTEX_INIT_W_CONSTRUCTORS
00036
#else
00037
#define AST_MUTEX_INIT_ON_FIRST_USE
00038
#endif
00039
#endif
00040
00041
00042
00043
#ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00044
#define PTHREAD_MUTEX_INIT_VALUE PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00045
#define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE_NP
00046
#else
00047 #define PTHREAD_MUTEX_INIT_VALUE PTHREAD_MUTEX_INITIALIZER
00048 #define AST_MUTEX_KIND PTHREAD_MUTEX_RECURSIVE
00049
#endif
00050
00051
#ifdef DEBUG_THREADS
00052
00053
#ifdef THREAD_CRASH
00054
#define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
00055
#endif
00056
00057
#include <errno.h>
00058
#include <string.h>
00059
#include <stdio.h>
00060
#include <unistd.h>
00061
00062
#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, NULL, 0, NULL, 0 }
00063
00064
struct ast_mutex_info {
00065 pthread_mutex_t mutex;
00066
char *file;
00067
int lineno;
00068
char *func;
00069 pthread_t thread;
00070 };
00071
00072
typedef struct ast_mutex_info
ast_mutex_t;
00073
00074
static inline int __ast_pthread_mutex_init_attr(
char *filename,
int lineno,
char *func,
00075
char* mutex_name, ast_mutex_t *t,
00076 pthread_mutexattr_t *attr)
00077 {
00078
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00079
if ((t->mutex) != ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) {
00080 fprintf(stderr,
"%s line %d (%s): Error: mutex '%s' is already initialized.\n",
00081 filename, lineno, func, mutex_name);
00082 fprintf(stderr,
"%s line %d (%s): Error: previously initialization of mutex '%s'.\n",
00083 t->file, t->lineno, t->func, mutex_name);
00084
#ifdef THREAD_CRASH
00085
DO_THREAD_CRASH;
00086
#endif
00087
return 0;
00088 }
00089
#endif
00090
t->file = filename;
00091 t->lineno = lineno;
00092 t->func = func;
00093 t->thread = 0;
00094
return pthread_mutex_init(&t->mutex, attr);
00095 }
00096
00097
static inline int __ast_pthread_mutex_init(
char *filename,
int lineno,
char *func,
00098
char *mutex_name, ast_mutex_t *t)
00099 {
00100
static pthread_mutexattr_t attr;
00101 pthread_mutexattr_init(&attr);
00102 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00103
return __ast_pthread_mutex_init_attr(filename, lineno, func, mutex_name, t, &attr);
00104 }
00105
00106
#define ast_mutex_init(pmutex) __ast_pthread_mutex_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
00107
#define ast_pthread_mutex_init(pmutex,attr) __ast_pthread_mutex_init_attr(__FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex, attr)
00108
00109
static inline int __ast_pthread_mutex_destroy(
char *filename,
int lineno,
char *func,
00110
char *mutex_name, ast_mutex_t *t)
00111 {
00112
int res;
00113
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00114
if ((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) {
00115 fprintf(stderr,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00116 filename, lineno, func, mutex_name);
00117 }
00118
#endif
00119
res = pthread_mutex_trylock(&t->mutex);
00120
switch (res) {
00121
case 0:
00122 pthread_mutex_unlock(&t->mutex);
00123
break;
00124
case EINVAL:
00125 fprintf(stderr,
"%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
00126 filename, lineno, func, mutex_name);
00127
break;
00128
case EBUSY:
00129 fprintf(stderr,
"%s line %d (%s): Error: attemp to destroy locked mutex '%s'.\n",
00130 filename, lineno, func, mutex_name);
00131 fprintf(stderr,
"%s line %d (%s): Error: '%s' was locked here.\n",
00132 t->file, t->lineno, t->func, mutex_name);
00133
break;
00134 }
00135 res = pthread_mutex_destroy(&t->mutex);
00136
if (res)
00137 fprintf(stderr,
"%s line %d (%s): Error destroying mutex: %s\n",
00138 filename, lineno, func, strerror(res));
00139
#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00140
else
00141 t->mutex =
PTHREAD_MUTEX_INIT_VALUE;
00142
#endif
00143
t->file = filename;
00144 t->lineno = lineno;
00145 t->func = func;
00146
return res;
00147 }
00148
00149
#define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00150
00151
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00152
00153
00154
#define __AST_MUTEX_DEFINE(scope,mutex) \
00155
scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
00156
static void __attribute__ ((constructor)) init_##mutex(void) \
00157
{ \
00158
ast_mutex_init(&mutex); \
00159
} \
00160
static void __attribute__ ((destructor)) fini_##mutex(void) \
00161
{ \
00162
ast_mutex_destroy(&mutex); \
00163
}
00164
#elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
00165
00166
00167
00168
00169
00170
#define __AST_MUTEX_DEFINE(scope,mutex) \
00171
scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00172
#else
00173
00174
#define __AST_MUTEX_DEFINE(scope,mutex) \
00175
scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00176
#endif
00177
00178
00179
00180
static inline int __ast_pthread_mutex_lock(
char *filename,
int lineno,
char *func,
00181
char* mutex_name, ast_mutex_t *t)
00182 {
00183
int res;
00184
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
00185
if ((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) {
00186
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00187
fprintf(stderr,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00188 filename, lineno, func, mutex_name);
00189
#endif
00190
ast_mutex_init(t);
00191 }
00192
#endif
00193
#ifdef DETECT_DEADLOCKS
00194
{
00195 time_t seconds seconds = time(NULL);
00196
do {
00197 res = pthread_mutex_trylock(&t->mutex);
00198
if (res == EBUSY) {
00199
if ((time(NULL) - seconds) % 5) {
00200 fprintf(stderr,
"%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
00201 filename, lineno, func, (time(NULL) - seconds), mutex_name);
00202 fprintf(stderr,
"%s line %d (%s): '%s' was locked here.\n",
00203 t->file, t->lineno, t->func, mutex_name);
00204 }
00205 usleep(200);
00206 }
00207 }
while (res == EBUSY);
00208 }
00209
#else
00210
res = pthread_mutex_lock(&t->mutex);
00211
#endif
00212
if (!res) {
00213 t->file = filename;
00214 t->lineno = lineno;
00215 t->func = func;
00216 t->thread = pthread_self();
00217 }
else {
00218 fprintf(stderr,
"%s line %d (%s): Error obtaining mutex: %s\n",
00219 filename, lineno, func, strerror(errno));
00220
#ifdef THREAD_CRASH
00221
DO_THREAD_CRASH;
00222
#endif
00223
}
00224
return res;
00225 }
00226
00227
#define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00228
00229
static inline int __ast_pthread_mutex_trylock(
char *filename,
int lineno,
char *func,
00230
char* mutex_name, ast_mutex_t *t)
00231 {
00232
int res;
00233
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
00234
if ((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) {
00235
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00236
fprintf(stderr,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00237 filename, lineno, func, mutex_name);
00238
#endif
00239
ast_mutex_init(t);
00240 }
00241
#endif
00242 res = pthread_mutex_trylock(&t->mutex);
00243
if (!res) {
00244 t->file = filename;
00245 t->lineno = lineno;
00246 t->func = func;
00247 t->thread = pthread_self();
00248 }
00249
return res;
00250 }
00251
00252
#define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00253
00254
static inline int __ast_pthread_mutex_unlock(
char *filename,
int lineno,
char *func,
00255
char* mutex_name, ast_mutex_t *t) {
00256
int res;
00257
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00258
if ((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) {
00259 fprintf(stderr,
"%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00260 filename, lineno, func, mutex_name);
00261 }
00262
#endif
00263
00264 t->file = NULL;
00265 t->lineno = 0;
00266 t->func = NULL;
00267 t->thread = 0;
00268 res = pthread_mutex_unlock(&t->mutex);
00269
if (res) {
00270 fprintf(stderr,
"%s line %d (%s): Error releasing mutex: %s\n",
00271 filename, lineno, func, strerror(res));
00272
#ifdef THREAD_CRASH
00273
DO_THREAD_CRASH;
00274
#endif
00275
}
00276
return res;
00277 }
00278
00279
#define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00280
00281
#define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
00282
#define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
00283
#define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
00284
#define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
00285
#define pthread_mutex_init use_ast_pthread_mutex_init_instead_of_pthread_mutex_init
00286
#define pthread_mutex_destroy use_ast_pthread_mutex_destroy_instead_of_pthread_mutex_destroy
00287
00288
#else
00289
00290
00291 #define AST_MUTEX_INIT_VALUE PTHREAD_MUTEX_INIT_VALUE
00292
00293
00294 typedef pthread_mutex_t
ast_mutex_t;
00295
00296
static inline int ast_mutex_init(ast_mutex_t *pmutex)
00297 {
00298 pthread_mutexattr_t attr;
00299 pthread_mutexattr_init(&attr);
00300 pthread_mutexattr_settype(&attr,
AST_MUTEX_KIND);
00301
return pthread_mutex_init(pmutex, &attr);
00302 }
00303 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
00304 #define ast_mutex_unlock(pmutex) pthread_mutex_unlock(pmutex)
00305 #define ast_mutex_destroy(pmutex) pthread_mutex_destroy(pmutex)
00306
00307
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00308
00309
00310
#define __AST_MUTEX_DEFINE(scope,mutex) \
00311
scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
00312
static void __attribute__ ((constructor)) init_##mutex(void) \
00313
{ \
00314
ast_mutex_init(&mutex); \
00315
} \
00316
static void __attribute__ ((destructor)) fini_##mutex(void) \
00317
{ \
00318
ast_mutex_destroy(&mutex); \
00319
}
00320
00321
#define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex)
00322
#define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex)
00323
00324
#elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
00325
00326
00327
00328
00329
#define __AST_MUTEX_DEFINE(scope,mutex) \
00330
scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00331
00332
static inline int ast_mutex_lock(ast_mutex_t *pmutex)
00333 {
00334
if (*pmutex == (
ast_mutex_t)
AST_MUTEX_KIND)
00335 ast_mutex_init(pmutex);
00336
return pthread_mutex_lock(pmutex);
00337 }
00338
static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
00339 {
00340
if (*pmutex == (
ast_mutex_t)
AST_MUTEX_KIND)
00341 ast_mutex_init(pmutex);
00342
return pthread_mutex_trylock(pmutex);
00343 }
00344
#else
00345
00346 #define __AST_MUTEX_DEFINE(scope,mutex) \
00347
scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00348 #define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex)
00349 #define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex)
00350
#endif
00351
00352
#endif
00353
00354 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static,mutex)
00355 #define AST_MUTEX_DEFINE_EXPORTED(mutex) __AST_MUTEX_DEFINE(,mutex)
00356
00357 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
00358
00359 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
00360 #define pthread_create __use_ast_pthread_create_instead__
00361
00362
#endif