Add crash option
[asterisk/asterisk.git] / include / asterisk / lock.h
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * General Asterisk channel definitions.
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #ifndef _ASTERISK_LOCK_H
15 #define _ASTERISK_LOCK_H
16
17 #include <pthread.h>
18
19 #ifdef DEBUG_THREADS
20 #ifdef THREAD_CRASH
21 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
22 #endif
23
24
25 #include <errno.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <unistd.h>
29
30 // #define AST_MUTEX_INITIALIZER      PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
31 // #define AST_MUTEX_KIND             PTHREAD_MUTEX_RECURSIVE_NP
32 #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
33 #define AST_MUTEX_INITIALIZER         { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 }
34 #else
35 #ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
36 #define AST_MUTEX_INITIALIZER         { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 }
37 #else
38 #define AST_MUTEX_INITIALIZER         { PTHREAD_MUTEX_INITIALIZER, NULL, 0, NULL, 0 }
39 #endif
40 #endif
41 #ifdef PTHREAD_MUTEX_ERRORCHECK_NP
42 #define AST_MUTEX_KIND                PTHREAD_MUTEX_ERRORCHECK_NP
43 #else
44 #define AST_MUTEX_KIND                PTHREAD_MUTEX_ERRORCHECK
45 #endif
46
47 struct ast_mutex_info {
48         pthread_mutex_t mutex;
49         char *file;
50         int lineno;
51         char *func;
52         pthread_t thread;
53 };
54
55 typedef struct ast_mutex_info ast_mutex_t;
56
57 static inline int ast_mutex_init(ast_mutex_t *t) {
58         static pthread_mutexattr_t  attr;
59         static int  init = 1;
60         int res;
61         extern int  pthread_mutexattr_setkind_np(pthread_mutexattr_t *, int);
62
63         if (init) {
64                 pthread_mutexattr_init(&attr);
65                 pthread_mutexattr_setkind_np(&attr, AST_MUTEX_KIND);
66                 init = 0;
67         }
68         res = pthread_mutex_init(&t->mutex, &attr);
69         t->file = NULL;
70         t->lineno = 0;
71         t->func = 0;
72         t->thread  = 0;
73         return res;
74 }
75
76 static inline int ast_pthread_mutex_init(ast_mutex_t *t, pthread_mutexattr_t *attr) 
77 {
78         int res;
79         res = pthread_mutex_init(&t->mutex, attr);
80         t->file = NULL;
81         t->lineno = 0;
82         t->func = 0;
83         t->thread  = 0;
84         return res;
85 }
86
87 static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, ast_mutex_t *t) {
88         int res;
89         res = pthread_mutex_lock(&t->mutex);
90         if (!res) {
91                 t->file = filename;
92                 t->lineno = lineno;
93                 t->func = func;
94                 t->thread = pthread_self();
95         } else {
96                 fprintf(stderr, "%s line %d (%s): Error obtaining mutex: %s\n",
97                         filename, lineno, func, strerror(errno));
98 #ifdef THREAD_CRASH
99                 DO_THREAD_CRASH;
100 #endif
101         }
102         return res;
103 }
104
105 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
106
107 static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func, ast_mutex_t *t) {
108         int res;
109         res = pthread_mutex_trylock(&t->mutex);
110         if (!res) {
111                 t->file = filename;
112                 t->lineno = lineno;
113                 t->func = func;
114                 t->thread = pthread_self();
115         }
116         return res;
117 }
118
119 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
120
121 static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func, ast_mutex_t *t) {
122         int res;
123         /* Assumes lock is actually held */
124         t->file = NULL;
125         t->lineno = 0;
126         t->func = NULL;
127         t->thread = 0;
128         res = pthread_mutex_unlock(&t->mutex);
129         if (res) {
130                 fprintf(stderr, "%s line %d (%s): Error releasing mutex: %s\n", 
131                                 filename, lineno, func, strerror(res));
132 #ifdef THREAD_CRASH
133                 DO_THREAD_CRASH;
134 #endif
135         }
136         return res;
137 }
138
139 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
140
141 static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char *func, ast_mutex_t *t)
142 {
143         int res;
144         t->file = NULL;
145         t->lineno = 0;
146         t->func = NULL;
147         t->thread = 0;
148         res = pthread_mutex_destroy(&t->mutex);
149         if (res) 
150                 fprintf(stderr, "%s line %d (%s): Error destroying mutex: %s\n",
151                                 filename, lineno, func, strerror(res));
152         return res;
153 }
154
155 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
156
157 #else
158
159 #define AST_MUTEX_INITIALIZER      PTHREAD_MUTEX_INITIALIZER
160 #ifdef PTHREAD_MUTEX_FAST_NP
161 #define AST_MUTEX_KIND             PTHREAD_MUTEX_FAST_NP
162 #else
163 #define AST_MUTEX_KIND             PTHREAD_NORMAL
164 #endif
165
166 typedef pthread_mutex_t ast_mutex_t;
167
168 static inline int ast_mutex_lock(ast_mutex_t *t)
169 {
170         return pthread_mutex_lock(t);
171 }
172
173 static inline int ast_mutex_unlock(ast_mutex_t *t)
174 {
175         return pthread_mutex_unlock(t);
176 }
177
178 static inline int ast_mutex_trylock(ast_mutex_t *t)
179 {
180         return pthread_mutex_trylock(t);
181 }
182
183 static inline int ast_pthread_mutex_init(ast_mutex_t *t, const pthread_mutexattr_t *mutexattr)
184 {
185         return pthread_mutex_init(t, mutexattr);
186 }
187
188 static inline int ast_mutex_init(ast_mutex_t *t)
189 {
190         return pthread_mutex_init(t, NULL);
191 }
192
193 static inline int ast_mutex_destroy(ast_mutex_t *t)
194 {
195         return pthread_mutex_destroy(t);
196 }
197 #endif
198
199 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
200 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
201 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
202 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
203 #define pthread_mutex_init use_ast_pthread_mutex_init_instead_of_pthread_mutex_init
204 #define pthread_mutex_destroy use_ast_pthread_mutex_destroy_instead_of_pthread_mutex_destroy
205
206 #endif