Review Board 1.7.16


asterisk/lock.h: Fix syntax errors for non-gcc OSX with 64-bit integers

Review Request #4436 - Created Feb. 19, 2015 and submitted

Corey Farrell
11, 13, trunk
ASTERISK-24814
Reviewers
asterisk-dev
Asterisk
asterisk/lock.h: Add a couple of missing closing brackets / parenthesis.
Looked at the source.  I don't know what compiler would match the #if conditions.

Diff revision 1 (Latest)

  1. /branches/11/include/asterisk/lock.h: Loading...
/branches/11/include/asterisk/lock.h
Revision 431994 New Change
1
/*
1
/*
2
 * Asterisk -- An open source telephony toolkit.
2
 * Asterisk -- An open source telephony toolkit.
3
 *
3
 *
4
 * Copyright (C) 1999 - 2010, Digium, Inc.
4
 * Copyright (C) 1999 - 2010, Digium, Inc.
5
 *
5
 *
6
 * Mark Spencer <markster@digium.com>
6
 * Mark Spencer <markster@digium.com>
7
 *
7
 *
8
 * See http://www.asterisk.org for more information about
8
 * See http://www.asterisk.org for more information about
9
 * the Asterisk project. Please do not directly contact
9
 * the Asterisk project. Please do not directly contact
10
 * any of the maintainers of this project for assistance;
10
 * any of the maintainers of this project for assistance;
11
 * the project provides a web site, mailing lists and IRC
11
 * the project provides a web site, mailing lists and IRC
12
 * channels for your use.
12
 * channels for your use.
13
 *
13
 *
14
 * This program is free software, distributed under the terms of
14
 * This program is free software, distributed under the terms of
15
 * the GNU General Public License Version 2. See the LICENSE file
15
 * the GNU General Public License Version 2. See the LICENSE file
16
 * at the top of the source tree.
16
 * at the top of the source tree.
17
 */
17
 */
18

    
   
18

   
19
/*! \file
19
/*! \file
20
 * \brief Asterisk locking-related definitions:
20
 * \brief Asterisk locking-related definitions:
21
 * - ast_mutex_t, ast_rwlock_t and related functions;
21
 * - ast_mutex_t, ast_rwlock_t and related functions;
22
 * - atomic arithmetic instructions;
22
 * - atomic arithmetic instructions;
23
 * - wrappers for channel locking.
23
 * - wrappers for channel locking.
24
 *
24
 *
25
 * - See \ref LockDef
25
 * - See \ref LockDef
26
 */
26
 */
27

    
   
27

   
28
/*! \page LockDef Asterisk thread locking models
28
/*! \page LockDef Asterisk thread locking models
29
 *
29
 *
30
 * This file provides different implementation of the functions,
30
 * This file provides different implementation of the functions,
31
 * depending on the platform, the use of DEBUG_THREADS, and the way
31
 * depending on the platform, the use of DEBUG_THREADS, and the way
32
 * module-level mutexes are initialized.
32
 * module-level mutexes are initialized.
33
 *
33
 *
34
 *  - \b static: the mutex is assigned the value AST_MUTEX_INIT_VALUE
34
 *  - \b static: the mutex is assigned the value AST_MUTEX_INIT_VALUE
35
 *        this is done at compile time, and is the way used on Linux.
35
 *        this is done at compile time, and is the way used on Linux.
36
 *        This method is not applicable to all platforms e.g. when the
36
 *        This method is not applicable to all platforms e.g. when the
37
 *        initialization needs that some code is run.
37
 *        initialization needs that some code is run.
38
 *
38
 *
39
 *  - \b through constructors: for each mutex, a constructor function is
39
 *  - \b through constructors: for each mutex, a constructor function is
40
 *        defined, which then runs when the program (or the module)
40
 *        defined, which then runs when the program (or the module)
41
 *        starts. The problem with this approach is that there is a
41
 *        starts. The problem with this approach is that there is a
42
 *        lot of code duplication (a new block of code is created for
42
 *        lot of code duplication (a new block of code is created for
43
 *        each mutex). Also, it does not prevent a user from declaring
43
 *        each mutex). Also, it does not prevent a user from declaring
44
 *        a global mutex without going through the wrapper macros,
44
 *        a global mutex without going through the wrapper macros,
45
 *        so sane programming practices are still required.
45
 *        so sane programming practices are still required.
46
 */
46
 */
47

    
   
47

   
48
#ifndef _ASTERISK_LOCK_H
48
#ifndef _ASTERISK_LOCK_H
49
#define _ASTERISK_LOCK_H
49
#define _ASTERISK_LOCK_H
50

    
   
50

   
51
#include <pthread.h>
51
#include <pthread.h>
52
#include <time.h>
52
#include <time.h>
53
#include <sys/param.h>
53
#include <sys/param.h>
54
#ifdef HAVE_BKTR
54
#ifdef HAVE_BKTR
55
#include <execinfo.h>
55
#include <execinfo.h>
56
#endif
56
#endif
57

    
   
57

   
58
#ifndef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
58
#ifndef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
59
#include "asterisk/time.h"
59
#include "asterisk/time.h"
60
#endif
60
#endif
61

    
   
61

   
62
#include "asterisk/logger.h"
62
#include "asterisk/logger.h"
63
#include "asterisk/compiler.h"
63
#include "asterisk/compiler.h"
64

    
   
64

   
65
#define AST_PTHREADT_NULL (pthread_t) -1
65
#define AST_PTHREADT_NULL (pthread_t) -1
66
#define AST_PTHREADT_STOP (pthread_t) -2
66
#define AST_PTHREADT_STOP (pthread_t) -2
67

    
   
67

   
68
#if (defined(SOLARIS) || defined(BSD))
68
#if (defined(SOLARIS) || defined(BSD))
69
#define AST_MUTEX_INIT_W_CONSTRUCTORS
69
#define AST_MUTEX_INIT_W_CONSTRUCTORS
70
#endif /* SOLARIS || BSD */
70
#endif /* SOLARIS || BSD */
71

    
   
71

   
72
/* Asterisk REQUIRES recursive (not error checking) mutexes
72
/* Asterisk REQUIRES recursive (not error checking) mutexes
73
   and will not run without them. */
73
   and will not run without them. */
