Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Macros | Typedefs | Functions
lock.h File Reference

Asterisk locking-related definitions: More...

#include <pthread.h>
#include <time.h>
#include <sys/param.h>
#include <execinfo.h>
#include "asterisk/backtrace.h"
#include "asterisk/logger.h"
#include "asterisk/compiler.h"
#include "asterisk/inline_api.h"
Include dependency graph for lock.h:

Go to the source code of this file.

Data Structures

struct  ast_lock_track
 Lock tracking information. More...
 
struct  ast_lock_track_flags
 
struct  ast_mutex_info
 Structure for mutex and tracking information. More...
 
struct  ast_rwlock_info
 Structure for rwlock and tracking information. More...
 

Macros

#define __AST_MUTEX_DEFINE(scope, mutex, init_val, track)   scope ast_mutex_t mutex = init_val
 
#define __AST_RWLOCK_DEFINE(scope, rwlock, init_val, track)   scope ast_rwlock_t rwlock = init_val
 
#define __AST_RWLOCK_INIT_VALUE   PTHREAD_RWLOCK_INITIALIZER
 
#define AO2_DEADLOCK_AVOIDANCE(obj)
 
#define ast_cond_broadcast(cond)   __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
 
#define ast_cond_destroy(cond)   __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
 
#define ast_cond_init(cond, attr)   __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)
 
#define ast_cond_signal(cond)   __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)
 
#define ast_cond_timedwait(cond, mutex, time)   __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)
 
#define ast_cond_wait(cond, mutex)   __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)
 
#define AST_LOCK_TRACK_INIT_VALUE   { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }
 
#define AST_MAX_REENTRANCY   10
 
#define AST_MUTEX_DEFINE_STATIC(mutex)   __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)
 
#define AST_MUTEX_DEFINE_STATIC_NOTRACKING(mutex)   __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)
 
#define ast_mutex_destroy(a)   __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
 
#define ast_mutex_init(pmutex)   __ast_pthread_mutex_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
 
#define ast_mutex_init_notracking(pmutex)   __ast_pthread_mutex_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)
 
#define AST_MUTEX_INIT_VALUE   { PTHREAD_MUTEX_INIT_VALUE, NULL, {1, 0} }
 
#define AST_MUTEX_INIT_VALUE_NOTRACKING   { PTHREAD_MUTEX_INIT_VALUE, NULL, {0, 0} }
 
#define AST_MUTEX_INITIALIZER   __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__
 
#define AST_MUTEX_KIND   PTHREAD_MUTEX_RECURSIVE_NP
 
#define ast_mutex_lock(a)   __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
 
#define ast_mutex_trylock(a)   __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
 
#define ast_mutex_unlock(a)   __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)
 
#define AST_PTHREADT_NULL   (pthread_t) -1
 
#define AST_PTHREADT_STOP   (pthread_t) -2
 
#define AST_RWLOCK_DEFINE_STATIC(rwlock)   __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE, 1)
 
#define AST_RWLOCK_DEFINE_STATIC_NOTRACKING(rwlock)   __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE_NOTRACKING, 0)
 
#define ast_rwlock_destroy(rwlock)   __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
 
#define ast_rwlock_init(rwlock)   __ast_rwlock_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
 wrapper for rwlock with tracking enabled More...
 
#define ast_rwlock_init_notracking(rwlock)   __ast_rwlock_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)
 wrapper for ast_rwlock_init with tracking disabled More...
 
#define AST_RWLOCK_INIT_VALUE   { __AST_RWLOCK_INIT_VALUE, NULL, {1, 0} }
 
#define AST_RWLOCK_INIT_VALUE_NOTRACKING   { __AST_RWLOCK_INIT_VALUE, NULL, {0, 0} }
 
#define ast_rwlock_rdlock(a)   __ast_rwlock_rdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
 
#define ast_rwlock_timedrdlock(a, b)   __ast_rwlock_timedrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)
 
#define ast_rwlock_timedwrlock(a, b)   __ast_rwlock_timedwrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)
 
#define ast_rwlock_tryrdlock(a)   __ast_rwlock_tryrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
 
#define ast_rwlock_trywrlock(a)   __ast_rwlock_trywrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
 
#define ast_rwlock_unlock(a)   __ast_rwlock_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
 
#define ast_rwlock_wrlock(a)   __ast_rwlock_wrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)
 
#define CHANNEL_DEADLOCK_AVOIDANCE(chan)
 
#define DEADLOCK_AVOIDANCE(lock)
 
#define DLA_LOCK(lock)   ast_mutex_lock(lock)
 
#define DLA_UNLOCK(lock)   ast_mutex_unlock(lock)
 
#define gethostbyname   __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__
 
#define pthread_cond_broadcast   use_ast_cond_broadcast_instead_of_pthread_cond_broadcast
 
#define pthread_cond_destroy   use_ast_cond_destroy_instead_of_pthread_cond_destroy
 
#define pthread_cond_init   use_ast_cond_init_instead_of_pthread_cond_init
 
#define pthread_cond_signal   use_ast_cond_signal_instead_of_pthread_cond_signal
 
#define pthread_cond_t   use_ast_cond_t_instead_of_pthread_cond_t
 
#define pthread_cond_timedwait   use_ast_cond_timedwait_instead_of_pthread_cond_timedwait
 
#define pthread_cond_wait   use_ast_cond_wait_instead_of_pthread_cond_wait
 
#define pthread_create   __use_ast_pthread_create_instead__
 
#define pthread_mutex_destroy   use_ast_mutex_destroy_instead_of_pthread_mutex_destroy
 
#define pthread_mutex_init   use_ast_mutex_init_instead_of_pthread_mutex_init
 
#define PTHREAD_MUTEX_INIT_VALUE   PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
 
#define pthread_mutex_lock   use_ast_mutex_lock_instead_of_pthread_mutex_lock
 
#define pthread_mutex_t   use_ast_mutex_t_instead_of_pthread_mutex_t
 
#define pthread_mutex_trylock   use_ast_mutex_trylock_instead_of_pthread_mutex_trylock
 
#define pthread_mutex_unlock   use_ast_mutex_unlock_instead_of_pthread_mutex_unlock
 
#define ROFFSET   ((lt->reentrancy > 0) ? (lt->reentrancy-1) : 0)
 
#define SCOPED_AO2LOCK(varname, obj)   SCOPED_LOCK(varname, (obj), ao2_lock, ao2_unlock)
 scoped lock specialization for ao2 mutexes. More...
 
#define SCOPED_AO2RDLOCK(varname, obj)   SCOPED_LOCK(varname, (obj), ao2_rdlock, ao2_unlock)
 scoped lock specialization for ao2 read locks. More...
 
#define SCOPED_AO2WRLOCK(varname, obj)   SCOPED_LOCK(varname, (obj), ao2_wrlock, ao2_unlock)
 scoped lock specialization for ao2 write locks. More...
 
#define SCOPED_CHANNELLOCK(varname, chan)   SCOPED_LOCK(varname, (chan), ast_channel_lock, ast_channel_unlock)
 scoped lock specialization for channels. More...
 
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)    RAII_VAR(typeof((lock)), varname, ({lockfunc((lock)); (lock); }), unlockfunc)
 Scoped Locks. More...
 
#define SCOPED_MUTEX(varname, lock)   SCOPED_LOCK(varname, (lock), ast_mutex_lock, ast_mutex_unlock)
 scoped lock specialization for mutexes More...
 
#define SCOPED_RDLOCK(varname, lock)   SCOPED_LOCK(varname, (lock), ast_rwlock_rdlock, ast_rwlock_unlock)
 scoped lock specialization for read locks More...
 
#define SCOPED_WRLOCK(varname, lock)   SCOPED_LOCK(varname, (lock), ast_rwlock_wrlock, ast_rwlock_unlock)
 scoped lock specialization for write locks More...
 

Typedefs

typedef pthread_cond_t ast_cond_t
 
typedef struct ast_mutex_info ast_mutex_t
 
typedef struct ast_rwlock_info ast_rwlock_t
 

Functions

int __ast_cond_broadcast (const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond)
 
int __ast_cond_destroy (const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond)
 
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)
 
int __ast_cond_signal (const char *filename, int lineno, const char *func, const char *cond_name, ast_cond_t *cond)
 
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)
 
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)
 
