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 = time(NULL);
00196 time_t current;
00197 do {
00198 res = pthread_mutex_trylock(&t->mutex);
00199 if (res == EBUSY) {
00200 current = time(NULL);
00201 if ((current - seconds) && (!((current - seconds) % 5))) {
00202 fprintf(stderr, "%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
00203 filename, lineno, func, (int)(current - seconds), mutex_name);
00204 fprintf(stderr, "%s line %d (%s): '%s' was locked here.\n",
00205 t->file, t->lineno, t->func, mutex_name);
00206 }
00207 usleep(200);
00208 }
00209 } while (res == EBUSY);
00210 }
00211 #else
00212 res = pthread_mutex_lock(&t->mutex);
00213 #endif
00214 if (!res) {
00215 t->file = filename;
00216 t->lineno = lineno;
00217 t->func = func;
00218 t->thread = pthread_self();
00219 } else {
00220 fprintf(stderr, "%s line %d (%s): Error obtaining mutex: %s\n",
00221 filename, lineno, func, strerror(errno));
00222 #ifdef THREAD_CRASH
00223 DO_THREAD_CRASH;
00224 #endif
00225 }
00226 return res;
00227 }
00228
00229 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00230
00231 static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func,
00232 char* mutex_name, ast_mutex_t *t)
00233 {
00234 int res;
00235 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE)
00236 if ((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) {
00237 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00238 fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00239 filename, lineno, func, mutex_name);
00240 #endif
00241 ast_mutex_init(t);
00242 }
00243 #endif
00244 res = pthread_mutex_trylock(&t->mutex);
00245 if (!res) {
00246 t->file = filename;
00247 t->lineno = lineno;
00248 t->func = func;
00249 t->thread = pthread_self();
00250 }
00251 return res;
00252 }
00253
00254 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00255
00256 static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func,
00257 char* mutex_name, ast_mutex_t *t) {
00258 int res;
00259 #ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
00260 if ((t->mutex) == ((pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER)) {
00261 fprintf(stderr, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
00262 filename, lineno, func, mutex_name);
00263 }
00264 #endif
00265
00266 t->file = NULL;
00267 t->lineno = 0;
00268 t->func = NULL;
00269 t->thread = 0;
00270 res = pthread_mutex_unlock(&t->mutex);
00271 if (res) {
00272 fprintf(stderr, "%s line %d (%s): Error releasing mutex: %s\n",
00273 filename, lineno, func, strerror(res));
00274 #ifdef THREAD_CRASH
00275 DO_THREAD_CRASH;
00276 #endif
00277 }
00278 return res;
00279 }
00280
00281 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
00282
00283 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
00284 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
00285 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
00286 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
00287 #define pthread_mutex_init use_ast_pthread_mutex_init_instead_of_pthread_mutex_init
00288 #define pthread_mutex_destroy use_ast_pthread_mutex_destroy_instead_of_pthread_mutex_destroy
00289
00290 #else
00291
00292
00293 #define AST_MUTEX_INIT_VALUE PTHREAD_MUTEX_INIT_VALUE
00294
00295
00296 typedef pthread_mutex_t ast_mutex_t;
00297
00298 static inline int ast_mutex_init(ast_mutex_t *pmutex)
00299 {
00300 pthread_mutexattr_t attr;
00301 pthread_mutexattr_init(&attr);
00302 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
00303 return pthread_mutex_init(pmutex, &attr);
00304 }
00305 #define ast_pthread_mutex_init(pmutex,a) pthread_mutex_init(pmutex,a)
00306 #define ast_mutex_unlock(pmutex) pthread_mutex_unlock(pmutex)
00307 #define ast_mutex_destroy(pmutex) pthread_mutex_destroy(pmutex)
00308
00309 #if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
00310
00311
00312 #define __AST_MUTEX_DEFINE(scope,mutex) \
00313 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE; \
00314 static void __attribute__ ((constructor)) init_##mutex(void) \
00315 { \
00316 ast_mutex_init(&mutex); \
00317 } \
00318 static void __attribute__ ((destructor)) fini_##mutex(void) \
00319 { \
00320 ast_mutex_destroy(&mutex); \
00321 }
00322
00323 #define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex)
00324 #define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex)
00325
00326 #elif defined(AST_MUTEX_INIT_ON_FIRST_USE)
00327
00328
00329
00330
00331 #define __AST_MUTEX_DEFINE(scope,mutex) \
00332 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00333
00334 static inline int ast_mutex_lock(ast_mutex_t *pmutex)
00335 {
00336 if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
00337 ast_mutex_init(pmutex);
00338 return pthread_mutex_lock(pmutex);
00339 }
00340 static inline int ast_mutex_trylock(ast_mutex_t *pmutex)
00341 {
00342 if (*pmutex == (ast_mutex_t)AST_MUTEX_KIND)
00343 ast_mutex_init(pmutex);
00344 return pthread_mutex_trylock(pmutex);
00345 }
00346 #else
00347
00348 #define __AST_MUTEX_DEFINE(scope,mutex) \
00349 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE
00350 #define ast_mutex_lock(pmutex) pthread_mutex_lock(pmutex)
00351 #define ast_mutex_trylock(pmutex) pthread_mutex_trylock(pmutex)
00352 #endif
00353
00354 #endif
00355
00356 #define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static,mutex)
00357 #define AST_MUTEX_DEFINE_EXPORTED(mutex) __AST_MUTEX_DEFINE(,mutex)
00358
00359 #define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
00360
00361 #define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
00362 #define pthread_create __use_ast_pthread_create_instead__
00363
00364 #endif