74
#if defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(HAVE_PTHREAD_MUTEX_RECURSIVE_NP)
74
#if defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) && defined(HAVE_PTHREAD_MUTEX_RECURSIVE_NP)
75
#define PTHREAD_MUTEX_INIT_VALUE	PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
75
#define PTHREAD_MUTEX_INIT_VALUE	PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
76
#define AST_MUTEX_KIND			PTHREAD_MUTEX_RECURSIVE_NP
76
#define AST_MUTEX_KIND			PTHREAD_MUTEX_RECURSIVE_NP
77
#else
77
#else
78
#define PTHREAD_MUTEX_INIT_VALUE	PTHREAD_MUTEX_INITIALIZER
78
#define PTHREAD_MUTEX_INIT_VALUE	PTHREAD_MUTEX_INITIALIZER
79
#define AST_MUTEX_KIND			PTHREAD_MUTEX_RECURSIVE
79
#define AST_MUTEX_KIND			PTHREAD_MUTEX_RECURSIVE
80
#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
80
#endif /* PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP */
81

    
   
81

   
82
#ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
82
#ifdef HAVE_PTHREAD_RWLOCK_INITIALIZER
83
#define __AST_RWLOCK_INIT_VALUE		PTHREAD_RWLOCK_INITIALIZER
83
#define __AST_RWLOCK_INIT_VALUE		PTHREAD_RWLOCK_INITIALIZER
84
#else  /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
84
#else  /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
85
#define __AST_RWLOCK_INIT_VALUE		{0}
85
#define __AST_RWLOCK_INIT_VALUE		{0}
86
#endif /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
86
#endif /* HAVE_PTHREAD_RWLOCK_INITIALIZER */
87

    
   
87

   
88
#ifdef HAVE_BKTR
88
#ifdef HAVE_BKTR
89
#define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
89
#define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
90
#else
90
#else
91
#define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
91
#define AST_LOCK_TRACK_INIT_VALUE { { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INIT_VALUE }
92
#endif
92
#endif
93

    
   
93

   
94
#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, NULL, 1 }
94
#define AST_MUTEX_INIT_VALUE { PTHREAD_MUTEX_INIT_VALUE, NULL, 1 }
95
#define AST_MUTEX_INIT_VALUE_NOTRACKING { PTHREAD_MUTEX_INIT_VALUE, NULL, 0 }
95
#define AST_MUTEX_INIT_VALUE_NOTRACKING { PTHREAD_MUTEX_INIT_VALUE, NULL, 0 }
96

    
   
96

   
97
#define AST_RWLOCK_INIT_VALUE { __AST_RWLOCK_INIT_VALUE, NULL, 1 }
97
#define AST_RWLOCK_INIT_VALUE { __AST_RWLOCK_INIT_VALUE, NULL, 1 }
98
#define AST_RWLOCK_INIT_VALUE_NOTRACKING { __AST_RWLOCK_INIT_VALUE, NULL, 0 }
98
#define AST_RWLOCK_INIT_VALUE_NOTRACKING { __AST_RWLOCK_INIT_VALUE, NULL, 0 }
99

    
   
99

   
100
#define AST_MAX_REENTRANCY 10
100
#define AST_MAX_REENTRANCY 10
101

    
   
101

   
102
struct ast_channel;
102
struct ast_channel;
103

    
   
103

   
104
/*!
104
/*!
105
 * \brief Lock tracking information.
105
 * \brief Lock tracking information.
106
 *
106
 *
107
 * \note Any changes to this struct MUST be reflected in the
107
 * \note Any changes to this struct MUST be reflected in the
108
 * lock.c:restore_lock_tracking() function.
108
 * lock.c:restore_lock_tracking() function.
109
 */
109
 */
110
struct ast_lock_track {
110
struct ast_lock_track {
111
	const char *file[AST_MAX_REENTRANCY];
111
	const char *file[AST_MAX_REENTRANCY];
112
	int lineno[AST_MAX_REENTRANCY];
112
	int lineno[AST_MAX_REENTRANCY];
113
	int reentrancy;
113
	int reentrancy;
114
	const char *func[AST_MAX_REENTRANCY];
114
	const char *func[AST_MAX_REENTRANCY];
115
	pthread_t thread[AST_MAX_REENTRANCY];
115
	pthread_t thread[AST_MAX_REENTRANCY];
116
#ifdef HAVE_BKTR
116
#ifdef HAVE_BKTR
117
	struct ast_bt backtrace[AST_MAX_REENTRANCY];
117
	struct ast_bt backtrace[AST_MAX_REENTRANCY];
118
#endif
118
#endif
119
	pthread_mutex_t reentr_mutex;
119
	pthread_mutex_t reentr_mutex;
120
};
120
};
121

    
   
121

   
122
/*! \brief Structure for mutex and tracking information.
122
/*! \brief Structure for mutex and tracking information.
123
 *
123
 *
124
 * We have tracking information in this structure regardless of DEBUG_THREADS being enabled.
124
 * We have tracking information in this structure regardless of DEBUG_THREADS being enabled.
125
 * The information will just be ignored in the core if a module does not request it..
125
 * The information will just be ignored in the core if a module does not request it..
126
 */
126
 */
127
struct ast_mutex_info {
127
struct ast_mutex_info {
128
	pthread_mutex_t mutex;
128
	pthread_mutex_t mutex;
129
	/*! Track which thread holds this mutex */
129
	/*! Track which thread holds this mutex */
130
	struct ast_lock_track *track;
130
	struct ast_lock_track *track;
131
	unsigned int tracking:1;
131
	unsigned int tracking:1;
132
};
132
};
133

    
   
133

   
134
/*! \brief Structure for rwlock and tracking information.
134
/*! \brief Structure for rwlock and tracking information.
135
 *
135
 *
136
 * We have tracking information in this structure regardless of DEBUG_THREADS being enabled.
136
 * We have tracking information in this structure regardless of DEBUG_THREADS being enabled.
137
 * The information will just be ignored in the core if a module does not request it..
137
 * The information will just be ignored in the core if a module does not request it..
138
 */
138
 */
139
struct ast_rwlock_info {
139
struct ast_rwlock_info {
140
	pthread_rwlock_t lock;
140
	pthread_rwlock_t lock;
141
	/*! Track which thread holds this lock */
141
	/*! Track which thread holds this lock */
142
	struct ast_lock_track *track;
142
	struct ast_lock_track *track;
143
	unsigned int tracking:1;
143
	unsigned int tracking:1;
144
};
144
};
145

    
   
145

   
146
typedef struct ast_mutex_info ast_mutex_t;
146
typedef struct ast_mutex_info ast_mutex_t;
147

    
   
147

   
148
typedef struct ast_rwlock_info ast_rwlock_t;
148
typedef struct ast_rwlock_info ast_rwlock_t;
149

    
   
149

   
150
typedef pthread_cond_t ast_cond_t;
150
typedef pthread_cond_t ast_cond_t;
151

    
   
151

   
152
int __ast_pthread_mutex_init(int tracking, const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t);
152
int __ast_pthread_mutex_init(int tracking, const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t);
153
int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t);
153
int __ast_pthread_mutex_destroy(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t);
154
int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func, const char* mutex_name, ast_mutex_t *t);
154
int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func, const char* mutex_name, ast_mutex_t *t);
155
int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, const char* mutex_name, ast_mutex_t *t);
155
int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, const char* mutex_name, ast_mutex_t *t);
156
int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t);
156
int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t);
157

    
   