int __ast_pthread_mutex_destroy (const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
 
int __ast_pthread_mutex_init (int tracking, const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
 
int __ast_pthread_mutex_lock (const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
 
int __ast_pthread_mutex_trylock (const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
 
int __ast_pthread_mutex_unlock (const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
 
int __ast_rwlock_destroy (const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
 
int __ast_rwlock_init (int tracking, const char *filename, int lineno, const char *func, const char *rwlock_name, ast_rwlock_t *t)
 
int __ast_rwlock_rdlock (const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
 
int __ast_rwlock_timedrdlock (const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout)
 
int __ast_rwlock_timedwrlock (const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name, const struct timespec *abs_timeout)
 
int __ast_rwlock_tryrdlock (const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
 
int __ast_rwlock_trywrlock (const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
 
int __ast_rwlock_unlock (const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
 
int __ast_rwlock_wrlock (const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
 
#define ast_atomic_add_fetch(ptr, val, memorder)   __atomic_add_fetch((ptr), (val), (memorder))
 
#define ast_atomic_and_fetch(ptr, val, memorder)   __atomic_and_fetch((ptr), (val), (memorder))
 
int ast_atomic_dec_and_test (volatile int *p)
 decrement *p by 1 and return true if the variable has reached 0. More...
 
#define ast_atomic_fetch_add(ptr, val, memorder)   __atomic_fetch_add((ptr), (val), (memorder))
 Support for atomic instructions. More...
 
#define ast_atomic_fetch_and(ptr, val, memorder)   __atomic_fetch_and((ptr), (val), (memorder))
 
#define ast_atomic_fetch_or(ptr, val, memorder)   __atomic_fetch_or((ptr), (val), (memorder))
 
#define ast_atomic_fetch_sub(ptr, val, memorder)   __atomic_fetch_sub((ptr), (val), (memorder))
 
#define ast_atomic_fetch_xor(ptr, val, memorder)   __atomic_fetch_xor((ptr), (val), (memorder))
 
int ast_atomic_fetchadd_int (volatile int *p, int v)
 Atomically add v to *p and return the previous value of *p. More...
 
#define ast_atomic_flag_clear(ptr, val, memorder)   ast_atomic_fetch_and((ptr), ~(val), (memorder))
 
#define ast_atomic_flag_set(ptr, val, memorder)   ast_atomic_fetch_or((ptr), (val), (memorder))
 
#define ast_atomic_or_fetch(ptr, val, memorder)   __atomic_or_fetch((ptr), (val), (memorder))
 
#define ast_atomic_sub_fetch(ptr, val, memorder)   __atomic_sub_fetch((ptr), (val), (memorder))
 
#define ast_atomic_xor_fetch(ptr, val, memorder)   __atomic_xor_fetch((ptr), (val), (memorder))
 

Detailed Description

Asterisk locking-related definitions:

Magic number.

This is used to verify that a pointer is a valid astobj2 or ao2_weak reference.

Note
This field is constant after object creation. It shares a uint32_t with options and lockused.
Warning
Stealing bits for any additional writable fields would cause reentrancy issues if using bitfields. If any additional writable bits are required in the future we will need to put all bitfields into a single 'uint32_t flags' field and use atomic operations from to perform writes.

Definition in file lock.h.

Macro Definition Documentation

◆ __AST_MUTEX_DEFINE

#define __AST_MUTEX_DEFINE (   scope,
  mutex,
  init_val,
  track 
)    scope ast_mutex_t mutex = init_val

Definition at line 521 of file lock.h.

◆ __AST_RWLOCK_DEFINE

#define __AST_RWLOCK_DEFINE (   scope,
  rwlock,
  init_val,
  track 
)    scope ast_rwlock_t rwlock = init_val

Definition at line 544 of file lock.h.

◆ __AST_RWLOCK_INIT_VALUE

#define __AST_RWLOCK_INIT_VALUE   PTHREAD_RWLOCK_INITIALIZER

Definition at line 88 of file lock.h.

◆ AO2_DEADLOCK_AVOIDANCE

#define AO2_DEADLOCK_AVOIDANCE (   obj)
Value:
ao2_unlock(obj); \
usleep(1); \
ao2_lock(obj);
#define ao2_unlock(a)
Definition: astobj2.h:729

Definition at line 473 of file lock.h.

◆ ast_atomic_add_fetch

#define ast_atomic_add_fetch (   ptr,
  val,
  memorder 
)    __atomic_add_fetch((ptr), (val), (memorder))

Definition at line 674 of file lock.h.

◆ ast_atomic_and_fetch

#define ast_atomic_and_fetch (   ptr,
  val,
  memorder 
)    __atomic_and_fetch((ptr), (val), (memorder))

Definition at line 682 of file lock.h.

◆ ast_atomic_fetch_add

#define ast_atomic_fetch_add (   ptr,
  val,
  memorder 
)    __atomic_fetch_add((ptr), (val), (memorder))

Support for atomic instructions.

These macros implement a uniform interface to use built-in atomic functionality. If available __atomic built-ins are prefered. Legacy __sync built-ins are used as a fallback for older compilers.

Detailed documentation can be found in the GCC manual, all API's are modeled after the __atomic interfaces but using the namespace ast_atomic.

The memorder argument is always ignored by legacy __sync functions. Invalid memorder arguments do not produce errors unless __atomic functions are supported as the argument is erased by the preprocessor.

Note
ast_atomic_fetch_nand and ast_atomic_nand_fetch purposely do not exist. It's implementation was broken prior to gcc-4.4.

Atomic +=

Definition at line 673 of file lock.h.

◆ ast_atomic_fetch_and

#define ast_atomic_fetch_and (   ptr,
  val,
  memorder 
)    __atomic_fetch_and((ptr), (val), (memorder))

Atomic &=

Definition at line 681 of file lock.h.

◆ ast_atomic_fetch_or

#define ast_atomic_fetch_or (   ptr,
  val,
  memorder 
)    __atomic_fetch_or((ptr), (val), (memorder))

Atomic |=

Definition at line 685 of file lock.h.

◆ ast_atomic_fetch_sub

#define ast_atomic_fetch_sub (   ptr,
  val,
  memorder 
)    __atomic_fetch_sub((ptr), (val), (memorder))

Atomic -=

Definition at line 677 of file lock.h.

◆ ast_atomic_fetch_xor

#define ast_atomic_fetch_xor (   ptr,
  val,
  memorder 
)    __atomic_fetch_xor((ptr), (val), (memorder))

Atomic xor =

Definition at line 689 of file lock.h.

◆ ast_atomic_flag_clear

#define ast_atomic_flag_clear (   ptr,
  val,
  memorder 
)    ast_atomic_fetch_and((ptr), ~(val), (memorder))

Atomic flag clear

Definition at line 750 of file lock.h.

◆ ast_atomic_flag_set

#define ast_atomic_flag_set (   ptr,
  val,
  memorder 
)    ast_atomic_fetch_or((ptr), (val), (memorder))

Atomic flag set

Definition at line 747 of file lock.h.

◆ ast_atomic_or_fetch

#define ast_atomic_or_fetch (   ptr,
  val,
  memorder 
)    __atomic_or_fetch((ptr), (val), (memorder))

Definition at line 686 of file lock.h.

◆ ast_atomic_sub_fetch

#define ast_atomic_sub_fetch (   ptr,
  val,
  memorder 
)    __atomic_sub_fetch((ptr), (val), (memorder))

Definition at line 678 of file lock.h.

◆ ast_atomic_xor_fetch

#define ast_atomic_xor_fetch (   ptr,
  val,
  memorder 
)    __atomic_xor_fetch((ptr), (val), (memorder))

Definition at line 690 of file lock.h.

◆ ast_cond_broadcast

#define ast_cond_broadcast (   cond)    __ast_cond_broadcast(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)

Definition at line 208 of file lock.h.

◆ ast_cond_destroy

#define ast_cond_destroy (   cond)    __ast_cond_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)

Definition at line 206 of file lock.h.

◆ ast_cond_init

#define ast_cond_init (   cond,
  attr 
)    __ast_cond_init(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond, attr)

Definition at line 205 of file lock.h.

◆ ast_cond_signal

#define ast_cond_signal (   cond)    __ast_cond_signal(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, cond)

Definition at line 207 of file lock.h.

◆ ast_cond_timedwait

#define ast_cond_timedwait (   cond,
  mutex,
  time 
)    __ast_cond_timedwait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex, time)

Definition at line 210 of file lock.h.

◆ ast_cond_wait

#define ast_cond_wait (   cond,
  mutex 
)    __ast_cond_wait(__FILE__, __LINE__, __PRETTY_FUNCTION__, #cond, #mutex, cond, mutex)

Definition at line 209 of file lock.h.

◆ AST_LOCK_TRACK_INIT_VALUE

#define AST_LOCK_TRACK_INIT_VALUE   { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_MUTEX_INIT_VALUE }

Definition at line 94 of file lock.h.

◆ AST_MAX_REENTRANCY

#define AST_MAX_REENTRANCY   10

Definition at line 105 of file lock.h.

◆ AST_MUTEX_DEFINE_STATIC

#define AST_MUTEX_DEFINE_STATIC (   mutex)    __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE, 1)

Definition at line 524 of file lock.h.

◆ AST_MUTEX_DEFINE_STATIC_NOTRACKING

#define AST_MUTEX_DEFINE_STATIC_NOTRACKING (   mutex)    __AST_MUTEX_DEFINE(static, mutex, AST_MUTEX_INIT_VALUE_NOTRACKING, 0)

Definition at line 525 of file lock.h.

◆ ast_mutex_destroy

#define ast_mutex_destroy (   a)    __ast_pthread_mutex_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)

Definition at line 192 of file lock.h.

◆ ast_mutex_init

#define ast_mutex_init (   pmutex)    __ast_pthread_mutex_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)

Definition at line 190 of file lock.h.

◆ ast_mutex_init_notracking

#define ast_mutex_init_notracking (   pmutex)    __ast_pthread_mutex_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #pmutex, pmutex)

Definition at line 191 of file lock.h.

◆ AST_MUTEX_INIT_VALUE

#define AST_MUTEX_INIT_VALUE   { PTHREAD_MUTEX_INIT_VALUE, NULL, {1, 0} }

Definition at line 99 of file lock.h.

◆ AST_MUTEX_INIT_VALUE_NOTRACKING

#define AST_MUTEX_INIT_VALUE_NOTRACKING   { PTHREAD_MUTEX_INIT_VALUE, NULL, {0, 0} }

Definition at line 100 of file lock.h.

◆ AST_MUTEX_INITIALIZER

#define AST_MUTEX_INITIALIZER   __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__

Definition at line 641 of file lock.h.

◆ AST_MUTEX_KIND

#define AST_MUTEX_KIND   PTHREAD_MUTEX_RECURSIVE_NP

Definition at line 81 of file lock.h.

◆ ast_mutex_lock

#define ast_mutex_lock (   a)    __ast_pthread_mutex_lock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)

Definition at line 193 of file lock.h.

◆ ast_mutex_trylock

#define ast_mutex_trylock (   a)    __ast_pthread_mutex_trylock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)

Definition at line 195 of file lock.h.

◆ ast_mutex_unlock

#define ast_mutex_unlock (   a)    __ast_pthread_mutex_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, #a, a)

Definition at line 194 of file lock.h.

◆ AST_PTHREADT_NULL

#define AST_PTHREADT_NULL   (pthread_t) -1

Definition at line 70 of file lock.h.

◆ AST_PTHREADT_STOP

#define AST_PTHREADT_STOP   (pthread_t) -2

Definition at line 71 of file lock.h.

◆ AST_RWLOCK_DEFINE_STATIC

#define AST_RWLOCK_DEFINE_STATIC (   rwlock)    __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE, 1)

Definition at line 547 of file lock.h.

◆ AST_RWLOCK_DEFINE_STATIC_NOTRACKING

#define AST_RWLOCK_DEFINE_STATIC_NOTRACKING (   rwlock)    __AST_RWLOCK_DEFINE(static, rwlock, AST_RWLOCK_INIT_VALUE_NOTRACKING, 0)

Definition at line 548 of file lock.h.

◆ ast_rwlock_destroy

#define ast_rwlock_destroy (   rwlock)    __ast_rwlock_destroy(__FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)

Definition at line 237 of file lock.h.

◆ ast_rwlock_init

#define ast_rwlock_init (   rwlock)    __ast_rwlock_init(1, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)

wrapper for rwlock with tracking enabled

Returns
0 on success, non zero for error
Since
1.6.1

Definition at line 228 of file lock.h.

◆ ast_rwlock_init_notracking

#define ast_rwlock_init_notracking (   rwlock)    __ast_rwlock_init(0, __FILE__, __LINE__, __PRETTY_FUNCTION__, #rwlock, rwlock)

wrapper for ast_rwlock_init with tracking disabled

Returns
0 on success, non zero for error
Since
1.6.1

Definition at line 235 of file lock.h.

◆ AST_RWLOCK_INIT_VALUE

#define AST_RWLOCK_INIT_VALUE   { __AST_RWLOCK_INIT_VALUE, NULL, {1, 0} }

Definition at line 102 of file lock.h.

◆ AST_RWLOCK_INIT_VALUE_NOTRACKING

#define AST_RWLOCK_INIT_VALUE_NOTRACKING   { __AST_RWLOCK_INIT_VALUE, NULL, {0, 0} }

Definition at line 103 of file lock.h.

◆ ast_rwlock_rdlock

#define ast_rwlock_rdlock (   a)    __ast_rwlock_rdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)

Definition at line 239 of file lock.h.

◆ ast_rwlock_timedrdlock

#define ast_rwlock_timedrdlock (   a,
  b 
)    __ast_rwlock_timedrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)

