Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

lock.h

Go to the documentation of this file.
00001 /* 00002 * Asterisk -- A telephony toolkit for Linux. 00003 * 00004 * General Asterisk channel definitions. 00005 * 00006 * Copyright (C) 1999, Mark Spencer 00007 * 00008 * Mark Spencer <markster@linux-support.net> 00009 * 00010 * This program is free software, distributed under the terms of 00011 * the GNU General Public License 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 /* Provide the Linux initializers for MacOS X */ 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 /* BSD */ 00040 00041 /* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes 00042 and will not run without them. */ 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 /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */ 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 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope 00153 constrictors/destructors to create/destroy mutexes. */ 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 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on 00166 first use. The performance impact on FreeBSD should be small since 00167 the pthreads library does this itself to initialize errror checking 00168 (defaulty type) mutexes. If nither is defined, the pthreads librariy 00169 does the initialization itself on first use. */ 00170 #define __AST_MUTEX_DEFINE(scope,mutex) \ 00171 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE 00172 #else /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00173 /* By default, use static initialization of mutexes.*/ 00174 #define __AST_MUTEX_DEFINE(scope,mutex) \ 00175 scope ast_mutex_t mutex = AST_MUTEX_INIT_VALUE 00176 #endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 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 /* definded(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */ 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 /* DETECT_DEADLOCKS */ 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 /* definded(AST_MUTEX_INIT_W_CONSTRUCTORS) || defined(AST_MUTEX_INIT_ON_FIRST_USE) */ 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 /* Assumes lock is actually held */ 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 /* DEBUG_THREADS */ 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 /* if AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope 00309 constrictors/destructors to create/destroy mutexes. */ 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 /* if AST_MUTEX_INIT_ON_FIRST_USE is defined, mutexes are created on 00326 first use. The performance impact on FreeBSD should be small since 00327 the pthreads library does this itself to initialize errror checking 00328 (defaulty type) mutexes.*/ 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 /* By default, use static initialization of mutexes.*/ 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 /* AST_MUTEX_INIT_W_CONSTRUCTORS */ 00351 00352 #endif /* DEBUG_THREADS */ 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 00361 #endif

Generated on Tue Aug 17 16:13:53 2004 for Asterisk by doxygen 1.3.8