157

   
158
#define ast_mutex_init(pmutex)            __ast_pthread_mutex_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
158
#define ast_mutex_init(pmutex)            __ast_pthread_mutex_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
159
#define ast_mutex_init_notracking(pmutex) __ast_pthread_mutex_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
159
#define ast_mutex_init_notracking(pmutex) __ast_pthread_mutex_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
160
#define ast_mutex_destroy(a)              __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
160
#define ast_mutex_destroy(a)              __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
161
#define ast_mutex_lock(a)                 __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
161
#define ast_mutex_lock(a)                 __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
162
#define ast_mutex_unlock(a)               __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
162
#define ast_mutex_unlock(a)               __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
163
#define ast_mutex_trylock(a)              __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
163
#define ast_mutex_trylock(a)              __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
164

    
   
164

   
165

    
   
165

   
166
int __ast_cond_init(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr);
166
int __ast_cond_init(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond, pthread_condattr_t *cond_attr);
167
int __ast_cond_signal(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond);
167
int __ast_cond_signal(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond);
168
int __ast_cond_broadcast(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond);
168
int __ast_cond_broadcast(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond);
169
int __ast_cond_destroy(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond);
169
int __ast_cond_destroy(const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond);
170
int __ast_cond_wait(const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t);
170
int __ast_cond_wait(const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t);
171
int __ast_cond_timedwait(const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime);
171
int __ast_cond_timedwait(const char *filename, int lineno, const char *func, const char *cond_name, const char *mutex_name, ast_cond_t *cond, ast_mutex_t *t, const struct timespec *abstime);
172

    
   
172

   
173
#define ast_cond_init(cond, attr)             __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
173
#define ast_cond_init(cond, attr)             __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
174
#define ast_cond_destroy(cond)                __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
174
#define ast_cond_destroy(cond)                __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
175
#define ast_cond_signal(cond)                 __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
175
#define ast_cond_signal(cond)                 __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
176
#define ast_cond_broadcast(cond)              __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
176
#define ast_cond_broadcast(cond)              __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
177
#define ast_cond_wait(cond, mutex)            __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
177
#define ast_cond_wait(cond, mutex)            __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
178
#define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
178
#define ast_cond_timedwait(cond, mutex, time) __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
179

    
   
179

   
180

    
   
180

   
181
int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t);
181
int __ast_rwlock_init(int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t);
182
int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t);
182
int __ast_rwlock_destroy(const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t);
183
int __ast_rwlock_unlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
183
int __ast_rwlock_unlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
184
int __ast_rwlock_rdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
184
int __ast_rwlock_rdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
185
int __ast_rwlock_wrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
185
int __ast_rwlock_wrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
186
int __ast_rwlock_timedrdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout);
186
int __ast_rwlock_timedrdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout);
187
int __ast_rwlock_timedwrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout);
187
int __ast_rwlock_timedwrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout);
188
int __ast_rwlock_tryrdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
188
int __ast_rwlock_tryrdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
189
int __ast_rwlock_trywrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
189
int __ast_rwlock_trywrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name);
190

    
   
190

   
191
/*!
191
/*!
192
 * \brief wrapper for rwlock with tracking enabled
192
 * \brief wrapper for rwlock with tracking enabled
193
 * \return 0 on success, non zero for error
193
 * \return 0 on success, non zero for error
194
 * \since 1.6.1
194
 * \since 1.6.1
195
 */
195
 */
196
#define ast_rwlock_init(rwlock)            __ast_rwlock_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
196
#define ast_rwlock_init(rwlock)            __ast_rwlock_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
197

    
   
197

   
198
/*!
198
/*!
199
 * \brief wrapper for ast_rwlock_init with tracking disabled
199
 * \brief wrapper for ast_rwlock_init with tracking disabled
200
 * \return 0 on success, non zero for error
200
 * \return 0 on success, non zero for error
201
 * \since 1.6.1
201
 * \since 1.6.1
202
 */
202
 */
203
#define ast_rwlock_init_notracking(rwlock) __ast_rwlock_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
203
#define ast_rwlock_init_notracking(rwlock) __ast_rwlock_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
204

    
   
204

   
205
#define ast_rwlock_destroy(rwlock)         __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
205
#define ast_rwlock_destroy(rwlock)         __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
206
#define ast_rwlock_unlock(a)               __ast_rwlock_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
206
#define ast_rwlock_unlock(a)               __ast_rwlock_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
207
#define ast_rwlock_rdlock(a)               __ast_rwlock_rdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
207
#define ast_rwlock_rdlock(a)               __ast_rwlock_rdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
208
#define ast_rwlock_wrlock(a)               __ast_rwlock_wrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
208
#define ast_rwlock_wrlock(a)               __ast_rwlock_wrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
209
#define ast_rwlock_tryrdlock(a)            __ast_rwlock_tryrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
209
#define ast_rwlock_tryrdlock(a)            __ast_rwlock_tryrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
210
#define ast_rwlock_trywrlock(a)            __ast_rwlock_trywrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
210
#define ast_rwlock_trywrlock(a)            __ast_rwlock_trywrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
211
#define ast_rwlock_timedrdlock(a, b)       __ast_rwlock_timedrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)
211
#define ast_rwlock_timedrdlock(a, b)       __ast_rwlock_timedrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)
212
#define ast_rwlock_timedwrlock(a, b)       __ast_rwlock_timedwrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)
212
#define ast_rwlock_timedwrlock(a, b)       __ast_rwlock_timedwrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)
213

    
   
213

   
214
#define	ROFFSET	((lt->reentrancy > 0) ? (lt->reentrancy-1) : 0)
214
#define	ROFFSET	((lt->reentrancy > 0) ? (lt->reentrancy-1) : 0)
215

    
   
215

   
216
#ifdef DEBUG_THREADS
216
#ifdef DEBUG_THREADS
217

    
   
217

   
218
#define __ast_mutex_logger(...)  do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
218
#define __ast_mutex_logger(...)  do { if (canlog) ast_log(LOG_ERROR, __VA_ARGS__); else fprintf(stderr, __VA_ARGS__); } while (0)
219

    
   
219

   
220
#ifdef THREAD_CRASH
220
#ifdef THREAD_CRASH
221
#define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
221
#define DO_THREAD_CRASH do { *((int *)(0)) = 1; } while(0)
222
#else
222
#else
223
#define DO_THREAD_CRASH do { } while (0)
223
#define DO_THREAD_CRASH do { } while (0)
224
#endif
224
#endif
225

    
   
