Asterisk - The Open Source Telephony Project GIT-master-85241bd
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 517 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 540 of file lock.h.

◆ __AST_RWLOCK_INIT_VALUE

#define __AST_RWLOCK_INIT_VALUE   PTHREAD_RWLOCK_INITIALIZER

Definition at line 84 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 469 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 670 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 678 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 669 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 677 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 681 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 673 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 685 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 746 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 743 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 682 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 674 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 686 of file lock.h.

◆ ast_cond_broadcast

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

Definition at line 204 of file lock.h.

◆ ast_cond_destroy

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

Definition at line 202 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 201 of file lock.h.

◆ ast_cond_signal

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

Definition at line 203 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 206 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 205 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 90 of file lock.h.

◆ AST_MAX_REENTRANCY

#define AST_MAX_REENTRANCY   10

Definition at line 101 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 520 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 521 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 188 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 186 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 187 of file lock.h.

◆ AST_MUTEX_INIT_VALUE

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

Definition at line 95 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 96 of file lock.h.

◆ AST_MUTEX_INITIALIZER

#define AST_MUTEX_INITIALIZER   __use_AST_MUTEX_DEFINE_STATIC_rather_than_AST_MUTEX_INITIALIZER__

Definition at line 637 of file lock.h.

◆ AST_MUTEX_KIND

#define AST_MUTEX_KIND   PTHREAD_MUTEX_RECURSIVE_NP

Definition at line 77 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 189 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 191 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 190 of file lock.h.

◆ AST_PTHREADT_NULL

#define AST_PTHREADT_NULL   (pthread_t) -1

Definition at line 66 of file lock.h.

◆ AST_PTHREADT_STOP

#define AST_PTHREADT_STOP   (pthread_t) -2

Definition at line 67 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 543 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 544 of file lock.h.

◆ ast_rwlock_destroy

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

Definition at line 233 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 224 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 231 of file lock.h.

◆ AST_RWLOCK_INIT_VALUE

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

Definition at line 98 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 99 of file lock.h.

◆ ast_rwlock_rdlock

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

Definition at line 235 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 239 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 240 of file lock.h.

◆ ast_rwlock_tryrdlock

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

Definition at line 237 of file lock.h.

◆ ast_rwlock_trywrlock

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

Definition at line 238 of file lock.h.

◆ ast_rwlock_unlock

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

Definition at line 234 of file lock.h.

◆ ast_rwlock_wrlock

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

Definition at line 236 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:2923

Definition at line 474 of file lock.h.

◆ DEADLOCK_AVOIDANCE

#define DEADLOCK_AVOIDANCE (   lock)

Definition at line 479 of file lock.h.

◆ DLA_LOCK

#define DLA_LOCK (   lock)    ast_mutex_lock(lock)

Definition at line 492 of file lock.h.

◆ DLA_UNLOCK

#define DLA_UNLOCK (   lock)    ast_mutex_unlock(lock)

Definition at line 490 of file lock.h.

◆ gethostbyname

#define gethostbyname   __gethostbyname__is__not__reentrant__use__ast_gethostbyname__instead__

Definition at line 639 of file lock.h.

◆ pthread_cond_broadcast

#define pthread_cond_broadcast   use_ast_cond_broadcast_instead_of_pthread_cond_broadcast

Definition at line 633 of file lock.h.

◆ pthread_cond_destroy

#define pthread_cond_destroy   use_ast_cond_destroy_instead_of_pthread_cond_destroy

Definition at line 631 of file lock.h.

◆ pthread_cond_init

#define pthread_cond_init   use_ast_cond_init_instead_of_pthread_cond_init

Definition at line 630 of file lock.h.

◆ pthread_cond_signal

#define pthread_cond_signal   use_ast_cond_signal_instead_of_pthread_cond_signal

Definition at line 632 of file lock.h.

◆ pthread_cond_t

#define pthread_cond_t   use_ast_cond_t_instead_of_pthread_cond_t

Definition at line 623 of file lock.h.

◆ pthread_cond_timedwait

#define pthread_cond_timedwait   use_ast_cond_timedwait_instead_of_pthread_cond_timedwait

Definition at line 635 of file lock.h.

◆ pthread_cond_wait

#define pthread_cond_wait   use_ast_cond_wait_instead_of_pthread_cond_wait

Definition at line 634 of file lock.h.

◆ pthread_create

#define pthread_create   __use_ast_pthread_create_instead__

Definition at line 642 of file lock.h.

◆ pthread_mutex_destroy

#define pthread_mutex_destroy   use_ast_mutex_destroy_instead_of_pthread_mutex_destroy

Definition at line 629 of file lock.h.

◆ pthread_mutex_init

#define pthread_mutex_init   use_ast_mutex_init_instead_of_pthread_mutex_init

Definition at line 628 of file lock.h.

◆ PTHREAD_MUTEX_INIT_VALUE

#define PTHREAD_MUTEX_INIT_VALUE   PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP

Definition at line 76 of file lock.h.

◆ pthread_mutex_lock

#define pthread_mutex_lock   use_ast_mutex_lock_instead_of_pthread_mutex_lock

Definition at line 625 of file lock.h.

◆ pthread_mutex_t

#define pthread_mutex_t   use_ast_mutex_t_instead_of_pthread_mutex_t

Definition at line 622 of file lock.h.

◆ pthread_mutex_trylock

#define pthread_mutex_trylock   use_ast_mutex_trylock_instead_of_pthread_mutex_trylock