Definition at line 243 of file lock.h.

◆ ast_rwlock_timedwrlock

#define ast_rwlock_timedwrlock (   a,
  b 
)    __ast_rwlock_timedwrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a, b)

Definition at line 244 of file lock.h.

◆ ast_rwlock_tryrdlock

#define ast_rwlock_tryrdlock (   a)    __ast_rwlock_tryrdlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)

Definition at line 241 of file lock.h.

◆ ast_rwlock_trywrlock

#define ast_rwlock_trywrlock (   a)    __ast_rwlock_trywrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)

Definition at line 242 of file lock.h.

◆ ast_rwlock_unlock

#define ast_rwlock_unlock (   a)    __ast_rwlock_unlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)

Definition at line 238 of file lock.h.

◆ ast_rwlock_wrlock

#define ast_rwlock_wrlock (   a)    __ast_rwlock_wrlock(__FILE__, __LINE__, __PRETTY_FUNCTION__, a, #a)

Definition at line 240 of file lock.h.

◆ CHANNEL_DEADLOCK_AVOIDANCE

#define CHANNEL_DEADLOCK_AVOIDANCE (   chan)
Value:
usleep(1); \
ast_channel_lock(chan);
#define ast_channel_unlock(chan)
Definition: channel.h:2971

Definition at line 478 of file lock.h.

◆ DEADLOCK_AVOIDANCE

#define DEADLOCK_AVOIDANCE (   lock)

Definition at line 483 of file lock.h.

◆ DLA_LOCK

#define DLA_LOCK (   lock)    ast_mutex_lock(lock)

Definition at line 496 of file lock.h.

◆ DLA_UNLOCK

#define DLA_UNLOCK (   lock)    ast_mutex_unlock(lock)

Definition at line 494 of file lock.h.

◆ gethostbyname

#define gethostbyname   __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__

Definition at line 643 of file lock.h.

◆ pthread_cond_broadcast

#define pthread_cond_broadcast   use_ast_cond_broadcast_instead_of_pthread_cond_broadcast

Definition at line 637 of file lock.h.

◆ pthread_cond_destroy

#define pthread_cond_destroy   use_ast_cond_destroy_instead_of_pthread_cond_destroy

Definition at line 635 of file lock.h.

◆ pthread_cond_init

#define pthread_cond_init   use_ast_cond_init_instead_of_pthread_cond_init

Definition at line 634 of file lock.h.

◆ pthread_cond_signal

#define pthread_cond_signal   use_ast_cond_signal_instead_of_pthread_cond_signal

Definition at line 636 of file lock.h.

◆ pthread_cond_t

#define pthread_cond_t   use_ast_cond_t_instead_of_pthread_cond_t

Definition at line 627 of file lock.h.

◆ pthread_cond_timedwait

#define pthread_cond_timedwait   use_ast_cond_timedwait_instead_of_pthread_cond_timedwait

Definition at line 639 of file lock.h.

◆ pthread_cond_wait

#define pthread_cond_wait   use_ast_cond_wait_instead_of_pthread_cond_wait

Definition at line 638 of file lock.h.

◆ pthread_create

#define pthread_create   __use_ast_pthread_create_instead__

Definition at line 646 of file lock.h.

◆ pthread_mutex_destroy

#define pthread_mutex_destroy   use_ast_mutex_destroy_instead_of_pthread_mutex_destroy

Definition at line 633 of file lock.h.

◆ pthread_mutex_init

#define pthread_mutex_init   use_ast_mutex_init_instead_of_pthread_mutex_init

Definition at line 632 of file lock.h.

◆ PTHREAD_MUTEX_INIT_VALUE

#define PTHREAD_MUTEX_INIT_VALUE   PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP

Definition at line 80 of file lock.h.

◆ pthread_mutex_lock

#define pthread_mutex_lock   use_ast_mutex_lock_instead_of_pthread_mutex_lock

Definition at line 629 of file lock.h.

◆ pthread_mutex_t

#define pthread_mutex_t   use_ast_mutex_t_instead_of_pthread_mutex_t

Definition at line 626 of file lock.h.

◆ pthread_mutex_trylock

#define pthread_mutex_trylock   use_ast_mutex_trylock_instead_of_pthread_mutex_trylock

Definition at line 631 of file lock.h.

◆ pthread_mutex_unlock

#define pthread_mutex_unlock   use_ast_mutex_unlock_instead_of_pthread_mutex_unlock

Definition at line 630 of file lock.h.

◆ ROFFSET

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

Definition at line 246 of file lock.h.

◆ SCOPED_AO2LOCK

#define SCOPED_AO2LOCK (   varname,
  obj 
)    SCOPED_LOCK(varname, (obj), ao2_lock, ao2_unlock)

scoped lock specialization for ao2 mutexes.

Definition at line 608 of file lock.h.

◆ SCOPED_AO2RDLOCK

#define SCOPED_AO2RDLOCK (   varname,
  obj 
)    SCOPED_LOCK(varname, (obj), ao2_rdlock, ao2_unlock)

scoped lock specialization for ao2 read locks.

Definition at line 613 of file lock.h.

◆ SCOPED_AO2WRLOCK

#define SCOPED_AO2WRLOCK (   varname,
  obj 
)    SCOPED_LOCK(varname, (obj), ao2_wrlock, ao2_unlock)

scoped lock specialization for ao2 write locks.

Definition at line 618 of file lock.h.

◆ SCOPED_CHANNELLOCK

#define SCOPED_CHANNELLOCK (   varname,
  chan 
)    SCOPED_LOCK(varname, (chan), ast_channel_lock, ast_channel_unlock)

scoped lock specialization for channels.

Definition at line 623 of file lock.h.

◆ SCOPED_LOCK

#define SCOPED_LOCK (   varname,
  lock,
  lockfunc,
  unlockfunc 
)     RAII_VAR(typeof((lock)), varname, ({lockfunc((lock)); (lock); }), unlockfunc)

Scoped Locks.

Scoped locks provide a way to use RAII locks. In other words, declaration of a scoped lock will automatically define and lock the lock. When the lock goes out of scope, it will automatically be unlocked.

int some_function(struct ast_channel *chan)
{
if (!strcmp(ast_channel_name(chan, "foo")) {
return 0;
}
return -1;
}
ast_mutex_t lock
Definition: app_sla.c:337
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2970
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:587
Main Channel structure associated with a channel.

In the above example, neither return path requires explicit unlocking of the channel.

Note
Care should be taken when using SCOPED_LOCKS in conjunction with ao2 objects. ao2 objects should be unlocked before they are unreffed. Since SCOPED_LOCK runs once the variable goes out of scope, this can easily lead to situations where the variable gets unlocked after it is unreffed.
Parameters
varnameThe unique name to give to the scoped lock. You are not likely to reference this outside of the SCOPED_LOCK invocation.
lockThe variable to lock. This can be anything that can be passed to a locking or unlocking function.
lockfuncThe function to call to lock the lock
unlockfuncThe function to call to unlock the lock

Definition at line 587 of file lock.h.

◆ SCOPED_MUTEX

#define SCOPED_MUTEX (   varname,
  lock 
)    SCOPED_LOCK(varname, (lock), ast_mutex_lock, ast_mutex_unlock)

scoped lock specialization for mutexes

Definition at line 593 of file lock.h.

◆ SCOPED_RDLOCK

#define SCOPED_RDLOCK (   varname,
  lock 
)    SCOPED_LOCK(varname, (lock), ast_rwlock_rdlock, ast_rwlock_unlock)

scoped lock specialization for read locks

Definition at line 598 of file lock.h.

◆ SCOPED_WRLOCK

#define SCOPED_WRLOCK (   varname,
  lock 
)    SCOPED_LOCK(varname, (lock), ast_rwlock_wrlock, ast_rwlock_unlock)

scoped lock specialization for write locks

Definition at line 603 of file lock.h.

Typedef Documentation

◆ ast_cond_t

Definition at line 182 of file lock.h.

◆ ast_mutex_t

typedef struct ast_mutex_info ast_mutex_t

Definition at line 178 of file lock.h.

◆ ast_rwlock_t

typedef struct ast_rwlock_info ast_rwlock_t