225

   
226
#include <errno.h>
226
#include <errno.h>
227

    
   
227

   
228
enum ast_lock_type {
228
enum ast_lock_type {
229
	AST_MUTEX,
229
	AST_MUTEX,
230
	AST_RDLOCK,
230
	AST_RDLOCK,
231
	AST_WRLOCK,
231
	AST_WRLOCK,
232
};
232
};
233

    
   
233

   
234
/*!
234
/*!
235
 * \brief Store lock info for the current thread
235
 * \brief Store lock info for the current thread
236
 *
236
 *
237
 * This function gets called in ast_mutex_lock() and ast_mutex_trylock() so
237
 * This function gets called in ast_mutex_lock() and ast_mutex_trylock() so
238
 * that information about this lock can be stored in this thread's
238
 * that information about this lock can be stored in this thread's
239
 * lock info struct.  The lock is marked as pending as the thread is waiting
239
 * lock info struct.  The lock is marked as pending as the thread is waiting
240
 * on the lock.  ast_mark_lock_acquired() will mark it as held by this thread.
240
 * on the lock.  ast_mark_lock_acquired() will mark it as held by this thread.
241
 */
241
 */
242
#if !defined(LOW_MEMORY)
242
#if !defined(LOW_MEMORY)
243
#ifdef HAVE_BKTR
243
#ifdef HAVE_BKTR
244
void ast_store_lock_info(enum ast_lock_type type, const char *filename,
244
void ast_store_lock_info(enum ast_lock_type type, const char *filename,
245
	int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt);
245
	int line_num, const char *func, const char *lock_name, void *lock_addr, struct ast_bt *bt);
246
#else
246
#else
247
void ast_store_lock_info(enum ast_lock_type type, const char *filename,
247
void ast_store_lock_info(enum ast_lock_type type, const char *filename,
248
	int line_num, const char *func, const char *lock_name, void *lock_addr);
248
	int line_num, const char *func, const char *lock_name, void *lock_addr);
249
#endif /* HAVE_BKTR */
249
#endif /* HAVE_BKTR */
250

    
   
250

   
251
#else
251
#else
252

    
   
252

   
253
#ifdef HAVE_BKTR
253
#ifdef HAVE_BKTR
254
#define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS,BUD)
254
#define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS,BUD)
255
#else
255
#else
256
#define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
256
#define ast_store_lock_info(I,DONT,CARE,ABOUT,THE,PARAMETERS)
257
#endif /* HAVE_BKTR */
257
#endif /* HAVE_BKTR */
258
#endif /* !defined(LOW_MEMORY) */
258
#endif /* !defined(LOW_MEMORY) */
259

    
   
259

   
260
/*!
260
/*!
261
 * \brief Mark the last lock as acquired
261
 * \brief Mark the last lock as acquired
262
 */
262
 */
263
#if !defined(LOW_MEMORY)
263
#if !defined(LOW_MEMORY)
264
void ast_mark_lock_acquired(void *lock_addr);
264
void ast_mark_lock_acquired(void *lock_addr);
265
#else
265
#else
266
#define ast_mark_lock_acquired(ignore)
266
#define ast_mark_lock_acquired(ignore)
267
#endif
267
#endif
268

    
   
268

   
269
/*!
269
/*!
270
 * \brief Mark the last lock as failed (trylock)
270
 * \brief Mark the last lock as failed (trylock)
271
 */
271
 */
272
#if !defined(LOW_MEMORY)
272
#if !defined(LOW_MEMORY)
273
void ast_mark_lock_failed(void *lock_addr);
273
void ast_mark_lock_failed(void *lock_addr);
274
#else
274
#else
275
#define ast_mark_lock_failed(ignore)
275
#define ast_mark_lock_failed(ignore)
276
#endif
276
#endif
277

    
   
277

   
278
/*!
278
/*!
279
 * \brief remove lock info for the current thread
279
 * \brief remove lock info for the current thread
280
 *
280
 *
281
 * this gets called by ast_mutex_unlock so that information on the lock can
281
 * this gets called by ast_mutex_unlock so that information on the lock can
282
 * be removed from the current thread's lock info struct.
282
 * be removed from the current thread's lock info struct.
283
 */
283
 */
284
#if !defined(LOW_MEMORY)
284
#if !defined(LOW_MEMORY)
285
#ifdef HAVE_BKTR
285
#ifdef HAVE_BKTR
286
void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt);
286
void ast_remove_lock_info(void *lock_addr, struct ast_bt *bt);
287
#else
287
#else
288
void ast_remove_lock_info(void *lock_addr);
288
void ast_remove_lock_info(void *lock_addr);
289
#endif /* HAVE_BKTR */
289
#endif /* HAVE_BKTR */
290
void ast_suspend_lock_info(void *lock_addr);
290
void ast_suspend_lock_info(void *lock_addr);
291
void ast_restore_lock_info(void *lock_addr);
291
void ast_restore_lock_info(void *lock_addr);
292
#else
292
#else
293
#ifdef HAVE_BKTR
293
#ifdef HAVE_BKTR
294
#define ast_remove_lock_info(ignore,me)
294
#define ast_remove_lock_info(ignore,me)
295
#else
295
#else
296
#define ast_remove_lock_info(ignore)
296
#define ast_remove_lock_info(ignore)
297
#endif /* HAVE_BKTR */
297
#endif /* HAVE_BKTR */
298
#define ast_suspend_lock_info(ignore);
298
#define ast_suspend_lock_info(ignore);
299
#define ast_restore_lock_info(ignore);
299
#define ast_restore_lock_info(ignore);
300
#endif /* !defined(LOW_MEMORY) */
300
#endif /* !defined(LOW_MEMORY) */
301

    
   
301

   
302
/*!
302
/*!
303
 * \brief log info for the current lock with ast_log().
303
 * \brief log info for the current lock with ast_log().
304
 *
304
 *
305
 * this function would be mostly for debug. If you come across a lock
305
 * this function would be mostly for debug. If you come across a lock
306
 * that is unexpectedly but momentarily locked, and you wonder who
306
 * that is unexpectedly but momentarily locked, and you wonder who
307
 * are fighting with for the lock, this routine could be called, IF
307
 * are fighting with for the lock, this routine could be called, IF
308
 * you have the thread debugging stuff turned on.
308
 * you have the thread debugging stuff turned on.
309
 * \param this_lock_addr lock address to return lock information
309
 * \param this_lock_addr lock address to return lock information
310
 * \since 1.6.1
310
 * \since 1.6.1
311
 */
311
 */
312
void log_show_lock(void *this_lock_addr);
312
void log_show_lock(void *this_lock_addr);
313

    
   
