Update locking for non-debug mode, too
[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 #define AST_PTHREADT_NULL (pthread_t) -1
20 #define AST_PTHREADT_STOP (pthread_t) -2
21
22 #ifdef DEBUG_THREADS
23
24 #ifdef THREAD_CRASH
25 #define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
26 #endif
27
28 #include <errno.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <unistd.h>
32
33 /* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes
34    and will not run without them. */
35
36 #define AST_MUTEX_INITIALIZER      PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
37 #define AST_MUTEX_KIND             PTHREAD_MUTEX_RECURSIVE_NP
38
39 struct ast_mutex_info {
40         pthread_mutex_t mutex;
41         char *file;
42         int lineno;
43         char *func;
44         pthread_t thread;
45 };
46
47 typedef struct ast_mutex_info ast_mutex_t;
48
49 static inline int ast_mutex_init(ast_mutex_t *t) {
50         static pthread_mutexattr_t  attr;
51         static int  init = 1;
52         int res;
53         extern int  pthread_mutexattr_setkind_np(pthread_mutexattr_t *, int);
54
55         if (init) {
56                 pthread_mutexattr_init(&attr);
57                 pthread_mutexattr_setkind_np(&attr, AST_MUTEX_KIND);
58                 init = 0;
59         }
60         res = pthread_mutex_init(&t->mutex, &attr);
61         t->file = NULL;
62         t->lineno = 0;
63         t->func = 0;
64         t->thread  = 0;
65         return res;
66 }
67
68 static inline int ast_pthread_mutex_init(ast_mutex_t *t, pthread_mutexattr_t *attr) 
69 {
70         int res;
71         res = pthread_mutex_init(&t->mutex, attr);
72         t->file = NULL;
73         t->lineno = 0;
74         t->func = 0;
75         t->thread  = 0;
76         return res;
77 }
78
79 static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, ast_mutex_t *t) {
80         int res;
81         res = pthread_mutex_lock(&t->mutex);
82         if (!res) {
83                 t->file = filename;
84                 t->lineno = lineno;
85                 t->func = func;
86                 t->thread = pthread_self();
87         } else {
88                 fprintf(stderr, "%s line %d (%s): Error obtaining mutex: %s\n",
89                         filename, lineno, func, strerror(errno));
90 #ifdef THREAD_CRASH
91                 DO_THREAD_CRASH;
92 #endif
93         }
94         return res;
95 }
96
97 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
98
99 static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func, ast_mutex_t *t) {
100         int res;
101         res = pthread_mutex_trylock(&t->mutex);
102         if (!res) {
103                 t->file = filename;
104                 t->lineno = lineno;
105                 t->func = func;
106                 t->thread = pthread_self();
107         }
108         return res;
109 }
110
111 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
112
113 static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func, ast_mutex_t *t) {
114         int res;
115         /* Assumes lock is actually held */
116         t->file = NULL;
117         t->lineno = 0;
118         t->func = NULL;
119         t->thread = 0;
120         res = pthread_mutex_unlock(&t->mutex);
121         if (res) {
122                 fprintf(stderr, "%s line %d (%s): Error releasing mutex: %s\n", 
123                                 filename, lineno, func, strerror(res));
124 #ifdef THREAD_CRASH
125                 DO_THREAD_CRASH;
126 #endif
127         }
128         return res;
129 }
130
131 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
132
133 static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char *func, ast_mutex_t *t)
134 {
135         int res;
136         t->file = NULL;
137         t->lineno = 0;
138         t->func = NULL;
139         t->thread = 0;
140         res = pthread_mutex_destroy(&t->mutex);
141         if (res) 
142                 fprintf(stderr, "%s line %d (%s): Error destroying mutex: %s\n",
143                                 filename, lineno, func, strerror(res));
144         return res;
145 }
146
147 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
148
149 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
150 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
151 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
152 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
153 #define pthread_mutex_init use_ast_pthread_mutex_init_instead_of_pthread_mutex_init
154 #define pthread_mutex_destroy use_ast_pthread_mutex_destroy_instead_of_pthread_mutex_destroy
155
156 #else /* DEBUG_THREADS */
157
158 /* From now on, Asterisk REQUIRES Recursive (not error checking) mutexes
159    and will not run without them. */
160 #define AST_MUTEX_INITIALIZER      PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
161 #define AST_MUTEX_KIND             PTHREAD_MUTEX_RECURSIVE_NP
162
163 typedef pthread_mutex_t ast_mutex_t;
164
165 #define ast_mutex_lock(t) pthread_mutex_lock(t)
166 #define ast_mutex_unlock(t) pthread_mutex_unlock(t)
167 #define ast_mutex_trylock(t) pthread_mutex_trylock(t)
168 static inline int ast_mutex_init(ast_mutex_t *t)
169 {
170         pthread_mutexattr_t attr;
171         pthread_mutexattr_init(&attr);
172         pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
173         return pthread_mutex_init(t, &attr);
174 }
175 #define ast_mutex_init(t) pthread_mutex_init(t, NULL)
176 #define ast_pthread_mutex_init(t,a) pthread_mutex_init(t,a)
177 #define ast_mutex_destroy(t) pthread_mutex_destroy(t)
178
179 #endif /* DEBUG_THREADS */
180
181
182 #endif