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