313

   
314
/*!
314
/*!
315
 * \brief retrieve lock info for the specified mutex
315
 * \brief retrieve lock info for the specified mutex
316
 *
316
 *
317
 * this gets called during deadlock avoidance, so that the information may
317
 * this gets called during deadlock avoidance, so that the information may
318
 * be preserved as to what location originally acquired the lock.
318
 * be preserved as to what location originally acquired the lock.
319
 */
319
 */
320
#if !defined(LOW_MEMORY)
320
#if !defined(LOW_MEMORY)
321
int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, int *lineno, char *func, size_t func_size, char *mutex_name, size_t mutex_name_size);
321
int ast_find_lock_info(void *lock_addr, char *filename, size_t filename_size, int *lineno, char *func, size_t func_size, char *mutex_name, size_t mutex_name_size);
322
#else
322
#else
323
#define ast_find_lock_info(a,b,c,d,e,f,g,h) -1
323
#define ast_find_lock_info(a,b,c,d,e,f,g,h) -1
324
#endif
324
#endif
325

    
   
325

   
326
/*!
326
/*!
327
 * \brief Unlock a lock briefly
327
 * \brief Unlock a lock briefly
328
 *
328
 *
329
 * used during deadlock avoidance, to preserve the original location where
329
 * used during deadlock avoidance, to preserve the original location where
330
 * a lock was originally acquired.
330
 * a lock was originally acquired.
331
 */
331
 */