Definition at line 180 of file lock.h.

Function Documentation

◆ __ast_cond_broadcast()

int __ast_cond_broadcast ( const char *  filename,
int  lineno,
const char *  func,
const char *  cond_name,
ast_cond_t cond 
)

Definition at line 536 of file lock.c.

538{
540}
ast_cond_t cond
Definition: app_sla.c:336
#define pthread_cond_broadcast
Definition: lock.h:637

References cond, and pthread_cond_broadcast.

◆ __ast_cond_destroy()

int __ast_cond_destroy ( const char *  filename,
int  lineno,
const char *  func,
const char *  cond_name,
ast_cond_t cond 
)

Definition at line 542 of file lock.c.

544{
546}
#define pthread_cond_destroy
Definition: lock.h:635

References cond, and pthread_cond_destroy.

◆ __ast_cond_init()

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 
)

Definition at line 524 of file lock.c.

526{
527 return pthread_cond_init(cond, cond_attr);
528}
#define pthread_cond_init
Definition: lock.h:634

References cond, and pthread_cond_init.

◆ __ast_cond_signal()

int __ast_cond_signal ( const char *  filename,
int  lineno,
const char *  func,
const char *  cond_name,
ast_cond_t cond 
)

Definition at line 530 of file lock.c.

532{
534}
#define pthread_cond_signal
Definition: lock.h:636

References cond, and pthread_cond_signal.

◆ __ast_cond_timedwait()

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 
)

Definition at line 636 of file lock.c.

639{
640 int res;
641
642#ifdef DEBUG_THREADS
643 struct ast_lock_track *lt = NULL;
644 struct ast_lock_track lt_orig;
645 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
646
647#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
648 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
649 log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
650 filename, lineno, func, mutex_name);
651 DO_THREAD_CRASH;
652 return EINVAL;
653 }
654#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
655
656 lt = ast_get_reentrancy(&t->track, &t->flags, 0);
657 if (lt) {
658 ast_reentrancy_lock(lt);
659 if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) {
660 log_mutex_error(canlog, "%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
661 filename, lineno, func, mutex_name);
662 log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
663 lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
664#ifdef HAVE_BKTR
665 __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
666#endif
667 DO_THREAD_CRASH;
668 } else if (lt->reentrancy <= 0) {
669 log_mutex_error(canlog, "%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
670 filename, lineno, func, mutex_name);
671 DO_THREAD_CRASH;
672 }
673
674 /* Waiting on a condition completely suspends a recursive mutex,
675 * even if it's been recursively locked multiple times. Make a
676 * copy of the lock tracking, and reset reentrancy to zero */
677 lt_orig = *lt;
678 lt->reentrancy = 0;
679 ast_reentrancy_unlock(lt);
680
681 ast_suspend_lock_info(t);
682 }
683#endif /* DEBUG_THREADS */
684
685 res = pthread_cond_timedwait(cond, &t->mutex, abstime);
686
687#ifdef DEBUG_THREADS
688 if (res && (res != ETIMEDOUT)) {
689 log_mutex_error(canlog, "%s line %d (%s): Error waiting on condition mutex '%s'\n",
690 filename, lineno, func, strerror(res));
691 DO_THREAD_CRASH;
692 } else if (lt) {
693 restore_lock_tracking(lt, &lt_orig);
694 ast_restore_lock_info(t);
695 }
696#endif /* DEBUG_THREADS */
697
698 return res;
699}
#define ROFFSET
Definition: lock.h:246
#define pthread_mutex_t
Definition: lock.h:626
#define pthread_cond_timedwait
Definition: lock.h:639
#define NULL
Definition: resample.c:96
Lock tracking information.
Definition: lock.h:115
int reentrancy
Definition: lock.h:118
struct ast_bt backtrace[AST_MAX_REENTRANCY]
Definition: lock.h:122
pthread_t thread_id[AST_MAX_REENTRANCY]
Definition: lock.h:120
int lineno[AST_MAX_REENTRANCY]
Definition: lock.h:117
const char * file[AST_MAX_REENTRANCY]
Definition: lock.h:116
const char * func[AST_MAX_REENTRANCY]
Definition: lock.h:119
pthread_mutex_t mutex
Definition: lock.h:140

References ast_lock_track::backtrace, cond, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, NULL, pthread_cond_timedwait, pthread_mutex_t, ast_lock_track::reentrancy, ROFFSET, and ast_lock_track::thread_id.

◆ __ast_cond_wait()

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 
)

Definition at line 571 of file lock.c.

574{
575 int res;
576
577#ifdef DEBUG_THREADS
578 struct ast_lock_track *lt = NULL;
579 struct ast_lock_track lt_orig;
580 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
581
582#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
583 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
584 log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
585 filename, lineno, func, mutex_name);
586 DO_THREAD_CRASH;
587 return EINVAL;
588 }
589#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
590
591 lt = ast_get_reentrancy(&t->track, &t->flags, 0);
592 if (lt) {
593 ast_reentrancy_lock(lt);
594 if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) {
595 log_mutex_error(canlog, "%s line %d (%s): attempted wait using mutex '%s' without owning it!\n",
596 filename, lineno, func, mutex_name);
597 log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
598 lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
599#ifdef HAVE_BKTR
600 __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
601#endif
602 DO_THREAD_CRASH;
603 } else if (lt->reentrancy <= 0) {
604 log_mutex_error(canlog, "%s line %d (%s): attempted wait using an unlocked mutex '%s'\n",
605 filename, lineno, func, mutex_name);
606 DO_THREAD_CRASH;
607 }
608
609 /* Waiting on a condition completely suspends a recursive mutex,
610 * even if it's been recursively locked multiple times. Make a
611 * copy of the lock tracking, and reset reentrancy to zero */
612 lt_orig = *lt;
613 lt->reentrancy = 0;
614 ast_reentrancy_unlock(lt);
615
616 ast_suspend_lock_info(t);
617 }
618#endif /* DEBUG_THREADS */
619
620 res = pthread_cond_wait(cond, &t->mutex);
621
622#ifdef DEBUG_THREADS
623 if (res) {
624 log_mutex_error(canlog, "%s line %d (%s): Error waiting on condition mutex '%s'\n",
625 filename, lineno, func, strerror(res));
626 DO_THREAD_CRASH;
627 } else if (lt) {
628 restore_lock_tracking(lt, &lt_orig);
629 ast_restore_lock_info(t);
630 }
631#endif /* DEBUG_THREADS */
632
633 return res;
634}
#define pthread_cond_wait
Definition: lock.h:638

References ast_lock_track::backtrace, cond, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, NULL, pthread_cond_wait, pthread_mutex_t, ast_lock_track::reentrancy, ROFFSET, and ast_lock_track::thread_id.

◆ __ast_pthread_mutex_destroy()

int __ast_pthread_mutex_destroy ( const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 177 of file lock.c.

179{
180 int res;
181
182#ifdef DEBUG_THREADS
183 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 1);
184 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
185
186#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
187 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
188 /* Don't try to uninitialize an uninitialized mutex
189 * This may have no effect on linux
190 * but it always generates a core on *BSD when
191 * linked with libpthread.
192 * This is not an error condition if the mutex is created on the fly.
193 */
194 log_mutex_error(canlog, "%s line %d (%s): NOTICE: mutex '%s' is uninitialized.\n",
195 filename, lineno, func, mutex_name);
196 DO_THREAD_CRASH;
197 res = EINVAL;
198 goto lt_cleanup;
199 }
200#endif
201
202 res = pthread_mutex_trylock(&t->mutex);
203 switch (res) {
204 case 0:
206 break;
207 case EINVAL:
208 log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy invalid mutex '%s'.\n",
209 filename, lineno, func, mutex_name);
210 break;
211 case EBUSY:
212 log_mutex_error(canlog, "%s line %d (%s): Error: attempt to destroy locked mutex '%s'.\n",
213 filename, lineno, func, mutex_name);
214 if (lt) {
215 ast_reentrancy_lock(lt);
216 log_mutex_error(canlog, "%s line %d (%s): Error: '%s' was locked here.\n",
217 lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
218#ifdef HAVE_BKTR
219 __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
220#endif
221 ast_reentrancy_unlock(lt);
222 }
223 break;
224 }
225#endif /* DEBUG_THREADS */
226
227 res = pthread_mutex_destroy(&t->mutex);
228
229#ifdef DEBUG_THREADS
230 if (res) {
231 log_mutex_error(canlog, "%s line %d (%s): Error destroying mutex %s: %s\n",
232 filename, lineno, func, mutex_name, strerror(res));
233 }
234#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
235lt_cleanup:
236#endif
237 if (lt) {
238 ast_reentrancy_lock(lt);
239 lt->file[0] = filename;
240 lt->lineno[0] = lineno;
241 lt->func[0] = func;
242 lt->reentrancy = 0;
243 lt->thread_id[0] = 0;
244#ifdef HAVE_BKTR
245 memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
246#endif
247 ast_reentrancy_unlock(lt);
248 delete_reentrancy_cs(&t->track);
249 }
250#endif /* DEBUG_THREADS */
251
252 return res;
253}
#define pthread_mutex_trylock
Definition: lock.h:631
#define pthread_mutex_unlock
Definition: lock.h:630
#define pthread_mutex_destroy
Definition: lock.h:633

References ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, pthread_mutex_destroy, pthread_mutex_t, pthread_mutex_trylock, pthread_mutex_unlock, ast_lock_track::reentrancy, ROFFSET, and ast_lock_track::thread_id.

◆ __ast_pthread_mutex_init()

