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