332
#define CHANNEL_DEADLOCK_AVOIDANCE(chan) \
332
#define CHANNEL_DEADLOCK_AVOIDANCE(chan) \
333
	do { \
333
	do { \
334
		char __filename[80], __func[80], __mutex_name[80]; \
334
		char __filename[80], __func[80], __mutex_name[80]; \
335
		int __lineno; \
335
		int __lineno; \
336
		int __res = ast_find_lock_info(ao2_object_get_lockaddr(chan), __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
336
		int __res = ast_find_lock_info(ao2_object_get_lockaddr(chan), __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
337
		int __res2 = ast_channel_unlock(chan); \
337
		int __res2 = ast_channel_unlock(chan); \
338
		usleep(1); \
338
		usleep(1); \
339
		if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
339
		if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
340
			if (__res2) { \
340
			if (__res2) { \
341
				ast_log(LOG_WARNING, "Could not unlock channel '%s': %s and no lock info found!  I will NOT try to relock.\n", #chan, strerror(__res2)); \
341
				ast_log(LOG_WARNING, "Could not unlock channel '%s': %s and no lock info found!  I will NOT try to relock.\n", #chan, strerror(__res2)); \
342
			} else { \
342
			} else { \
343
				ast_channel_lock(chan); \
343
				ast_channel_lock(chan); \
344
			} \
344
			} \
345
		} else { \
345
		} else { \
346
			if (__res2) { \
346
			if (__res2) { \
347
				ast_log(LOG_WARNING, "Could not unlock channel '%s': %s.  {{{Originally locked at %s line %d: (%s) '%s'}}}  I will NOT try to relock.\n", #chan, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
347
				ast_log(LOG_WARNING, "Could not unlock channel '%s': %s.  {{{Originally locked at %s line %d: (%s) '%s'}}}  I will NOT try to relock.\n", #chan, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
348
			} else { \
348
			} else { \
349
				__ao2_lock(chan, AO2_LOCK_REQ_MUTEX, __filename, __func, __lineno, __mutex_name); \
349
				__ao2_lock(chan, AO2_LOCK_REQ_MUTEX, __filename, __func, __lineno, __mutex_name); \
350
			} \
350
			} \
351
		} \
351
		} \
352
	} while (0)
352
	} while (0)
353

    
   
353

   
354
#define DEADLOCK_AVOIDANCE(lock) \
354
#define DEADLOCK_AVOIDANCE(lock) \
355
	do { \
355
	do { \
356
		char __filename[80], __func[80], __mutex_name[80]; \
356
		char __filename[80], __func[80], __mutex_name[80]; \
357
		int __lineno; \
357
		int __lineno; \
358
		int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
358
		int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
359
		int __res2 = ast_mutex_unlock(lock); \
359
		int __res2 = ast_mutex_unlock(lock); \
360
		usleep(1); \
360
		usleep(1); \
361
		if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
361
		if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
362
			if (__res2 == 0) { \
362
			if (__res2 == 0) { \
363
				ast_mutex_lock(lock); \
363
				ast_mutex_lock(lock); \
364
			} else { \
364
			} else { \
365
				ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s and no lock info found!  I will NOT try to relock.\n", #lock, strerror(__res2)); \
365
				ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s and no lock info found!  I will NOT try to relock.\n", #lock, strerror(__res2)); \
366
			} \
366
			} \
367
		} else { \
367
		} else { \
368
			if (__res2 == 0) { \
368
			if (__res2 == 0) { \
369
				__ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
369
				__ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
370
			} else { \
370
			} else { \
371
				ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s.  {{{Originally locked at %s line %d: (%s) '%s'}}}  I will NOT try to relock.\n", #lock, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
371
				ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s.  {{{Originally locked at %s line %d: (%s) '%s'}}}  I will NOT try to relock.\n", #lock, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
372
			} \
372
			} \
373
		} \
373
		} \
374
	} while (0)
374
	} while (0)
375

    
   
375

   
376
/*!
376
/*!
377
 * \brief Deadlock avoidance unlock
377
 * \brief Deadlock avoidance unlock
378
 *
378
 *
379
 * In certain deadlock avoidance scenarios, there is more than one lock to be
379
 * In certain deadlock avoidance scenarios, there is more than one lock to be
380
 * unlocked and relocked.  Therefore, this pair of macros is provided for that
380
 * unlocked and relocked.  Therefore, this pair of macros is provided for that
381
 * purpose.  Note that every DLA_UNLOCK _MUST_ be paired with a matching
381
 * purpose.  Note that every DLA_UNLOCK _MUST_ be paired with a matching
382
 * DLA_LOCK.  The intent of this pair of macros is to be used around another
382
 * DLA_LOCK.  The intent of this pair of macros is to be used around another
383
 * set of deadlock avoidance code, mainly CHANNEL_DEADLOCK_AVOIDANCE, as the
383
 * set of deadlock avoidance code, mainly CHANNEL_DEADLOCK_AVOIDANCE, as the
384
 * locking order specifies that we may safely lock a channel, followed by its
384
 * locking order specifies that we may safely lock a channel, followed by its
385
 * pvt, with no worries about a deadlock.  In any other scenario, this macro
385
 * pvt, with no worries about a deadlock.  In any other scenario, this macro
386
 * may not be safe to use.
386
 * may not be safe to use.
387
 */
387
 */
388
#define DLA_UNLOCK(lock) \
388
#define DLA_UNLOCK(lock) \
389
	do { \
389
	do { \
390
		char __filename[80], __func[80], __mutex_name[80]; \
390
		char __filename[80], __func[80], __mutex_name[80]; \
391
		int __lineno; \
391
		int __lineno; \
392
		int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
392
		int __res = ast_find_lock_info(lock, __filename, sizeof(__filename), &__lineno, __func, sizeof(__func), __mutex_name, sizeof(__mutex_name)); \
393
		int __res2 = ast_mutex_unlock(lock);
393
		int __res2 = ast_mutex_unlock(lock);
394

    
   
394

   
395
/*!
395
/*!
396
 * \brief Deadlock avoidance lock
396
 * \brief Deadlock avoidance lock
397
 *
397
 *
398
 * In certain deadlock avoidance scenarios, there is more than one lock to be
398
 * In certain deadlock avoidance scenarios, there is more than one lock to be
399
 * unlocked and relocked.  Therefore, this pair of macros is provided for that
399
 * unlocked and relocked.  Therefore, this pair of macros is provided for that
400
 * purpose.  Note that every DLA_UNLOCK _MUST_ be paired with a matching
400
 * purpose.  Note that every DLA_UNLOCK _MUST_ be paired with a matching
401
 * DLA_LOCK.  The intent of this pair of macros is to be used around another
401
 * DLA_LOCK.  The intent of this pair of macros is to be used around another
402
 * set of deadlock avoidance code, mainly CHANNEL_DEADLOCK_AVOIDANCE, as the
402
 * set of deadlock avoidance code, mainly CHANNEL_DEADLOCK_AVOIDANCE, as the
403
 * locking order specifies that we may safely lock a channel, followed by its
403
 * locking order specifies that we may safely lock a channel, followed by its
404
 * pvt, with no worries about a deadlock.  In any other scenario, this macro
404
 * pvt, with no worries about a deadlock.  In any other scenario, this macro
405
 * may not be safe to use.
405
 * may not be safe to use.
406
 */
406
 */
407
#define DLA_LOCK(lock) \
407
#define DLA_LOCK(lock) \
408
		if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
408
		if (__res < 0) { /* Shouldn't ever happen, but just in case... */ \
409
			if (__res2) { \
409
			if (__res2) { \
410
				ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s and no lock info found!  I will NOT try to relock.\n", #lock, strerror(__res2)); \
410
				ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s and no lock info found!  I will NOT try to relock.\n", #lock, strerror(__res2)); \
411
			} else { \
411
			} else { \
412
				ast_mutex_lock(lock); \
412
				ast_mutex_lock(lock); \
413
			} \
413
			} \
414
		} else { \
414
		} else { \
415
			if (__res2) { \
415
			if (__res2) { \
416
				ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s.  {{{Originally locked at %s line %d: (%s) '%s'}}}  I will NOT try to relock.\n", #lock, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
416
				ast_log(LOG_WARNING, "Could not unlock mutex '%s': %s.  {{{Originally locked at %s line %d: (%s) '%s'}}}  I will NOT try to relock.\n", #lock, strerror(__res2), __filename, __lineno, __func, __mutex_name); \
417
			} else { \
417
			} else { \
418
				__ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
418
				__ast_pthread_mutex_lock(__filename, __lineno, __func, __mutex_name, lock); \
419
			} \
419
			} \
420
		} \
420
		} \
421
	} while (0)
421
	} while (0)
422

    
   
422

   
423
static inline void ast_reentrancy_lock(struct ast_lock_track *lt)
423
static inline void ast_reentrancy_lock(struct ast_lock_track *lt)
424
{
424
{
425
	int res;
425
	int res;
426
	if ((res = pthread_mutex_lock(&lt->reentr_mutex))) {
426
	if ((res = pthread_mutex_lock(&lt->reentr_mutex))) {
427
		fprintf(stderr, "ast_reentrancy_lock failed: '%s' (%d)\n", strerror(res), res);
427
		fprintf(stderr, "ast_reentrancy_lock failed: '%s' (%d)\n", strerror(res), res);
428
#if defined(DO_CRASH) || defined(THREAD_CRASH)
428
#if defined(DO_CRASH) || defined(THREAD_CRASH)
429
		abort();
429
		abort();
430
#endif
430
#endif
431
	}
431
	}
432
}
432
}
433

    
   
433

   
434
static inline void ast_reentrancy_unlock(struct ast_lock_track *lt)
434
static inline void ast_reentrancy_unlock(struct ast_lock_track *lt)
435
{
435
{
436
	int res;
436
	int res;
437
	if ((res = pthread_mutex_unlock(&lt->reentr_mutex))) {
437
	if ((res = pthread_mutex_unlock(&lt->reentr_mutex))) {
438
		fprintf(stderr, "ast_reentrancy_unlock failed: '%s' (%d)\n", strerror(res), res);
438
		fprintf(stderr, "ast_reentrancy_unlock failed: '%s' (%d)\n", strerror(res), res);
439
#if defined(DO_CRASH) || defined(THREAD_CRASH)
439
#if defined(DO_CRASH) || defined(THREAD_CRASH)
440
		abort();
440
		abort();
441
#endif
441
#endif
442
	}
442
	}
443
}
443
}
444

    
   
444

   
445
#else /* !DEBUG_THREADS */
445
#else /* !DEBUG_THREADS */
446

    
   
446

   
447
#define	CHANNEL_DEADLOCK_AVOIDANCE(chan) \
447
#define	CHANNEL_DEADLOCK_AVOIDANCE(chan) \
448
	ast_channel_unlock(chan); \
448
	ast_channel_unlock(chan); \
449
	usleep(1); \
449
	usleep(1); \
450
	ast_channel_lock(chan);
450
	ast_channel_lock(chan);
451

    
   
451

   
452
#define	DEADLOCK_AVOIDANCE(lock) \
452
#define	DEADLOCK_AVOIDANCE(lock) \
453
	do { \
453
	do { \
454
		int __res; \
454
		int __res; \
455
		if (!(__res = ast_mutex_unlock(lock))) { \
455
		if (!(__res = ast_mutex_unlock(lock))) { \
456
			usleep(1); \
456
			usleep(1); \
457
			ast_mutex_lock(lock); \
457
			ast_mutex_lock(lock); \
458
		} else { \
458
		} else { \
459
			ast_log(LOG_WARNING, "Failed to unlock mutex '%s' (%s).  I will NOT try to relock. {{{ THIS IS A BUG. }}}\n", #lock, strerror(__res)); \
459
			ast_log(LOG_WARNING, "Failed to unlock mutex '%s' (%s).  I will NOT try to relock. {{{ THIS IS A BUG. }}}\n", #lock, strerror(__res)); \
460
		} \
460
		} \
461
	} while (0)
461
	} while (0)
462

    
   
462

   
463
#define DLA_UNLOCK(lock) ast_mutex_unlock(lock)
463
#define DLA_UNLOCK(lock) ast_mutex_unlock(lock)
464

    
   
464

   
465
#define DLA_LOCK(lock) ast_mutex_lock(lock)
465
#define DLA_LOCK(lock) ast_mutex_lock(lock)
466

    
   
466

   
467
#endif /* !DEBUG_THREADS */
467
#endif /* !DEBUG_THREADS */
468

    
   
468

   
469
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
469
#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS)
470
/*
470
/*
471
 * If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope constructors
471
 * If AST_MUTEX_INIT_W_CONSTRUCTORS is defined, use file scope constructors
472
 * and destructors to create/destroy global mutexes.
472
 * and destructors to create/destroy global mutexes.
473
 */
473
 */
474
#define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)	\
474
#define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)	\
475
	scope ast_mutex_t mutex = init_val;			\
475
	scope ast_mutex_t mutex = init_val;			\
476
static void  __attribute__((constructor)) init_##mutex(void)	\
476
static void  __attribute__((constructor)) init_##mutex(void)	\
477
{								\
477
{								\
478
	if (track)						\
478
	if (track)						\
479
		ast_mutex_init(&mutex);				\
479
		ast_mutex_init(&mutex);				\
480
	else							\
480
	else							\
481
		ast_mutex_init_notracking(&mutex);		\
481
		ast_mutex_init_notracking(&mutex);		\
482
}								\
482
}								\
483
								\
483
								\
484
static void  __attribute__((destructor)) fini_##mutex(void)	\
484
static void  __attribute__((destructor)) fini_##mutex(void)	\
485
{								\
485
{								\
486
	ast_mutex_destroy(&mutex);				\
486
	ast_mutex_destroy(&mutex);				\
487
}
487
}
488
#else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
488
#else /* !AST_MUTEX_INIT_W_CONSTRUCTORS */
489
/* By default, use static initialization of mutexes. */
489
/* By default, use static initialization of mutexes. */
490
#define __AST_MUTEX_DEFINE(scope, mutex, init_val, track) scope ast_mutex_t mutex = init_val
490
#define __AST_MUTEX_DEFINE(scope, mutex, init_val, track) scope ast_mutex_t mutex = init_val
491
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
491
#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
492

    
   
492

   
493
#define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
493
#define AST_MUTEX_DEFINE_STATIC(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
494
#define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
494
#define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex) __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
495

    
   
495

   
496

    
   
496

   
497
/* Statically declared read/write locks */
497
/* Statically declared read/write locks */
498
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
498
#ifdef AST_MUTEX_INIT_W_CONSTRUCTORS
499
#define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) \
499
#define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) \
500
        scope ast_rwlock_t rwlock = init_val; \
500
        scope ast_rwlock_t rwlock = init_val; \
501
static void  __attribute__((constructor)) init_##rwlock(void) \
501
static void  __attribute__((constructor)) init_##rwlock(void) \
502
{ \
502
{ \
503
	if (track) \
503
	if (track) \
504
        	ast_rwlock_init(&rwlock); \
504
        	ast_rwlock_init(&rwlock); \
505
	else \
505
	else \
506
		ast_rwlock_init_notracking(&rwlock); \
506
		ast_rwlock_init_notracking(&rwlock); \
507
} \
507
} \
508
static void  __attribute__((destructor)) fini_##rwlock(void) \
508
static void  __attribute__((destructor)) fini_##rwlock(void) \
509
{ \
509
{ \
510
        ast_rwlock_destroy(&rwlock); \
510
        ast_rwlock_destroy(&rwlock); \
511
}
511
}
512
#else
512
#else
513
#define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) scope ast_rwlock_t rwlock = init_val
513
#define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track) scope ast_rwlock_t rwlock = init_val
514
#endif
514
#endif
515

    
   
515

   
516
#define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE, 1)
516
#define AST_RWLOCK_DEFINE_STATIC(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE, 1)
517
#define AST_RWLOCK_DEFINE_STATIC_NOTRACKING(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE_NOTRACKING, 0)
517
#define AST_RWLOCK_DEFINE_STATIC_NOTRACKING(rwlock) __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE_NOTRACKING, 0)
518

    
   
518

   
519
#ifndef __CYGWIN__	/* temporary disabled for cygwin */
519
#ifndef __CYGWIN__	/* temporary disabled for cygwin */
520
#define pthread_mutex_t		use_ast_mutex_t_instead_of_pthread_mutex_t
520
#define pthread_mutex_t		use_ast_mutex_t_instead_of_pthread_mutex_t
521
#define pthread_cond_t		use_ast_cond_t_instead_of_pthread_cond_t
521
#define pthread_cond_t		use_ast_cond_t_instead_of_pthread_cond_t
522
#endif
522
#endif
523
#define pthread_mutex_lock	use_ast_mutex_lock_instead_of_pthread_mutex_lock
523
#define pthread_mutex_lock	use_ast_mutex_lock_instead_of_pthread_mutex_lock
524
#define pthread_mutex_unlock	use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
524
#define pthread_mutex_unlock	use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
525
#define pthread_mutex_trylock	use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
525
#define pthread_mutex_trylock	use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
526
#define pthread_mutex_init	use_ast_mutex_init_instead_of_pthread_mutex_init
526
#define pthread_mutex_init	use_ast_mutex_init_instead_of_pthread_mutex_init
527
#define pthread_mutex_destroy	use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
527
#define pthread_mutex_destroy	use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
528
#define pthread_cond_init	use_ast_cond_init_instead_of_pthread_cond_init
528
#define pthread_cond_init	use_ast_cond_init_instead_of_pthread_cond_init
529
#define pthread_cond_destroy	use_ast_cond_destroy_instead_of_pthread_cond_destroy
529
#define pthread_cond_destroy	use_ast_cond_destroy_instead_of_pthread_cond_destroy
530
#define pthread_cond_signal	use_ast_cond_signal_instead_of_pthread_cond_signal
530
#define pthread_cond_signal	use_ast_cond_signal_instead_of_pthread_cond_signal
531
#define pthread_cond_broadcast	use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
531
#define pthread_cond_broadcast	use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
532
#define pthread_cond_wait	use_ast_cond_wait_instead_of_pthread_cond_wait
532
#define pthread_cond_wait	use_ast_cond_wait_instead_of_pthread_cond_wait
533
#define pthread_cond_timedwait	use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
533
#define pthread_cond_timedwait	use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
534

    
   
534

   
535
#define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
535
#define AST_MUTEX_INITIALIZER __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
536

    
   
536

   
537
#define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
537
#define gethostbyname __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
538

    
   
538

   
539
#ifndef __linux__
539
#ifndef __linux__
540
#define pthread_create __use_ast_pthread_create_instead__
540
#define pthread_create __use_ast_pthread_create_instead__
541
#endif
541
#endif
542

    
   
542

   
543
/*
543
/*
544
 * Support for atomic instructions.
544
 * Support for atomic instructions.
545
 * For platforms that have it, use the native cpu instruction to
545
 * For platforms that have it, use the native cpu instruction to
546
 * implement them. For other platforms, resort to a 'slow' version
546
 * implement them. For other platforms, resort to a 'slow' version
547
 * (defined in utils.c) that protects the atomic instruction with
547
 * (defined in utils.c) that protects the atomic instruction with
548
 * a single lock.
548
 * a single lock.
549
 * The slow versions is always available, for testing purposes,
549
 * The slow versions is always available, for testing purposes,
550
 * as ast_atomic_fetchadd_int_slow()
550
 * as ast_atomic_fetchadd_int_slow()
551
 */
551
 */
552

    
   
552

   
553
int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
553
int ast_atomic_fetchadd_int_slow(volatile int *p, int v);
554

    
   
554

   
555
#include "asterisk/inline_api.h"
555
#include "asterisk/inline_api.h"
556

    
   
556

   
557
#if defined(HAVE_OSX_ATOMICS)
557
#if defined(HAVE_OSX_ATOMICS)
558
#include "libkern/OSAtomic.h"
558
#include "libkern/OSAtomic.h"
559
#endif
559
#endif
560

    
   
560

   
561
/*! \brief Atomically add v to *p and return * the previous value of *p.
561
/*! \brief Atomically add v to *p and return * the previous value of *p.
562
 * This can be used to handle reference counts, and the return value
562
 * This can be used to handle reference counts, and the return value
563
 * can be used to generate unique identifiers.
563
 * can be used to generate unique identifiers.
564
 */
564
 */
565

    
   
565

   
566
#if defined(HAVE_GCC_ATOMICS)
566
#if defined(HAVE_GCC_ATOMICS)
567
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
567
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
568
{
568
{
569
	return __sync_fetch_and_add(p, v);
569
	return __sync_fetch_and_add(p, v);
570
})
570
})
571
#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
571
#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
572
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
572
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
573
{
573
{
574
	return OSAtomicAdd32(v, (int32_t *) p) - v;
574
	return OSAtomicAdd32(v, (int32_t *) p) - v;
575
})
575
})
576
#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
576
#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
577
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
577
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
578
{
578
{
579
	return OSAtomicAdd64(v, (int64_t *) p) - v;
579
	return OSAtomicAdd64(v, (int64_t *) p) - v;

    
   
580
})
580
#elif defined (__i386__) || defined(__x86_64__)
581
#elif defined (__i386__) || defined(__x86_64__)
581
#ifdef sun
582
#ifdef sun
582
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
583
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
583
{
584
{
584
	__asm __volatile (
585
	__asm __volatile (
585
	"       lock;  xaddl   %0, %1 ;        "
586
	"       lock;  xaddl   %0, %1 ;        "
586
	: "+r" (v),                     /* 0 (result) */
587
	: "+r" (v),                     /* 0 (result) */
587
	  "=m" (*p)                     /* 1 */
588
	  "=m" (*p)                     /* 1 */
588
	: "m" (*p));                    /* 2 */
589
	: "m" (*p));                    /* 2 */
589
	return (v);
590
	return (v);
590
})
591
})
591
#else /* ifndef sun */
592
#else /* ifndef sun */
592
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
593
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
593
{
594
{
594
	__asm __volatile (
595
	__asm __volatile (
595
	"       lock   xaddl   %0, %1 ;        "
596
	"       lock   xaddl   %0, %1 ;        "
596
	: "+r" (v),                     /* 0 (result) */
597
	: "+r" (v),                     /* 0 (result) */
597
	  "=m" (*p)                     /* 1 */
598
	  "=m" (*p)                     /* 1 */
598
	: "m" (*p));                    /* 2 */
599
	: "m" (*p));                    /* 2 */
599
	return (v);
600
	return (v);
600
})
601
})
601
#endif
602
#endif
602
#else   /* low performance version in utils.c */
603
#else   /* low performance version in utils.c */
603
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
604
AST_INLINE_API(int ast_atomic_fetchadd_int(volatile int *p, int v),
604
{
605
{
605
	return ast_atomic_fetchadd_int_slow(p, v);
606
	return ast_atomic_fetchadd_int_slow(p, v);
606
})
607
})
607
#endif
608
#endif
608

    
   