int __ast_pthread_mutex_init ( int  tracking,
const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 145 of file lock.c.

147{
148 int res;
149 pthread_mutexattr_t attr;
150
151#if defined(DEBUG_THREADS) && defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && \
152 defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
153 if ((t->mutex) != ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
154 int canlog = tracking && strcmp(filename, "logger.c");
155
156 log_mutex_error(canlog, "%s line %d (%s): NOTICE: mutex '%s' is already initialized.\n",
157 filename, lineno, func, mutex_name);
158 DO_THREAD_CRASH;
159 return EBUSY;
160 }
161#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
162
163#if defined(DEBUG_THREADS) || defined(DETECT_DEADLOCKS)
164 t->track = NULL;
165 t->flags.tracking = tracking;
166 t->flags.setup = 0;
167#endif /* DEBUG_THREADS */
168
169 pthread_mutexattr_init(&attr);
170 pthread_mutexattr_settype(&attr, AST_MUTEX_KIND);
171 res = pthread_mutex_init(&t->mutex, &attr);
172 pthread_mutexattr_destroy(&attr);
173
174 return res;
175}
#define AST_MUTEX_KIND
Definition: lock.h:81
#define pthread_mutex_init
Definition: lock.h:632

References AST_MUTEX_KIND, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, NULL, pthread_mutex_init, and pthread_mutex_t.

◆ __ast_pthread_mutex_lock()

int __ast_pthread_mutex_lock ( const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 255 of file lock.c.

257{
258 int res;
259
260#if defined(DETECT_DEADLOCKS) || defined(DEBUG_THREADS)
261 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
262#endif
263
264#ifdef DEBUG_THREADS
265 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
266 struct ast_bt *bt = NULL;
267
268 if (lt) {
269#ifdef HAVE_BKTR
270 struct ast_bt tmp;
271
272 /* The implementation of backtrace() may have its own locks.
273 * Capture the backtrace outside of the reentrancy lock to
274 * avoid deadlocks. See ASTERISK-22455. */
276
277 ast_reentrancy_lock(lt);
278 if (lt->reentrancy < AST_MAX_REENTRANCY) {
279 lt->backtrace[lt->reentrancy] = tmp;
280 bt = &lt->backtrace[lt->reentrancy];
281 }
282 ast_reentrancy_unlock(lt);
283#endif
284 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
285 }
286#endif /* DEBUG_THREADS */
287
288#if defined(DETECT_DEADLOCKS)
289 {
290 time_t seconds = time(NULL);
291 time_t wait_time, reported_wait = 0;
292 do {
293#ifdef HAVE_MTX_PROFILE
294 ast_mark(mtx_prof, 1);
295#endif
296 res = pthread_mutex_trylock(&t->mutex);
297#ifdef HAVE_MTX_PROFILE
298 ast_mark(mtx_prof, 0);
299#endif
300 if (res == EBUSY) {
301 wait_time = time(NULL) - seconds;
302 if (wait_time > reported_wait && (wait_time % 5) == 0) {
303 log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for mutex '%s'?\n",
304 filename, lineno, func, (int) wait_time, mutex_name);
305#ifdef DEBUG_THREADS
306 if (lt) {
307 ast_reentrancy_lock(lt);
308#ifdef HAVE_BKTR
309 __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
310#endif
311 log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
312 lt->file[ROFFSET], lt->lineno[ROFFSET],
313 lt->func[ROFFSET], mutex_name);
314#ifdef HAVE_BKTR
315 __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
316#endif
317 ast_reentrancy_unlock(lt);
318 }
319#endif
320 reported_wait = wait_time;
321 if ((int) wait_time < 10) { /* Only emit an event when a deadlock starts, not every 5 seconds */
322 /*** DOCUMENTATION
323 <managerEvent language="en_US" name="DeadlockStart">
324 <managerEventInstance class="EVENT_FLAG_SYSTEM">
325 <since>
326 <version>16.29.0</version>
327 <version>18.15.0</version>
328 <version>19.7.0</version>
329 </since>
330 <synopsis>Raised when a probable deadlock has started.
331 Delivery of this event is attempted but not guaranteed,
332 and could fail for example if the manager itself is deadlocked.
333 </synopsis>
334 <syntax>
335 <parameter name="Mutex">
336 <para>The mutex involved in the deadlock.</para>
337 </parameter>
338 </syntax>
339 </managerEventInstance>
340 </managerEvent>
341 ***/
342 manager_event(EVENT_FLAG_SYSTEM, "DeadlockStart",
343 "Mutex: %s\r\n",
344 mutex_name);
345 }
346 }
347 usleep(200);
348 }
349 } while (res == EBUSY);
350 }
351#else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
352#ifdef HAVE_MTX_PROFILE
353 ast_mark(mtx_prof, 1);
354 res = pthread_mutex_trylock(&t->mutex);
355 ast_mark(mtx_prof, 0);
356 if (res)
357#endif
358 res = pthread_mutex_lock(&t->mutex);
359#endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
360
361#ifdef DEBUG_THREADS
362 if (lt && !res) {
363 ast_reentrancy_lock(lt);
364 if (lt->reentrancy < AST_MAX_REENTRANCY) {
365 lt->file[lt->reentrancy] = filename;
366 lt->lineno[lt->reentrancy] = lineno;
367 lt->func[lt->reentrancy] = func;
368 lt->thread_id[lt->reentrancy] = pthread_self();
369 lt->reentrancy++;
370 } else {
371 log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
372 filename, lineno, func, mutex_name);
373 }
374 ast_reentrancy_unlock(lt);
375 ast_mark_lock_acquired(t);
376 } else if (lt) {
377#ifdef HAVE_BKTR
378 if (lt->reentrancy) {
379 ast_reentrancy_lock(lt);
380 bt = &lt->backtrace[lt->reentrancy-1];
381 ast_reentrancy_unlock(lt);
382 } else {
383 bt = NULL;
384 }
385#endif
386 ast_remove_lock_info(t, bt);
387 }
388 if (res) {
389 log_mutex_error(canlog, "%s line %d (%s): Error obtaining mutex: %s\n",
390 filename, lineno, func, strerror(res));
391 DO_THREAD_CRASH;
392 }
393#endif /* DEBUG_THREADS */
394
395 return res;
396}
int64_t ast_mark(int, int start1_stop0)
Definition: astman.c:103
#define ast_bt_get_addresses(bt)
Definition: backtrace.h:38
@ AST_MUTEX
Definition: check_expr.c:36
#define AST_MAX_REENTRANCY
Definition: lock.h:105
#define pthread_mutex_lock
Definition: lock.h:629
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:254
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
A structure to hold backtrace information. This structure provides an easy means to store backtrace i...
Definition: backtrace.h:50

References ast_bt_get_addresses, ast_mark(), AST_MAX_REENTRANCY, AST_MUTEX, ast_lock_track::backtrace, EVENT_FLAG_SYSTEM, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, manager_event, ast_mutex_info::mutex, NULL, pthread_mutex_lock, pthread_mutex_trylock, ast_lock_track::reentrancy, ROFFSET, and ast_lock_track::thread_id.

Referenced by __ao2_lock().

◆ __ast_pthread_mutex_trylock()

int __ast_pthread_mutex_trylock ( const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 398 of file lock.c.

400{
401 int res;
402
403#ifdef DEBUG_THREADS
404 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
405 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
406 struct ast_bt *bt = NULL;
407
408 if (lt) {
409#ifdef HAVE_BKTR
410 struct ast_bt tmp;
411
412 /* The implementation of backtrace() may have its own locks.
413 * Capture the backtrace outside of the reentrancy lock to
414 * avoid deadlocks. See ASTERISK-22455. */
416
417 ast_reentrancy_lock(lt);
418 if (lt->reentrancy < AST_MAX_REENTRANCY) {
419 lt->backtrace[lt->reentrancy] = tmp;
420 bt = &lt->backtrace[lt->reentrancy];
421 }
422 ast_reentrancy_unlock(lt);
423#endif
424 ast_store_lock_info(AST_MUTEX, filename, lineno, func, mutex_name, t, bt);
425 }
426#endif /* DEBUG_THREADS */
427
428 res = pthread_mutex_trylock(&t->mutex);
429
430#ifdef DEBUG_THREADS
431 if (lt && !res) {
432 ast_reentrancy_lock(lt);
433 if (lt->reentrancy < AST_MAX_REENTRANCY) {
434 lt->file[lt->reentrancy] = filename;
435 lt->lineno[lt->reentrancy] = lineno;
436 lt->func[lt->reentrancy] = func;
437 lt->thread_id[lt->reentrancy] = pthread_self();
438 lt->reentrancy++;
439 } else {
440 log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
441 filename, lineno, func, mutex_name);
442 }
443 ast_reentrancy_unlock(lt);
444 ast_mark_lock_acquired(t);
445 } else if (lt) {
447 }
448#endif /* DEBUG_THREADS */
449
450 return res;
451}
void ast_mark_lock_failed(void *lock_addr)
Definition: extconf.c:2313

References ast_bt_get_addresses, ast_mark_lock_failed(), AST_MAX_REENTRANCY, AST_MUTEX, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, NULL, pthread_mutex_trylock, ast_lock_track::reentrancy, and ast_lock_track::thread_id.

Referenced by __ao2_trylock().

◆ __ast_pthread_mutex_unlock()

int __ast_pthread_mutex_unlock ( const char *  filename,
int  lineno,
const char *  func,
const char *  mutex_name,
ast_mutex_t t 
)

Definition at line 453 of file lock.c.

