aba263c09fc87ed5b3d282ad44bf50ef1888c3c7
[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 // #define AST_MUTEX_INITIALIZER      PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
34 // #define AST_MUTEX_KIND             PTHREAD_MUTEX_RECURSIVE_NP
35 #ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
36 #define AST_MUTEX_INITIALIZER         { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 }
37 #else
38 #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
39 #define AST_MUTEX_INITIALIZER         { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, NULL, 0, NULL, 0 }
40 #else
41 #define AST_MUTEX_INITIALIZER         { PTHREAD_MUTEX_INITIALIZER, NULL, 0, NULL, 0 }
42 #endif
43 #endif
44 #ifdef PTHREAD_MUTEX_ERRORCHECK_NP
45 #define AST_MUTEX_KIND                PTHREAD_MUTEX_ERRORCHECK_NP
46 #else
47 #define AST_MUTEX_KIND                PTHREAD_MUTEX_ERRORCHECK
48 #endif
49
50 struct ast_mutex_info {
51         pthread_mutex_t mutex;
52         char *file;
53         int lineno;
54         char *func;
55         pthread_t thread;
56 };
57
58 typedef struct ast_mutex_info ast_mutex_t;
59
60 static inline int ast_mutex_init(ast_mutex_t *t) {
61         static pthread_mutexattr_t  attr;
62         static int  init = 1;
63         int res;
64         extern int  pthread_mutexattr_setkind_np(pthread_mutexattr_t *, int);
65
66         if (init) {
67                 pthread_mutexattr_init(&attr);
68                 pthread_mutexattr_setkind_np(&attr, AST_MUTEX_KIND);
69                 init = 0;
70         }
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_init(ast_mutex_t *t, pthread_mutexattr_t *attr) 
80 {
81         int res;
82         res = pthread_mutex_init(&t->mutex, attr);
83         t->file = NULL;
84         t->lineno = 0;
85         t->func = 0;
86         t->thread  = 0;
87         return res;
88 }
89
90 static inline int __ast_pthread_mutex_lock(char *filename, int lineno, char *func, ast_mutex_t *t) {
91         int res;
92         res = pthread_mutex_lock(&t->mutex);
93         if (!res) {
94                 t->file = filename;
95                 t->lineno = lineno;
96                 t->func = func;
97                 t->thread = pthread_self();
98         } else {
99                 fprintf(stderr, "%s line %d (%s): Error obtaining mutex: %s\n",
100                         filename, lineno, func, strerror(errno));
101 #ifdef THREAD_CRASH
102                 DO_THREAD_CRASH;
103 #endif
104         }
105         return res;
106 }
107
108 #define ast_mutex_lock(a) __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
109
110 static inline int __ast_pthread_mutex_trylock(char *filename, int lineno, char *func, ast_mutex_t *t) {
111         int res;
112         res = pthread_mutex_trylock(&t->mutex);
113         if (!res) {
114                 t->file = filename;
115                 t->lineno = lineno;
116                 t->func = func;
117                 t->thread = pthread_self();
118         }
119         return res;
120 }
121
122 #define ast_mutex_trylock(a) __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
123
124 static inline int __ast_pthread_mutex_unlock(char *filename, int lineno, char *func, ast_mutex_t *t) {
125         int res;
126         /* Assumes lock is actually held */
127         t->file = NULL;
128         t->lineno = 0;
129         t->func = NULL;
130         t->thread = 0;
131         res = pthread_mutex_unlock(&t->mutex);
132         if (res) {
133                 fprintf(stderr, "%s line %d (%s): Error releasing mutex: %s\n", 
134                                 filename, lineno, func, strerror(res));
135 #ifdef THREAD_CRASH
136                 DO_THREAD_CRASH;
137 #endif
138         }
139         return res;
140 }
141
142 #define ast_mutex_unlock(a) __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
143
144 static inline int __ast_pthread_mutex_destroy(char *filename, int lineno, char *func, ast_mutex_t *t)
145 {
146         int res;
147         t->file = NULL;
148         t->lineno = 0;
149         t->func = NULL;
150         t->thread = 0;
151         res = pthread_mutex_destroy(&t->mutex);
152         if (res) 
153                 fprintf(stderr, "%s line %d (%s): Error destroying mutex: %s\n",
154                                 filename, lineno, func, strerror(res));
155         return res;
156 }
157
158 #define ast_mutex_destroy(a) __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, a)
159
160 #define pthread_mutex_t use_ast_mutex_t_instead_of_pthread_mutex_t
161 #define pthread_mutex_lock use_ast_mutex_lock_instead_of_pthread_mutex_lock
162 #define pthread_mutex_unlock use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
163 #define pthread_mutex_trylock use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
164 #define pthread_mutex_init use_ast_pthread_mutex_init_instead_of_pthread_mutex_init
165 #define pthread_mutex_destroy use_ast_pthread_mutex_destroy_instead_of_pthread_mutex_destroy
166
167 #else /* DEBUG_THREADS */
168
169 #define AST_MUTEX_INITIALIZER      PTHREAD_MUTEX_INITIALIZER
170 #ifdef PTHREAD_MUTEX_FAST_NP
171 #define AST_MUTEX_KIND             PTHREAD_MUTEX_FAST_NP
172 #else
173 #define AST_MUTEX_KIND             PTHREAD_NORMAL
174 #endif
175
176 typedef pthread_mutex_t ast_mutex_t;
177
178 #define ast_mutex_lock(t) pthread_mutex_lock(t)
179 #define ast_mutex_unlock(t) pthread_mutex_unlock(t)
180 #define ast_mutex_trylock(t) pthread_mutex_trylock(t)
181 #define ast_mutex_init(t) pthread_mutex_init(t, NULL)
182 #define ast_pthread_mutex_init(t,a) pthread_mutex_init(t,a)
183 #define ast_mutex_destroy(t) pthread_mutex_destroy(t)
184
185 #endif /* DEBUG_THREADS */
186
187
188 #endif