Definition at line 627 of file lock.h.

◆ pthread_mutex_unlock

#define pthread_mutex_unlock   use_ast_mutex_unlock_instead_of_pthread_mutex_unlock

Definition at line 626 of file lock.h.

◆ ROFFSET

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

Definition at line 242 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 604 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 609 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 614 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 619 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:331
const char * ast_channel_name(const struct ast_channel *chan)
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Definition: lock.h:583
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 583 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 589 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 594 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 599 of file lock.h.

Typedef Documentation

◆ ast_cond_t

Definition at line 178 of file lock.h.

◆ ast_mutex_t

typedef struct ast_mutex_info ast_mutex_t

Definition at line 174 of file lock.h.

◆ ast_rwlock_t

typedef struct ast_rwlock_info ast_rwlock_t

Definition at line 176 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 531 of file lock.c.

533{
535}
ast_cond_t cond
Definition: app_sla.c:330
#define pthread_cond_broadcast
Definition: lock.h:633

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 537 of file lock.c.

539{
541}
#define pthread_cond_destroy
Definition: lock.h:631

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 519 of file lock.c.

521{
522 return pthread_cond_init(cond, cond_attr);
523}
#define pthread_cond_init
Definition: lock.h:630

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 525 of file lock.c.

527{
529}
#define pthread_cond_signal
Definition: lock.h:632

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 631 of file lock.c.

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

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 566 of file lock.c.

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

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:627
#define pthread_mutex_unlock
Definition: lock.h:626
#define pthread_mutex_destroy
Definition: lock.h:629

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:77
#define pthread_mutex_init
Definition: lock.h:628

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 <synopsis>Raised when a probable deadlock has started.
326 Delivery of this event is attempted but not guaranteed,
327 and could fail for example if the manager itself is deadlocked.
328 </synopsis>
329 <syntax>
330 <parameter name="Mutex">
331 <para>The mutex involved in the deadlock.</para>
332 </parameter>
333 </syntax>
334 </managerEventInstance>
335 </managerEvent>
336 ***/
337 manager_event(EVENT_FLAG_SYSTEM, "DeadlockStart",
338 "Mutex: %s\r\n",
339 mutex_name);
340 }
341 }
342 usleep(200);
343 }
344 } while (res == EBUSY);
345 }
346#else /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
347#ifdef HAVE_MTX_PROFILE
348 ast_mark(mtx_prof, 1);
349 res = pthread_mutex_trylock(&t->mutex);
350 ast_mark(mtx_prof, 0);
351 if (res)
352#endif
353 res = pthread_mutex_lock(&t->mutex);
354#endif /* !DETECT_DEADLOCKS || !DEBUG_THREADS */
355
356#ifdef DEBUG_THREADS
357 if (lt && !res) {
358 ast_reentrancy_lock(lt);
359 if (lt->reentrancy < AST_MAX_REENTRANCY) {
360 lt->file[lt->reentrancy] = filename;
361 lt->lineno[lt->reentrancy] = lineno;
362 lt->func[lt->reentrancy] = func;
363 lt->thread_id[lt->reentrancy] = pthread_self();
364 lt->reentrancy++;
365 } else {
366 log_mutex_error(canlog, "%s line %d (%s): '%s' really deep reentrancy!\n",
367 filename, lineno, func, mutex_name);
368 }
369 ast_reentrancy_unlock(lt);
370 ast_mark_lock_acquired(t);
371 } else if (lt) {
372#ifdef HAVE_BKTR
373 if (lt->reentrancy) {
374 ast_reentrancy_lock(lt);
375 bt = &lt->backtrace[lt->reentrancy-1];
376 ast_reentrancy_unlock(lt);
377 } else {
378 bt = NULL;
379 }
380#endif
381 ast_remove_lock_info(t, bt);
382 }
383 if (res) {
384 log_mutex_error(canlog, "%s line %d (%s): Error obtaining mutex: %s\n",
385 filename, lineno, func, strerror(res));
386 DO_THREAD_CRASH;
387 }
388#endif /* DEBUG_THREADS */
389
390 return res;
391}
int64_t ast_mark(int, int start1_stop0)
Definition: astman.c:103
#define ast_bt_get_addresses(bt)
Definition: backtrace.h:38
static int tmp()
Definition: bt_open.c:389
@ AST_MUTEX
Definition: check_expr.c:36
#define AST_MAX_REENTRANCY
Definition: lock.h:101
#define pthread_mutex_lock
Definition: lock.h:625
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:253
#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, ast_lock_track::thread_id, and tmp().

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 393 of file lock.c.

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

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 448 of file lock.c.

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

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 730 of file lock.c.

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

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 696 of file lock.c.

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

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 848 of file lock.c.

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

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 1055 of file lock.c.

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

◆ __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 1137 of file lock.c.

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

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, ast_lock_track::thread_id, and tmp().

◆ __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 1219 of file lock.c.

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

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, ast_lock_track::thread_id, and tmp().

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 1269 of file lock.c.

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

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, ast_lock_track::thread_id, and tmp().

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 777 of file lock.c.

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

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 952 of file lock.c.

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

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, ast_lock_track::thread_id, and tmp().

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 767 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 757 of file lock.h.

765{

Referenced by __ao2_link(), __ao2_lock(), __ao2_ref(), __ao2_trylock(), __ao2_unlock(), __ast_channel_alloc_ap(), __ast_channel_internal_alloc(), __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().