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
00019 #define AST_PTHREADT_NULL (pthread_t) -1
00020 #define AST_PTHREADT_STOP (pthread_t) -2
00021
00022 #ifdef DEBUG_THREADS
00023
00024 #ifdef THREAD_CRASH
00025 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
00026 #endif
00027
00028 #include <errno.h>
00029 #include <string.h>
00030 #include <stdio.h>
00031 #include <unistd.h>
00032
00033
00034
00035 #ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
00036 #define AST_MUTEX_INITIALIZER { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 }
00037 #else
00038 #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
00039 #define AST_MUTEX_INITIALIZER { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 }
00040 #else
00041 #define AST_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, NULL, 0, NULL, 0 }
00042 #endif
00043 #endif
00044 #ifdef PTHREAD_MUTEX_ERRORCHECK_NP
00045 #define AST_MUTEX_KIND PTHREAD_MUTEX_ERRORCHECK_NP
00046 #else
00047 #define AST_MUTEX_KIND PTHREAD_MUTEX_ERRORCHECK
00048 #endif
00049
00050 struct ast_mutex_info {
00051 pthread_mutex_t mutex;
00052 char *file;
00053 int lineno;
00054 char *func;
00055 pthread_t thread;
00056 };
00057
00058 typedef struct ast_mutex_info ast_mutex_t;
00059
00060 static inline int ast_mutex_init(ast_mutex_t *t) {
00061 static pthread_mutexattr_t attr;
00062 static int init = 1;
00063 int res;
00064 extern int pthread_mutexattr_setkind_np(pthread_mutexattr_t *, int);
00065
00066 if (init) {
00067 pthread_mutexattr_init(&attr);
00068 pthread_mutexattr_setkind_np(&attr, AST_MUTEX_KIND);
00069 init = 0;
00070 }
00071 res = pthread_mutex_init(&t->mutex, &attr);
00072 t->file = NULL;
00073 t->lineno = 0;
00074 t->func = 0;
00075 t->thread = 0;
00076 return res;
00077 }
00078
00079 static inline int ast_pthread_mutex_init(ast_mutex_t *t, pthread_mutexattr_t *attr)
00080 {
00081 int res;
00082 res = pthread_mutex_init(&t->mutex, attr);
00083 t->file = NULL;
00084 t->lineno = 0;
00085 t->func = 0;
00086 t->thread = 0;
00087 return res;
00088 }
00089
00090 static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, ast_mutex_t *t) {
00091 int res;
00092 res = pthread_mutex_lock(&t->mutex);
00093 if (!res) {
00094 t->file = filename;
00095 t->lineno = lineno;
00096 t->func = func;
00097 t->thread = pthread_self();
00098 } else {
00099 fprintf(stderr, "%s line %d (%s): Error obtaining mutex: %s\n",
00100 filename, lineno, func, strerror(errno));
00101 #ifdef THREAD_CRASH
00102 DO_THREAD_CRASH;
00103 #endif
00104 }
00105 return res;
00106 }
00107
00108 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
00109
00110 static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func, ast_mutex_t *t) {
00111 int res;
00112 res = pthread_mutex_trylock(&t->mutex);
00113 if (!res) {
00114 t->file = filename;
00115 t->lineno = lineno;
00116 t->func = func;
00117 t->thread = pthread_self();
00118 }
00119 return res;
00120 }
00121
00122 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
00123
00124 static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func, ast_mutex_t *t) {
00125 int res;
00126
00127 t->file = NULL;
00128 t->lineno = 0;
00129 t->func = NULL;
00130 t->thread = 0;
00131 res = pthread_mutex_unlock(&t->mutex);
00132 if (res) {
00133 fprintf(stderr, "%s line %d (%s): Error releasing mutex: %s\n",
00134 filename, lineno, func, strerror(res));
00135 #ifdef THREAD_CRASH
00136 DO_THREAD_CRASH;
00137 #endif
00138 }
00139 return res;
00140 }
00141
00142 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
00143
00144 static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char *func, ast_mutex_t *t)
00145 {
00146 int res;
00147 t->file = NULL;
00148 t->lineno = 0;
00149 t->func = NULL;
00150 t->thread = 0;
00151 res = pthread_mutex_destroy(&t->mutex);
00152 if (res)
00153 fprintf(stderr, "%s line %d (%s): Error destroying mutex: %s\n",
00154 filename, lineno, func, strerror(res));
00155 return res;
00156 }
00157
00158 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
00159
00160 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
00161 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
00162 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
00163 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
00164 #define pthread_mutex_init use_ast_pthread_mutex_init_instead_of_pthread_mutex_init
00165 #define pthread_mutex_destroy use_ast_pthread_mutex_destroy_instead_of_pthread_mutex_destroy
00166
00167 #else
00168
00169 #define AST_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
00170 #ifdef PTHREAD_MUTEX_FAST_NP
00171 #define AST_MUTEX_KIND PTHREAD_MUTEX_FAST_NP
00172 #else
00173 #define AST_MUTEX_KIND PTHREAD_NORMAL
00174 #endif
00175
00176 typedef pthread_mutex_t ast_mutex_t;
00177
00178 #define ast_mutex_lock(t) pthread_mutex_lock(t)
00179 #define ast_mutex_unlock(t) pthread_mutex_unlock(t)
00180 #define ast_mutex_trylock(t) pthread_mutex_trylock(t)
00181 #define ast_mutex_init(t) pthread_mutex_init(t, NULL)
00182 #define ast_pthread_mutex_init(t,a) pthread_mutex_init(t,a)
00183 #define ast_mutex_destroy(t) pthread_mutex_destroy(t)
00184
00185 #endif
00186
00187
00188 #endif