455{
456 int res;
457
458#ifdef DEBUG_THREADS
459 struct ast_lock_track *lt = NULL;
460 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
461 struct ast_bt *bt = NULL;
462
463#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
464 if ((t->mutex) == ((pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER)) {
465 log_mutex_error(canlog, "%s line %d (%s): Error: mutex '%s' is uninitialized.\n",
466 filename, lineno, func, mutex_name);
467 DO_THREAD_CRASH;
468 return EINVAL;
469 }
470#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
471
472 lt = ast_get_reentrancy(&t->track, &t->flags, 0);
473 if (lt) {
474 ast_reentrancy_lock(lt);
475 if (lt->reentrancy && (lt->thread_id[ROFFSET] != pthread_self())) {
476 log_mutex_error(canlog, "%s line %d (%s): attempted unlock mutex '%s' without owning it!\n",
477 filename, lineno, func, mutex_name);
478 log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
479 lt->file[ROFFSET], lt->lineno[ROFFSET], lt->func[ROFFSET], mutex_name);
480#ifdef HAVE_BKTR
481 __dump_backtrace(&lt->backtrace[ROFFSET], canlog);
482#endif
483 DO_THREAD_CRASH;
484 }
485
486 if (--lt->reentrancy < 0) {
487 log_mutex_error(canlog, "%s line %d (%s): mutex '%s' freed more times than we've locked!\n",
488 filename, lineno, func, mutex_name);
489 lt->reentrancy = 0;
490 }
491
492 if (lt->reentrancy < AST_MAX_REENTRANCY) {
493 lt->file[lt->reentrancy] = NULL;
494 lt->lineno[lt->reentrancy] = 0;
495 lt->func[lt->reentrancy] = NULL;
496 lt->thread_id[lt->reentrancy] = 0;
497 }
498
499#ifdef HAVE_BKTR
500 if (lt->reentrancy) {
501 bt = &lt->backtrace[lt->reentrancy - 1];
502 }
503#endif
504 ast_reentrancy_unlock(lt);
505
506 ast_remove_lock_info(t, bt);
507 }
508#endif /* DEBUG_THREADS */
509
510 res = pthread_mutex_unlock(&t->mutex);
511
512#ifdef DEBUG_THREADS
513 if (res) {
514 log_mutex_error(canlog, "%s line %d (%s): Error releasing mutex: %s\n",
515 filename, lineno, func, strerror(res));
516 DO_THREAD_CRASH;
517 }
518#endif /* DEBUG_THREADS */
519
520 return res;
521}

References AST_MAX_REENTRANCY, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_mutex_info::mutex, NULL, pthread_mutex_t, pthread_mutex_unlock, ast_lock_track::reentrancy, ROFFSET, and ast_lock_track::thread_id.

Referenced by __ao2_unlock().

◆ __ast_rwlock_destroy()

int __ast_rwlock_destroy ( const char *  filename,
int  lineno,
const char *  func,
const char *  rwlock_name,
ast_rwlock_t t 
)

Definition at line 735 of file lock.c.

736{
737 int res;
738
739#ifdef DEBUG_THREADS
740 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 1);
741 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
742
743#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
744 if (t->lock == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
745 log_mutex_error(canlog, "%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
746 filename, lineno, func, rwlock_name);
747 DO_THREAD_CRASH;
748 res = EINVAL;
749 goto lt_cleanup;
750 }
751#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
752#endif /* DEBUG_THREADS */
753
754 res = pthread_rwlock_destroy(&t->lock);
755
756#ifdef DEBUG_THREADS
757 if (res) {
758 log_mutex_error(canlog, "%s line %d (%s): Error destroying rwlock %s: %s\n",
759 filename, lineno, func, rwlock_name, strerror(res));
760 }
761#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
762lt_cleanup:
763#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
764 if (lt) {
765 ast_reentrancy_lock(lt);
766 lt->file[0] = filename;
767 lt->lineno[0] = lineno;
768 lt->func[0] = func;
769 lt->reentrancy = 0;
770 lt->thread_id[0] = 0;
771#ifdef HAVE_BKTR
772 memset(&lt->backtrace[0], 0, sizeof(lt->backtrace[0]));
773#endif
774 ast_reentrancy_unlock(lt);
775 delete_reentrancy_cs(&t->track);
776 }
777#endif /* DEBUG_THREADS */
778
779 return res;
780}
#define __AST_RWLOCK_INIT_VALUE
Definition: lock.h:88
pthread_rwlock_t lock
Definition: lock.h:162

References __AST_RWLOCK_INIT_VALUE, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, ast_lock_track::reentrancy, and ast_lock_track::thread_id.

◆ __ast_rwlock_init()

int __ast_rwlock_init ( int  tracking,
const char *  filename,
int  lineno,
const char *  func,
const char *  rwlock_name,
ast_rwlock_t t 
)

Definition at line 701 of file lock.c.

703{
704 int res;
705 pthread_rwlockattr_t attr;
706
707#if defined(DEBUG_THREADS) && defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && \
708 defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
709 if (t->lock != ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
710 int canlog = tracking && strcmp(filename, "logger.c");
711
712 log_mutex_error(canlog, "%s line %d (%s): Warning: rwlock '%s' is already initialized.\n",
713 filename, lineno, func, rwlock_name);
714 DO_THREAD_CRASH;
715 return EBUSY;
716 }
717#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
718
719#if defined(DEBUG_THREADS) || defined(DETECT_DEADLOCKS)
720 t->track = NULL;
721 t->flags.tracking = tracking;
722 t->flags.setup = 0;
723#endif /* DEBUG_THREADS */
724
725 pthread_rwlockattr_init(&attr);
726#ifdef HAVE_PTHREAD_RWLOCK_PREFER_WRITER_NP
727 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NP);
728#endif
729 res = pthread_rwlock_init(&t->lock, &attr);
730 pthread_rwlockattr_destroy(&attr);
731
732 return res;
733}

References __AST_RWLOCK_INIT_VALUE, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, and NULL.

◆ __ast_rwlock_rdlock()

int __ast_rwlock_rdlock ( const char *  filename,
int  lineno,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 853 of file lock.c.

855{
856 int res;
857
858#if defined(DEBUG_THREADS) || defined(DETECT_DEADLOCKS)
859 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
860#endif
861
862#ifdef DEBUG_THREADS
863 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
864 struct ast_bt *bt = NULL;
865
866 if (lt) {
867#ifdef HAVE_BKTR
868 struct ast_bt tmp;
869
870 /* The implementation of backtrace() may have its own locks.
871 * Capture the backtrace outside of the reentrancy lock to
872 * avoid deadlocks. See ASTERISK-22455. */
874
875 ast_reentrancy_lock(lt);
876 if (lt->reentrancy < AST_MAX_REENTRANCY) {
877 lt->backtrace[lt->reentrancy] = tmp;
878 bt = &lt->backtrace[lt->reentrancy];
879 }
880 ast_reentrancy_unlock(lt);
881#endif
882 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
883 }
884#endif /* DEBUG_THREADS */
885
886#if defined(DETECT_DEADLOCKS)
887 {
888 time_t seconds = time(NULL);
889 time_t wait_time, reported_wait = 0;
890 do {
891 res = pthread_rwlock_tryrdlock(&t->lock);
892 if (res == EBUSY) {
893 wait_time = time(NULL) - seconds;
894 if (wait_time > reported_wait && (wait_time % 5) == 0) {
895 log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for readlock '%s'?\n",
896 filename, line, func, (int)wait_time, name);
897#ifdef DEBUG_THREADS
898 if (lt) {
899 ast_reentrancy_lock(lt);
900#ifdef HAVE_BKTR
901 __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
902#endif
903 log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
904 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
905 lt->func[lt->reentrancy-1], name);
906#ifdef HAVE_BKTR
907 __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
908#endif
909 ast_reentrancy_unlock(lt);
910 }
911#endif
912 reported_wait = wait_time;
913 }
914 usleep(200);
915 }
916 } while (res == EBUSY);
917 }
918#else /* !DETECT_DEADLOCKS */
919 res = pthread_rwlock_rdlock(&t->lock);
920#endif /* !DETECT_DEADLOCKS */
921
922#ifdef DEBUG_THREADS
923 if (!res && lt) {
924 ast_reentrancy_lock(lt);
925 if (lt->reentrancy < AST_MAX_REENTRANCY) {
926 lt->file[lt->reentrancy] = filename;
927 lt->lineno[lt->reentrancy] = line;
928 lt->func[lt->reentrancy] = func;
929 lt->thread_id[lt->reentrancy] = pthread_self();
930 lt->reentrancy++;
931 }
932 ast_reentrancy_unlock(lt);
933 ast_mark_lock_acquired(t);
934 } else if (lt) {
935#ifdef HAVE_BKTR
936 if (lt->reentrancy) {
937 ast_reentrancy_lock(lt);
938 bt = &lt->backtrace[lt->reentrancy-1];
939 ast_reentrancy_unlock(lt);
940 } else {
941 bt = NULL;
942 }
943#endif
944 ast_remove_lock_info(t, bt);
945 }
946
947 if (res) {
948 log_mutex_error(canlog, "%s line %d (%s): Error obtaining read lock: %s\n",
949 filename, line, func, strerror(res));
950 DO_THREAD_CRASH;
951 }
952#endif /* DEBUG_THREADS */
953
954 return res;
955}
@ AST_RDLOCK
Definition: check_expr.c:37
static const char name[]
Definition: format_mp3.c:68

References ast_bt_get_addresses, AST_MAX_REENTRANCY, AST_RDLOCK, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, name, NULL, ast_lock_track::reentrancy, and ast_lock_track::thread_id.

Referenced by __ao2_global_obj_ref(), __ao2_lock(), and __ast_heap_rdlock().

◆ __ast_rwlock_timedrdlock()

int __ast_rwlock_timedrdlock ( const char *  filename,
int  lineno,
const char *  func,
ast_rwlock_t t,
const char *  name,
const struct timespec *  abs_timeout 
)

Definition at line 1060 of file lock.c.