609

   
609
/*! \brief decrement *p by 1 and return true if the variable has reached 0.
610
/*! \brief decrement *p by 1 and return true if the variable has reached 0.
610
 * Useful e.g. to check if a refcount has reached 0.
611
 * Useful e.g. to check if a refcount has reached 0.
611
 */
612
 */
612
#if defined(HAVE_GCC_ATOMICS)
613
#if defined(HAVE_GCC_ATOMICS)
613
AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
614
AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
614
{
615
{
615
	return __sync_sub_and_fetch(p, 1) == 0;
616
	return __sync_sub_and_fetch(p, 1) == 0;
616
})
617
})
617
#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
618
#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 4)
618
AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
619
AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
619
{
620
{
620
	return OSAtomicAdd32( -1, (int32_t *) p) == 0;
621
	return OSAtomicAdd32( -1, (int32_t *) p) == 0;
621
})
622
})
622
#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
623
#elif defined(HAVE_OSX_ATOMICS) && (SIZEOF_INT == 8)
623
AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
624
AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
624
{
625
{
625
	return OSAtomicAdd64( -1, (int64_t *) p) == 0;
626
	return OSAtomicAdd64( -1, (int64_t *) p) == 0;

    
   
627
})
626
#else
628
#else
627
AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
629
AST_INLINE_API(int ast_atomic_dec_and_test(volatile int *p),
628
{
630
{
629
	int a = ast_atomic_fetchadd_int(p, -1);
631
	int a = ast_atomic_fetchadd_int(p, -1);
630
	return a == 1; /* true if the value is 0 now (so it was 1 previously) */
632
	return a == 1; /* true if the value is 0 now (so it was 1 previously) */
631
})
633
})
632
#endif
634
#endif
633

    
   
635

   
634
#endif /* _ASTERISK_LOCK_H */
636
#endif /* _ASTERISK_LOCK_H */
  1. /branches/11/include/asterisk/lock.h: Loading...

https://reviewboard.asterisk.org/ runs on a server provided by Digium, Inc. and uses bandwidth donated to the open source Asterisk community by API Digital Communications in Huntsville, AL USA.
Please report problems with this site to asteriskteam@digium.com.