1062{
1063 int res;
1064
1065#ifdef DEBUG_THREADS
1066 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
1067 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
1068 struct ast_bt *bt = NULL;
1069
1070 if (lt) {
1071#ifdef HAVE_BKTR
1072 struct ast_bt tmp;
1073
1074 /* The implementation of backtrace() may have its own locks.
1075 * Capture the backtrace outside of the reentrancy lock to
1076 * avoid deadlocks. See ASTERISK-22455. */
1078
1079 ast_reentrancy_lock(lt);
1080 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1081 lt->backtrace[lt->reentrancy] = tmp;
1082 bt = &lt->backtrace[lt->reentrancy];
1083 }
1084 ast_reentrancy_unlock(lt);
1085#endif
1086 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1087 }
1088#endif /* DEBUG_THREADS */
1089
1090#ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1091 res = pthread_rwlock_timedrdlock(&t->lock, abs_timeout);
1092#else
1093 do {
1094 struct timeval _now;
1095 for (;;) {
1096 if (!(res = pthread_rwlock_tryrdlock(&t->lock))) {
1097 break;
1098 }
1099 _now = ast_tvnow();
1100 if (_now.tv_sec > abs_timeout->tv_sec || (_now.tv_sec == abs_timeout->tv_sec && _now.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1101 break;
1102 }
1103 usleep(1);
1104 }
1105 } while (0);
1106#endif
1107
1108#ifdef DEBUG_THREADS
1109 if (!res && lt) {
1110 ast_reentrancy_lock(lt);
1111 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1112 lt->file[lt->reentrancy] = filename;
1113 lt->lineno[lt->reentrancy] = line;
1114 lt->func[lt->reentrancy] = func;
1115 lt->thread_id[lt->reentrancy] = pthread_self();
1116 lt->reentrancy++;
1117 }
1118 ast_reentrancy_unlock(lt);
1119 ast_mark_lock_acquired(t);
1120 } else if (lt) {
1121#ifdef HAVE_BKTR
1122 if (lt->reentrancy) {
1123 ast_reentrancy_lock(lt);
1124 bt = &lt->backtrace[lt->reentrancy-1];
1125 ast_reentrancy_unlock(lt);
1126 } else {
1127 bt = NULL;
1128 }
1129#endif
1130 ast_remove_lock_info(t, bt);
1131 }
1132 if (res) {
1133 log_mutex_error(canlog, "%s line %d (%s): Error obtaining read lock: %s\n",
1134 filename, line, func, strerror(res));
1135 DO_THREAD_CRASH;
1136 }
1137#endif /* DEBUG_THREADS */
1138
1139 return res;
1140}
@ AST_WRLOCK
Definition: check_expr.c:38
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References ast_bt_get_addresses, AST_MAX_REENTRANCY, ast_tvnow(), AST_WRLOCK, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, name, NULL, ast_lock_track::reentrancy, and ast_lock_track::thread_id.

◆ __ast_rwlock_timedwrlock()

int __ast_rwlock_timedwrlock ( const char *  filename,
int  lineno,
const char *  func,
ast_rwlock_t t,
const char *  name,
const struct timespec *  abs_timeout 
)

Definition at line 1142 of file lock.c.

1144{
1145 int res;
1146
1147#ifdef DEBUG_THREADS
1148 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
1149 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
1150 struct ast_bt *bt = NULL;
1151
1152 if (lt) {
1153#ifdef HAVE_BKTR
1154 struct ast_bt tmp;
1155
1156 /* The implementation of backtrace() may have its own locks.
1157 * Capture the backtrace outside of the reentrancy lock to
1158 * avoid deadlocks. See ASTERISK-22455. */
1160
1161 ast_reentrancy_lock(lt);
1162 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1163 lt->backtrace[lt->reentrancy] = tmp;
1164 bt = &lt->backtrace[lt->reentrancy];
1165 }
1166 ast_reentrancy_unlock(lt);
1167#endif
1168 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1169 }
1170#endif /* DEBUG_THREADS */
1171
1172#ifdef HAVE_PTHREAD_RWLOCK_TIMEDWRLOCK
1173 res = pthread_rwlock_timedwrlock(&t->lock, abs_timeout);
1174#else
1175 do {
1176 struct timeval _now;
1177 for (;;) {
1178 if (!(res = pthread_rwlock_trywrlock(&t->lock))) {
1179 break;
1180 }
1181 _now = ast_tvnow();
1182 if (_now.tv_sec > abs_timeout->tv_sec || (_now.tv_sec == abs_timeout->tv_sec && _now.tv_usec * 1000 > abs_timeout->tv_nsec)) {
1183 break;
1184 }
1185 usleep(1);
1186 }
1187 } while (0);
1188#endif
1189
1190#ifdef DEBUG_THREADS
1191 if (!res && lt) {
1192 ast_reentrancy_lock(lt);
1193 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1194 lt->file[lt->reentrancy] = filename;
1195 lt->lineno[lt->reentrancy] = line;
1196 lt->func[lt->reentrancy] = func;
1197 lt->thread_id[lt->reentrancy] = pthread_self();
1198 lt->reentrancy++;
1199 }
1200 ast_reentrancy_unlock(lt);
1201 ast_mark_lock_acquired(t);
1202 } else if (lt) {
1203#ifdef HAVE_BKTR
1204 if (lt->reentrancy) {
1205 ast_reentrancy_lock(lt);
1206 bt = &lt->backtrace[lt->reentrancy-1];
1207 ast_reentrancy_unlock(lt);
1208 } else {
1209 bt = NULL;
1210 }
1211#endif
1212 ast_remove_lock_info(t, bt);
1213 }
1214 if (res) {
1215 log_mutex_error(canlog, "%s line %d (%s): Error obtaining read lock: %s\n",
1216 filename, line, func, strerror(res));
1217 DO_THREAD_CRASH;
1218 }
1219#endif /* DEBUG_THREADS */
1220
1221 return res;
1222}

References ast_bt_get_addresses, AST_MAX_REENTRANCY, ast_tvnow(), AST_WRLOCK, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, name, NULL, ast_lock_track::reentrancy, and ast_lock_track::thread_id.

◆ __ast_rwlock_tryrdlock()

int __ast_rwlock_tryrdlock ( const char *  filename,
int  lineno,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 1224 of file lock.c.

1225{
1226 int res;
1227
1228#ifdef DEBUG_THREADS
1229 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
1230 struct ast_bt *bt = NULL;
1231
1232 if (lt) {
1233#ifdef HAVE_BKTR
1234 struct ast_bt tmp;
1235
1236 /* The implementation of backtrace() may have its own locks.
1237 * Capture the backtrace outside of the reentrancy lock to
1238 * avoid deadlocks. See ASTERISK-22455. */
1240
1241 ast_reentrancy_lock(lt);
1242 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1243 lt->backtrace[lt->reentrancy] = tmp;
1244 bt = &lt->backtrace[lt->reentrancy];
1245 }
1246 ast_reentrancy_unlock(lt);
1247#endif
1248 ast_store_lock_info(AST_RDLOCK, filename, line, func, name, t, bt);
1249 }
1250#endif /* DEBUG_THREADS */
1251
1252 res = pthread_rwlock_tryrdlock(&t->lock);
1253
1254#ifdef DEBUG_THREADS
1255 if (!res && lt) {
1256 ast_reentrancy_lock(lt);
1257 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1258 lt->file[lt->reentrancy] = filename;
1259 lt->lineno[lt->reentrancy] = line;
1260 lt->func[lt->reentrancy] = func;
1261 lt->thread_id[lt->reentrancy] = pthread_self();
1262 lt->reentrancy++;
1263 }
1264 ast_reentrancy_unlock(lt);
1265 ast_mark_lock_acquired(t);
1266 } else if (lt) {
1268 }
1269#endif /* DEBUG_THREADS */
1270
1271 return res;
1272}

References ast_bt_get_addresses, ast_mark_lock_failed(), AST_MAX_REENTRANCY, AST_RDLOCK, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, name, NULL, ast_lock_track::reentrancy, and ast_lock_track::thread_id.

Referenced by __ao2_trylock().

◆ __ast_rwlock_trywrlock()

int __ast_rwlock_trywrlock ( const char *  filename,
int  lineno,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 1274 of file lock.c.

1275{
1276 int res;
1277
1278#ifdef DEBUG_THREADS
1279 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
1280 struct ast_bt *bt = NULL;
1281
1282 if (lt) {
1283#ifdef HAVE_BKTR
1284 struct ast_bt tmp;
1285
1286 /* The implementation of backtrace() may have its own locks.
1287 * Capture the backtrace outside of the reentrancy lock to
1288 * avoid deadlocks. See ASTERISK-22455. */
1290
1291 ast_reentrancy_lock(lt);
1292 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1293 lt->backtrace[lt->reentrancy] = tmp;
1294 bt = &lt->backtrace[lt->reentrancy];
1295 }
1296 ast_reentrancy_unlock(lt);
1297#endif
1298 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
1299 }
1300#endif /* DEBUG_THREADS */
1301
1302 res = pthread_rwlock_trywrlock(&t->lock);
1303
1304#ifdef DEBUG_THREADS
1305 if (!res && lt) {
1306 ast_reentrancy_lock(lt);
1307 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1308 lt->file[lt->reentrancy] = filename;
1309 lt->lineno[lt->reentrancy] = line;
1310 lt->func[lt->reentrancy] = func;
1311 lt->thread_id[lt->reentrancy] = pthread_self();
1312 lt->reentrancy++;
1313 }
1314 ast_reentrancy_unlock(lt);
1315 ast_mark_lock_acquired(t);
1316 } else if (lt) {
1318 }
1319#endif /* DEBUG_THREADS */
1320
1321 return res;
1322}

References ast_bt_get_addresses, ast_mark_lock_failed(), AST_MAX_REENTRANCY, AST_WRLOCK, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, name, NULL, ast_lock_track::reentrancy, and ast_lock_track::thread_id.

Referenced by __ao2_trylock().

◆ __ast_rwlock_unlock()

int __ast_rwlock_unlock ( const char *  filename,
int  lineno,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 782 of file lock.c.

783{
784 int res;
785
786#ifdef DEBUG_THREADS
787 struct ast_lock_track *lt = NULL;
788 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
789 struct ast_bt *bt = NULL;
790 int lock_found = 0;
791
792#if defined(AST_MUTEX_INIT_W_CONSTRUCTORS) && defined(CAN_COMPARE_MUTEX_TO_INIT_VALUE)
793 if ((t->lock) == ((pthread_rwlock_t) __AST_RWLOCK_INIT_VALUE)) {
794 log_mutex_error(canlog, "%s line %d (%s): Warning: rwlock '%s' is uninitialized.\n",
795 filename, line, func, name);
796 DO_THREAD_CRASH;
797 return EINVAL;
798 }
799#endif /* AST_MUTEX_INIT_W_CONSTRUCTORS */
800
801 lt = ast_get_reentrancy(&t->track, &t->flags, 0);
802 if (lt) {
803 ast_reentrancy_lock(lt);
804 if (lt->reentrancy) {
805 int i;
806 pthread_t self = pthread_self();
807 for (i = lt->reentrancy - 1; i >= 0; --i) {
808 if (lt->thread_id[i] == self) {
809 lock_found = 1;
810 if (i != lt->reentrancy - 1) {
811 lt->file[i] = lt->file[lt->reentrancy - 1];
812 lt->lineno[i] = lt->lineno[lt->reentrancy - 1];
813 lt->func[i] = lt->func[lt->reentrancy - 1];
814 lt->thread_id[i] = lt->thread_id[lt->reentrancy - 1];
815 }
816#ifdef HAVE_BKTR
817 bt = &lt->backtrace[i];
818#endif
819 lt->file[lt->reentrancy - 1] = NULL;
820 lt->lineno[lt->reentrancy - 1] = 0;
821 lt->func[lt->reentrancy - 1] = NULL;
823 break;
824 }
825 }
826 }
827
828 if (lock_found && --lt->reentrancy < 0) {
829 log_mutex_error(canlog, "%s line %d (%s): rwlock '%s' freed more times than we've locked!\n",
830 filename, line, func, name);
831 lt->reentrancy = 0;
832 }
833
834 ast_reentrancy_unlock(lt);
835
836 ast_remove_lock_info(t, bt);
837 }
838#endif /* DEBUG_THREADS */
839
840 res = pthread_rwlock_unlock(&t->lock);
841
842#ifdef DEBUG_THREADS
843 if (res) {
844 log_mutex_error(canlog, "%s line %d (%s): Error releasing rwlock: %s\n",
845 filename, line, func, strerror(res));
846 DO_THREAD_CRASH;
847 }
848#endif /* DEBUG_THREADS */
849
850 return res;
851}
#define AST_PTHREADT_NULL
Definition: lock.h:70

References __AST_RWLOCK_INIT_VALUE, AST_PTHREADT_NULL, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, name, NULL, ast_lock_track::reentrancy, and ast_lock_track::thread_id.

Referenced by __ao2_global_obj_ref(), __ao2_global_obj_replace(), __ao2_unlock(), and __ast_heap_unlock().

◆ __ast_rwlock_wrlock()

int __ast_rwlock_wrlock ( const char *  filename,
int  lineno,
const char *  func,
ast_rwlock_t t,
const char *  name 
)

Definition at line 957 of file lock.c.

959{
960 int res;
961
962#if defined(DEBUG_THREADS) || defined(DETECT_DEADLOCKS)
963 int canlog = t->flags.tracking && strcmp(filename, "logger.c");
964#endif
965
966#ifdef DEBUG_THREADS
967 struct ast_lock_track *lt = ast_get_reentrancy(&t->track, &t->flags, 0);
968 struct ast_bt *bt = NULL;
969
970 if (lt) {
971#ifdef HAVE_BKTR
972 struct ast_bt tmp;
973
974 /* The implementation of backtrace() may have its own locks.
975 * Capture the backtrace outside of the reentrancy lock to
976 * avoid deadlocks. See ASTERISK-22455. */
978
979 ast_reentrancy_lock(lt);
980 if (lt->reentrancy < AST_MAX_REENTRANCY) {
981 lt->backtrace[lt->reentrancy] = tmp;
982 bt = &lt->backtrace[lt->reentrancy];
983 }
984 ast_reentrancy_unlock(lt);
985#endif
986 ast_store_lock_info(AST_WRLOCK, filename, line, func, name, t, bt);
987 }
988#endif /* DEBUG_THREADS */
989
990#ifdef DETECT_DEADLOCKS
991 {
992 time_t seconds = time(NULL);
993 time_t wait_time, reported_wait = 0;
994 do {
995 res = pthread_rwlock_trywrlock(&t->lock);
996 if (res == EBUSY) {
997 wait_time = time(NULL) - seconds;
998 if (wait_time > reported_wait && (wait_time % 5) == 0) {
999 log_mutex_error(canlog, "%s line %d (%s): Deadlock? waited %d sec for writelock '%s'?\n",
1000 filename, line, func, (int)wait_time, name);
1001#ifdef DEBUG_THREADS
1002 if (lt) {
1003 ast_reentrancy_lock(lt);
1004#ifdef HAVE_BKTR
1005 __dump_backtrace(&lt->backtrace[lt->reentrancy], canlog);
1006#endif
1007 log_mutex_error(canlog, "%s line %d (%s): '%s' was locked here.\n",
1008 lt->file[lt->reentrancy-1], lt->lineno[lt->reentrancy-1],
1009 lt->func[lt->reentrancy-1], name);
1010#ifdef HAVE_BKTR
1011 __dump_backtrace(&lt->backtrace[lt->reentrancy-1], canlog);
1012#endif
1013 ast_reentrancy_unlock(lt);
1014 }
1015#endif
1016 reported_wait = wait_time;
1017 }
1018 usleep(200);
1019 }
1020 } while (res == EBUSY);
1021 }
1022#else /* !DETECT_DEADLOCKS */
1023 res = pthread_rwlock_wrlock(&t->lock);
1024#endif /* !DETECT_DEADLOCKS */
1025
1026#ifdef DEBUG_THREADS
1027 if (!res && lt) {
1028 ast_reentrancy_lock(lt);
1029 if (lt->reentrancy < AST_MAX_REENTRANCY) {
1030 lt->file[lt->reentrancy] = filename;
1031 lt->lineno[lt->reentrancy] = line;
1032 lt->func[lt->reentrancy] = func;
1033 lt->thread_id[lt->reentrancy] = pthread_self();
1034 lt->reentrancy++;
1035 }
1036 ast_reentrancy_unlock(lt);
1037 ast_mark_lock_acquired(t);
1038 } else if (lt) {
1039#ifdef HAVE_BKTR
1040 if (lt->reentrancy) {
1041 ast_reentrancy_lock(lt);
1042 bt = &lt->backtrace[lt->reentrancy-1];
1043 ast_reentrancy_unlock(lt);
1044 } else {
1045 bt = NULL;
1046 }
1047#endif
1048 ast_remove_lock_info(t, bt);
1049 }
1050 if (res) {
1051 log_mutex_error(canlog, "%s line %d (%s): Error obtaining write lock: %s\n",
1052 filename, line, func, strerror(res));
1053 DO_THREAD_CRASH;
1054 }
1055#endif /* DEBUG_THREADS */
1056
1057 return res;
1058}

References ast_bt_get_addresses, AST_MAX_REENTRANCY, AST_WRLOCK, ast_lock_track::backtrace, ast_lock_track::file, ast_lock_track::func, ast_lock_track::lineno, ast_rwlock_info::lock, name, NULL, ast_lock_track::reentrancy, and ast_lock_track::thread_id.

Referenced by __ao2_global_obj_replace(), __ao2_lock(), and __ast_heap_wrlock().

◆ ast_atomic_dec_and_test()

int ast_atomic_dec_and_test ( volatile int *  p)
inline

decrement *p by 1 and return true if the variable has reached 0.

Useful e.g. to check if a refcount has reached 0.

Definition at line 771 of file lock.h.

Referenced by dispose_conf(), iax2_process_thread_cleanup(), run_station(), and sla_station_exec().

◆ ast_atomic_fetchadd_int()

int ast_atomic_fetchadd_int ( volatile int *  p,
int  v 
)
inline

Atomically add v to *p and return the previous value of *p.

This can be used to handle reference counts, and the return value can be used to generate unique identifiers.

Definition at line 761 of file lock.h.

769{

Referenced by __ao2_link(), __ao2_lock(), __ao2_ref(), __ao2_trylock(), __ao2_unlock(), __ast_channel_alloc_ap(), __ast_channel_internal_alloc_with_initializers(), __ast_module_ref(), __ast_module_unref(), __ast_module_user_add(), __ast_module_user_hangup_all(), __ast_module_user_remove(), __container_unlink_node_debug(), __manager_event_sessions_va(), acf_odbc_read(), action_login(), admin_exec(), advance_event(), ao2_container_count(), append_event(), ast_bridge_interval_hook(), ast_channel_destructor(), ast_channel_internal_setup_topics(), ast_cli_command_full(), ast_create_callid(), ast_odbc_execute_sql(), ast_odbc_prepare(), ast_odbc_prepare_and_execute(), ast_odbc_smart_execute(), ast_sip_schedule_task(), ast_taskprocessor_seq_num(), AST_TEST_DEFINE(), ast_undestroyed_channels(), ast_unreal_new_channels(), authenticate_verify(), bridge_channel_handle_interval(), bridge_channel_queue_action_data_sync(), build_conf(), cc_device_monitor_init(), cc_extension_monitor_init(), cc_interfaces_datastore_init(), cdr_object_alloc(), chan_pjsip_new(), container_destruct(), dahdi_destroy(), dahdi_request(), dahdi_translate(), destroy_session(), dial_append_common(), dispatch_message(), dns_query_set_callback(), dundi_query_read(), enum_query_read(), fax_session_new(), fax_session_release(), fax_session_reserve(), find_idle_thread(), find_load_queue_rt_friendly(), find_session(), find_transcoders(), generate_msg_id(), generic_fax_exec(), grab_last(), hash_ao2_container_init(), hash_test_grow(), hash_test_lookup(), hook_read(), ht_delete(), ht_new(), httpd_helper_thread(), iax2_destroy_helper(), iax2_process_thread(), iax_frame_free(), iax_frame_new(), inprocess_count(), internal_ao2_alloc(), internal_stasis_subscribe(), pjsip_history_entry_alloc(), publish_msg(), pubsub_on_rx_publish_request(), rb_ao2_container_init(), rec_request(), receivefax_exec(), reload_single_queue(), run_station(), sendfax_exec(), session_destructor(), session_do(), sip_create_publication(), sla_add_trunk_to_station(), sla_handle_hold_event(), sla_station_exec(), smdi_msg_retrieve_read(), spandsp_fax_switch_to_t38(), stasis_app_control_snoop(), stasis_caching_topic_create(), stasis_cp_all_create(), stasis_message_type_create(), transport_create(), try_merge_optimize_out(), try_swap_optimize_out(), update_stats(), and worker_thread_alloc().