Asterisk - The Open Source Telephony Project  GIT-master-4a4f1a5
Data Structures | Macros | Functions | Variables
astobj2.c File Reference

Functions implementing astobj2 objects. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/astobj2.h"
#include "astobj2_private.h"
#include "astobj2_container_private.h"
#include "asterisk/cli.h"
#include "asterisk/paths.h"

Go to the source code of this file.

Data Structures

struct  __priv_data
 
struct  ao2_lock_priv
 
struct  ao2_lockobj_priv
 
struct  ao2_rwlock_priv
 
struct  ao2_weakproxy_notification
 
struct  astobj2
 
struct  astobj2_lock
 
struct  astobj2_lockobj
 
struct  astobj2_rwlock
 

Macros

#define __INTERNAL_OBJ_CHECK(user_data, file, line, func)
 convert from a pointer _p to a user-defined object More...
 
#define AO2_MAGIC   0xa70b123
 
#define AO2_WEAK   0xa70b122
 
#define ast_log   ast_log_safe
 
#define DEBUG_THREADS_LOOSE_ABI
 
#define EXCESSIVE_REF_COUNT   100000
 
#define EXTERNAL_OBJ(_p)   ((_p) == NULL ? NULL : (_p)->user_data)
 convert from a pointer _p to an astobj2 object More...
 
#define INTERNAL_OBJ(user_data)    (struct astobj2 *) ((char *) user_data - sizeof(struct astobj2))
 
#define INTERNAL_OBJ_CHECK(user_data)    __INTERNAL_OBJ_CHECK(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
 
#define INTERNAL_OBJ_LOCKOBJ(user_data)    ((struct astobj2_lockobj *) (((char *) (user_data)) - sizeof(struct astobj2_lockobj)))
 
#define INTERNAL_OBJ_MUTEX(user_data)    ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
 
#define INTERNAL_OBJ_RWLOCK(user_data)    ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
 
#define IS_AO2_MAGIC_BAD(p)   (AO2_MAGIC != (p->priv_data.magic | 1))
 

Functions

enum ao2_lock_req __adjust_lock (void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
 
void * __ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, const char *file, int line, const char *func)
 
void * __ao2_alloc_with_lockobj (size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj, const char *tag, const char *file, int line, const char *func)
 
void __ao2_cleanup (void *obj)
 
void __ao2_cleanup_debug (void *obj, const char *tag, const char *file, int line, const char *function)
 
void * __ao2_get_weakproxy (void *obj, const char *tag, const char *file, int line, const char *func)
 Get the weakproxy attached to obj. More...
 
int __ao2_lock (void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
 Lock an object. More...
 
int __ao2_ref (void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
 
int __ao2_trylock (void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
 Try locking– (don't block if fail) More...
 
int __ao2_unlock (void *user_data, const char *file, const char *func, int line, const char *var)
 Unlock an object. More...
 
void * __ao2_weakproxy_alloc (size_t data_size, ao2_destructor_fn destructor_fn, const char *tag, const char *file, int line, const char *func)
 Allocate an ao2_weakproxy object. More...
 
void * __ao2_weakproxy_get_object (void *weakproxy, int flags, const char *tag, const char *file, int line, const char *func)
 Get the object associated with weakproxy. More...
 
int __ao2_weakproxy_ref_object (void *weakproxy, int delta, int flags, const char *tag, const char *file, int line, const char *func)
 Run ao2_t_ref on the object associated with weakproxy. More...
 
int __ao2_weakproxy_set_object (void *weakproxy, void *obj, int flags, const char *tag, const char *file, int line, const char *func)
 Associate weakproxy with obj. More...
 
void * ao2_object_get_lockaddr (void *user_data)
 Return the mutex lock address of an object. More...
 
unsigned int ao2_options_get (void *obj)
 Retrieve the ao2 options used to create the object. More...
 
int ao2_weakproxy_subscribe (void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags)
 Request notification when weakproxy points to NULL. More...
 
int ao2_weakproxy_unsubscribe (void *weakproxy, ao2_weakproxy_notification_cb destroyed_cb, void *data, int flags)
 Remove notification of real object destruction. More...
 
static void astobj2_cleanup (void)
 
int astobj2_init (void)
 
static void * internal_ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, void *lockobj, const char *tag, const char *file, int line, const char *func)
 
int internal_is_ao2_object (void *user_data)
 
void log_bad_ao2 (void *user_data, const char *file, int line, const char *func)
 

Variables

static FILE * ref_log
 

Detailed Description

Functions implementing astobj2 objects.

Author
Richard Mudgett rmudg.nosp@m.ett@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file astobj2.c.

Macro Definition Documentation

◆ __INTERNAL_OBJ_CHECK

#define __INTERNAL_OBJ_CHECK (   user_data,
  file,
  line,
  func 
)

convert from a pointer _p to a user-defined object

Returns
the pointer to the astobj2 structure

Definition at line 171 of file astobj2.c.

◆ AO2_MAGIC

#define AO2_MAGIC   0xa70b123

Definition at line 96 of file astobj2.c.

◆ AO2_WEAK

#define AO2_WEAK   0xa70b122

Definition at line 97 of file astobj2.c.

◆ ast_log

#define ast_log   ast_log_safe
Examples
app_skel.c.

Definition at line 42 of file astobj2.c.

◆ DEBUG_THREADS_LOOSE_ABI

#define DEBUG_THREADS_LOOSE_ABI

Definition at line 30 of file astobj2.c.

◆ EXCESSIVE_REF_COUNT

#define EXCESSIVE_REF_COUNT   100000

◆ EXTERNAL_OBJ

#define EXTERNAL_OBJ (   _p)    ((_p) == NULL ? NULL : (_p)->user_data)

convert from a pointer _p to an astobj2 object

Returns
the pointer to the user-defined portion.

Definition at line 191 of file astobj2.c.

◆ INTERNAL_OBJ

#define INTERNAL_OBJ (   user_data)     (struct astobj2 *) ((char *) user_data - sizeof(struct astobj2))

Definition at line 163 of file astobj2.c.

◆ INTERNAL_OBJ_CHECK

#define INTERNAL_OBJ_CHECK (   user_data)     __INTERNAL_OBJ_CHECK(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__)

Definition at line 183 of file astobj2.c.

◆ INTERNAL_OBJ_LOCKOBJ

#define INTERNAL_OBJ_LOCKOBJ (   user_data)     ((struct astobj2_lockobj *) (((char *) (user_data)) - sizeof(struct astobj2_lockobj)))

Definition at line 160 of file astobj2.c.

◆ INTERNAL_OBJ_MUTEX

#define INTERNAL_OBJ_MUTEX (   user_data)     ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))

Definition at line 154 of file astobj2.c.

◆ INTERNAL_OBJ_RWLOCK

#define INTERNAL_OBJ_RWLOCK (   user_data)     ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))

Definition at line 157 of file astobj2.c.

◆ IS_AO2_MAGIC_BAD

#define IS_AO2_MAGIC_BAD (   p)    (AO2_MAGIC != (p->priv_data.magic | 1))

Definition at line 98 of file astobj2.c.

Function Documentation

◆ __adjust_lock()

enum ao2_lock_req __adjust_lock ( void *  user_data,
enum ao2_lock_req  lock_how,
int  keep_stronger 
)

Definition at line 342 of file astobj2.c.

426 {
427  struct astobj2 *obj = INTERNAL_OBJ(user_data);
428  struct astobj2_rwlock *obj_rwlock;
429  struct astobj2_lockobj *obj_lockobj;
430  enum ao2_lock_req orig_lock;
431 
432  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
434  obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
435  if (obj_rwlock->rwlock.num_lockers < 0) {
436  orig_lock = AO2_LOCK_REQ_WRLOCK;
437  } else {
438  orig_lock = AO2_LOCK_REQ_RDLOCK;
439  }
440  switch (lock_how) {
441  case AO2_LOCK_REQ_MUTEX:
442  lock_how = AO2_LOCK_REQ_WRLOCK;
443  /* Fall through */
444  case AO2_LOCK_REQ_WRLOCK:
445  if (lock_how != orig_lock) {
446  /* Switch from read lock to write lock. */
449  }
450  break;
451  case AO2_LOCK_REQ_RDLOCK:
452  if (!keep_stronger && lock_how != orig_lock) {
453  /* Switch from write lock to read lock. */
456  }
457  break;
458  }
459  break;
461  obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
462  orig_lock = __adjust_lock(obj_lockobj->lockobj.lock, lock_how, keep_stronger);
463  break;
464  default:
465  ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
466  /* Fall through */
469  orig_lock = AO2_LOCK_REQ_MUTEX;
470  break;
471  }
472 
473  return orig_lock;
474 }
enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
Definition: astobj2.c:425
#define INTERNAL_OBJ_LOCKOBJ(user_data)
Definition: astobj2.c:160
#define ast_log
Definition: astobj2.c:42
#define INTERNAL_OBJ_RWLOCK(user_data)
Definition: astobj2.c:157
#define INTERNAL_OBJ(user_data)
Definition: astobj2.c:163
#define ao2_rdlock(a)
Definition: astobj2.h:719
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:369
@ AO2_ALLOC_OPT_LOCK_OBJ
Definition: astobj2.h:378
@ AO2_ALLOC_OPT_LOCK_RWLOCK
Definition: astobj2.h:367
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:365
@ AO2_ALLOC_OPT_LOCK_MASK
Definition: astobj2.h:371
#define ao2_wrlock(a)
Definition: astobj2.h:720
ao2_lock_req
Which lock to request.
Definition: astobj2.h:701
@ AO2_LOCK_REQ_MUTEX
Definition: astobj2.h:703
@ AO2_LOCK_REQ_WRLOCK
Definition: astobj2.h:707
@ AO2_LOCK_REQ_RDLOCK
Definition: astobj2.h:705
#define ao2_unlock(a)
Definition: astobj2.h:730
#define LOG_ERROR
Definition: logger.h:286
uint32_t options
The ao2 object option flags.
Definition: astobj2.c:70
struct ao2_lockobj_priv lockobj
Definition: astobj2.c:145
void * user_data[0]
Definition: astobj2.c:147
struct ao2_rwlock_priv rwlock
Definition: astobj2.c:134
struct __priv_data priv_data
Definition: astobj2.c:105
void * user_data[0]
Definition: astobj2.c:106

References __ao2_trylock(), __ast_pthread_mutex_trylock(), __ast_rwlock_tryrdlock(), __ast_rwlock_trywrlock(), __INTERNAL_OBJ_CHECK, __LOG_ERROR, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_OBJ, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ast_atomic_fetchadd_int(), ast_log, make_ari_stubs::file, INTERNAL_OBJ_LOCKOBJ, INTERNAL_OBJ_MUTEX, INTERNAL_OBJ_RWLOCK, ao2_lock_priv::lock, ao2_rwlock_priv::lock, ao2_lockobj_priv::lock, astobj2_lockobj::lockobj, __priv_data::lockused, astobj2_lock::mutex, NULL, ao2_rwlock_priv::num_lockers, __priv_data::options, astobj2::priv_data, ref_log, astobj2_rwlock::rwlock, astobj2::user_data, astobj2_lockobj::user_data, and var.

Referenced by __ao2_iterator_next(), __ao2_link(), __ao2_weakproxy_find(), ao2_iterator_restart(), hash_ao2_node_destructor(), internal_ao2_traverse(), and rb_ao2_node_destructor().

◆ __ao2_alloc()

void* __ao2_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
unsigned int  options,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Definition at line 768 of file astobj2.c.

770 {
771  return internal_ao2_alloc(data_size, destructor_fn, options, NULL, tag, file, line, func);
772 }
static void * internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, void *lockobj, const char *tag, const char *file, int line, const char *func)
Definition: astobj2.c:684
#define NULL
Definition: resample.c:96
static struct test_options options

References make_ari_stubs::file, internal_ao2_alloc(), NULL, and options.

Referenced by __ao2_container_alloc_hash(), __ao2_weakproxy_alloc(), __ast_channel_internal_alloc(), __ast_format_cap_alloc(), __ast_named_lock_get(), __ast_sorcery_open(), __sip_alloc(), _moh_class_malloc(), and state_alloc().

◆ __ao2_alloc_with_lockobj()

void* __ao2_alloc_with_lockobj ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
void *  lockobj,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Definition at line 774 of file astobj2.c.

776 {
777  return internal_ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_OBJ, lockobj,
778  tag, file, line, func);
779 }

References AO2_ALLOC_OPT_LOCK_OBJ, make_ari_stubs::file, and internal_ao2_alloc().

◆ __ao2_cleanup()

void __ao2_cleanup ( void *  obj)

gcc attribute(cleanup()) functions

Note
they must be able to handle NULL parameters because most of the allocation/find functions can fail and we don't want to try to tear down a NULL

Definition at line 677 of file astobj2.c.

678 {
679  if (obj) {
680  ao2_ref(obj, -1);
681  }
682 }
#define ao2_ref(o, delta)
Definition: astobj2.h:464

References ao2_ref.

Referenced by agent_request_exec(), ast_ari_bridges_set_video_source(), bridge_agent_hold_push(), bridge_builtin_set_limits(), bridge_stasis_queue_join_action(), dial_bridge_after_cb(), internal_bridge_after_cb(), native_rtp_bridge_framehook_attach(), and parking_set_duration().

◆ __ao2_cleanup_debug()

void __ao2_cleanup_debug ( void *  obj,
const char *  tag,
const char *  file,
int  line,
const char *  function 
)

Definition at line 670 of file astobj2.c.

671 {
672  if (obj) {
673  __ao2_ref(obj, -1, tag, file, line, function);
674  }
675 }
int __ao2_ref(void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
Definition: astobj2.c:498

References __ao2_ref(), and make_ari_stubs::file.

◆ __ao2_get_weakproxy()

void* __ao2_get_weakproxy ( void *  obj,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Get the weakproxy attached to obj.

Since
14.0.0
Parameters
objThe object to retrieve a weakproxy from
Returns
The weakproxy object

Definition at line 917 of file astobj2.c.

918 {
919  struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func);
920 
921  if (!obj_internal || obj_internal->priv_data.magic != AO2_MAGIC) {
922  /* This method is meant to be run on normal ao2 objects! */
923  return NULL;
924  }
925 
926  if (!obj_internal->priv_data.weakptr) {
927  return NULL;
928  }
929 
930  __ao2_ref(obj_internal->priv_data.weakptr, +1, tag, file, line, func);
931  return obj_internal->priv_data.weakptr;
932 }
#define __INTERNAL_OBJ_CHECK(user_data, file, line, func)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:171
#define AO2_MAGIC
Definition: astobj2.c:96
uint32_t magic
Definition: astobj2.c:93
void * weakptr
Definition: astobj2.c:57

References __ao2_ref(), __INTERNAL_OBJ_CHECK, AO2_MAGIC, make_ari_stubs::file, __priv_data::magic, NULL, astobj2::priv_data, and __priv_data::weakptr.

◆ __ao2_lock()

int __ao2_lock ( void *  a,
enum ao2_lock_req  lock_how,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Lock an object.

Parameters
aA pointer to the object we want to lock.
lock_how,file,func,line,var
Returns
0 on success, other values on error.

Definition at line 222 of file astobj2.c.

223 {
224  struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
225  struct astobj2_lock *obj_mutex;
226  struct astobj2_rwlock *obj_rwlock;
227  struct astobj2_lockobj *obj_lockobj;
228  int res = 0;
229 
230  if (obj == NULL) {
231  return -1;
232  }
233 
234  if (ref_log) {
235  obj->priv_data.lockused = 1;
236  }
237 
238  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
240  obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
241  res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
242 #ifdef AO2_DEBUG
243  if (!res) {
244  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
245  }
246 #endif
247  break;
249  obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
250  switch (lock_how) {
251  case AO2_LOCK_REQ_MUTEX:
252  case AO2_LOCK_REQ_WRLOCK:
253  res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
254  if (!res) {
255  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
256 #ifdef AO2_DEBUG
257  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
258 #endif
259  }
260  break;
261  case AO2_LOCK_REQ_RDLOCK:
262  res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
263  if (!res) {
264  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
265 #ifdef AO2_DEBUG
266  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
267 #endif
268  }
269  break;
270  }
271  break;
273  /* The ao2 object has no lock. */
274  break;
276  obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
277  res = __ao2_lock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
278  break;
279  default:
280  ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
281  user_data);
282  return -1;
283  }
284 
285  return res;
286 }
#define var
Definition: ast_expr2f.c:614
static FILE * ref_log
Definition: astobj2.c:44
#define INTERNAL_OBJ_MUTEX(user_data)
Definition: astobj2.c:154
int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
Lock an object.
Definition: astobj2.c:222
int __ast_rwlock_wrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
Definition: lock.c:917
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:755
int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
Definition: lock.c:253
int __ast_rwlock_rdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
Definition: lock.c:819
#define __LOG_ERROR
Definition: logger.h:285
uint32_t lockused
Set to 1 when the lock is used if refdebug is enabled.
Definition: astobj2.c:77
ast_mutex_t lock
Definition: astobj2.c:116
ast_rwlock_t lock
Definition: astobj2.c:127
struct ao2_lock_priv mutex
Definition: astobj2.c:121

References __ao2_lock(), __ast_pthread_mutex_lock(), __ast_rwlock_rdlock(), __ast_rwlock_wrlock(), __INTERNAL_OBJ_CHECK, __LOG_ERROR, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_OBJ, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ast_atomic_fetchadd_int(), ast_log, make_ari_stubs::file, INTERNAL_OBJ_LOCKOBJ, INTERNAL_OBJ_MUTEX, INTERNAL_OBJ_RWLOCK, ao2_lock_priv::lock, ao2_rwlock_priv::lock, ao2_lockobj_priv::lock, astobj2_lockobj::lockobj, __priv_data::lockused, astobj2_lock::mutex, NULL, ao2_rwlock_priv::num_lockers, __priv_data::options, astobj2::priv_data, ref_log, astobj2_rwlock::rwlock, astobj2::user_data, astobj2_lockobj::user_data, and var.

Referenced by __ao2_lock(), _agent_lock(), _ast_bridge_channel_lock(), and _ast_bridge_lock().

◆ __ao2_ref()

int __ao2_ref ( void *  user_data,
int  delta,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Definition at line 498 of file astobj2.c.

500 {
501  struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
502  struct astobj2_lock *obj_mutex;
503  struct astobj2_rwlock *obj_rwlock;
504  struct astobj2_lockobj *obj_lockobj;
505  int32_t current_value;
506  int32_t ret;
507  uint32_t privdataoptions;
508  struct ao2_weakproxy *weakproxy = NULL;
509  const char *lock_state;
510 
511  if (obj == NULL) {
512  if (ref_log && user_data) {
513  fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
514  user_data, delta, ast_get_tid(), file, line, func, tag ?: "");
515  fflush(ref_log);
516  }
517  return -1;
518  }
519 
520  /* if delta is 0, just return the refcount */
521  if (delta == 0) {
522  return obj->priv_data.ref_counter;
523  }
524 
525  if (delta < 0 && obj->priv_data.magic == AO2_MAGIC && (weakproxy = obj->priv_data.weakptr)) {
526  ao2_lock(weakproxy);
527  }
528 
529  /* we modify with an atomic operation the reference counter */
530  ret = ast_atomic_fetch_add(&obj->priv_data.ref_counter, delta, __ATOMIC_RELAXED);
531  current_value = ret + delta;
532 
533 #ifdef AO2_DEBUG
534  ast_atomic_fetchadd_int(&ao2.total_refs, delta);
535 #endif
536 
537  if (weakproxy) {
538  struct ao2_weakproxy cbs;
539 
540  if (current_value == 1) {
541  /* The only remaining reference is the one owned by the weak object */
542  struct astobj2 *internal_weakproxy;
543 
544  internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy);
545 
546  /* Unlink the obj from the weak proxy */
547  internal_weakproxy->priv_data.weakptr = NULL;
548  obj->priv_data.weakptr = NULL;
549 
550  /* transfer list to local copy so callbacks are run with weakproxy unlocked. */
551  cbs.destroyed_cb = weakproxy->destroyed_cb;
553 
554  /* weak is already unlinked from obj so this won't recurse */
555  ao2_ref(user_data, -1);
556  }
557 
558  ao2_unlock(weakproxy);
559 
560  if (current_value == 1) {
561  struct ao2_weakproxy_notification *destroyed_cb;
562 
563  /* Notify the subscribers that weakproxy now points to NULL. */
564  while ((destroyed_cb = AST_LIST_REMOVE_HEAD(&cbs.destroyed_cb, list))) {
565  destroyed_cb->cb(weakproxy, destroyed_cb->data);
566  ast_free(destroyed_cb);
567  }
568 
569  ao2_ref(weakproxy, -1);
570  }
571  }
572 
573  if (0 < current_value) {
574  /* The object still lives. */
575 #define EXCESSIVE_REF_COUNT 100000
576 
577  if (EXCESSIVE_REF_COUNT <= current_value && ret < EXCESSIVE_REF_COUNT) {
578  char excessive_ref_buf[100];
579 
580  /* We just reached or went over the excessive ref count trigger */
581  snprintf(excessive_ref_buf, sizeof(excessive_ref_buf),
582  "Excessive refcount %d reached on ao2 object %p",
583  (int)current_value, user_data);
584  ast_log(__LOG_ERROR, file, line, func, "%s\n", excessive_ref_buf);
585 
586  __ast_assert_failed(0, excessive_ref_buf, file, line, func);
587  }
588 
590  fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data,
591  (delta < 0 ? "" : "+"), delta, ast_get_tid(),
592  file, line, func, (int)ret, tag ?: "");
593  fflush(ref_log);
594  }
595  return ret;
596  }
597 
598  /* this case must never happen */
599  if (current_value < 0) {
600  ast_log(__LOG_ERROR, file, line, func,
601  "Invalid refcount %d on ao2 object %p\n", (int)current_value, user_data);
602  if (ref_log) {
603  /* Log to ref_log even if AO2_ALLOC_OPT_NO_REF_DEBUG */
604  fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
605  user_data, delta, ast_get_tid(), file, line, func, tag ?: "");
606  fflush(ref_log);
607  }
608  ast_assert(0);
609  /* stop here even if assert doesn't DO_CRASH */
610  return -1;
611  }
612 
613  /* last reference, destroy the object */
614  if (obj->priv_data.destructor_fn != NULL) {
615  obj->priv_data.destructor_fn(user_data);
616  }
617 
618 #ifdef AO2_DEBUG
619  ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
620  ast_atomic_fetchadd_int(&ao2.total_objects, -1);
621 #endif
622 
623  /* In case someone uses an object after it's been freed */
624  obj->priv_data.magic = 0;
625  /* Save the options locally so the ref_log print at the end doesn't access freed data */
626  privdataoptions = obj->priv_data.options;
627 
628  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
630  obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
631  lock_state = obj->priv_data.lockused ? "used" : "unused";
632  ast_mutex_destroy(&obj_mutex->mutex.lock);
633 
634  ast_free(obj_mutex);
635  break;
637  obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
638  lock_state = obj->priv_data.lockused ? "used" : "unused";
639  ast_rwlock_destroy(&obj_rwlock->rwlock.lock);
640 
641  ast_free(obj_rwlock);
642  break;
644  lock_state = "none";
645  ast_free(obj);
646  break;
648  obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
649  lock_state = obj->priv_data.lockused ? "used" : "unused";
650  ao2_t_ref(obj_lockobj->lockobj.lock, -1, "release lockobj");
651 
652  ast_free(obj_lockobj);
653  break;
654  default:
655  ast_log(__LOG_ERROR, file, line, func,
656  "Invalid lock option on ao2 object %p\n", user_data);
657  lock_state = "invalid";
658  break;
659  }
660 
661  if (ref_log && !(privdataoptions & AO2_ALLOC_OPT_NO_REF_DEBUG)) {
662  fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**lock-state:%s**,%s\n",
663  user_data, delta, ast_get_tid(), file, line, func, lock_state, tag ?: "");
664  fflush(ref_log);
665  }
666 
667  return ret;
668 }
#define ast_free(a)
Definition: astmm.h:182
#define EXCESSIVE_REF_COUNT
#define INTERNAL_OBJ_CHECK(user_data)
Definition: astobj2.c:183
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
@ AO2_ALLOC_OPT_NO_REF_DEBUG
Definition: astobj2.h:380
#define ao2_lock(a)
Definition: astobj2.h:718
int int32_t
Definition: db.h:60
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Definition: linkedlists.h:681
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define ast_rwlock_destroy(rwlock)
Definition: lock.h:231
#define ast_mutex_destroy(a)
Definition: lock.h:186
#define ast_atomic_fetch_add(ptr, val, memorder)
Support for atomic instructions.
Definition: lock.h:667
int32_t ref_counter
Definition: astobj2.c:63
ao2_destructor_fn destructor_fn
Definition: astobj2.c:55
struct ao2_weakproxy_notification::@320 list
ao2_weakproxy_notification_cb cb
Definition: astobj2.c:110
This struct should be opaque, but it's size is needed.
Definition: astobj2.h:530
struct ao2_weakproxy::@211 destroyed_cb
#define ast_assert(a)
Definition: utils.h:710
int ast_get_tid(void)
Get current thread ID.
Definition: main/utils.c:2504
void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
Definition: main/utils.c:2564

References __ast_assert_failed(), __INTERNAL_OBJ_CHECK, __LOG_ERROR, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_OBJ, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_ALLOC_OPT_NO_REF_DEBUG, ao2_lock, AO2_MAGIC, ao2_ref, ao2_t_ref, ao2_unlock, ast_assert, ast_atomic_fetch_add, ast_atomic_fetchadd_int(), ast_free, ast_get_tid(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_REMOVE_HEAD, ast_log, ast_mutex_destroy, ast_rwlock_destroy, ao2_weakproxy_notification::cb, ao2_weakproxy_notification::data, ao2_weakproxy::destroyed_cb, __priv_data::destructor_fn, EXCESSIVE_REF_COUNT, make_ari_stubs::file, INTERNAL_OBJ_CHECK, INTERNAL_OBJ_LOCKOBJ, INTERNAL_OBJ_MUTEX, INTERNAL_OBJ_RWLOCK, ao2_weakproxy_notification::list, ao2_lock_priv::lock, ao2_rwlock_priv::lock, ao2_lockobj_priv::lock, astobj2_lockobj::lockobj, __priv_data::lockused, __priv_data::magic, astobj2_lock::mutex, NULL, __priv_data::options, astobj2::priv_data, __priv_data::ref_counter, ref_log, astobj2_rwlock::rwlock, astobj2::user_data, and __priv_data::weakptr.

Referenced by __ao2_cleanup_debug(), __ao2_container_clone(), __ao2_get_weakproxy(), __ao2_global_obj_ref(), __ao2_global_obj_replace(), __ao2_global_obj_replace_unref(), __ao2_iterator_next(), __ao2_weakproxy_get_object(), __ao2_weakproxy_ref_object(), __ao2_weakproxy_set_object(), __ast_format_cap_append(), __ast_module_ref(), __ast_module_unref(), __container_unlink_node_debug(), __find_call(), hash_ao2_insert_node(), internal_ao2_traverse(), and rb_ao2_new_node().

◆ __ao2_trylock()

int __ao2_trylock ( void *  a,
enum ao2_lock_req  lock_how,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Try locking– (don't block if fail)

Parameters
aA pointer to the object we want to lock.
lock_how,file,func,line,var
Returns
0 on success, other values on error.

Definition at line 342 of file astobj2.c.

343 {
344  struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
345  struct astobj2_lock *obj_mutex;
346  struct astobj2_rwlock *obj_rwlock;
347  struct astobj2_lockobj *obj_lockobj;
348  int res = 0;
349 
350  if (obj == NULL) {
351  return -1;
352  }
353 
354  if (ref_log) {
355  obj->priv_data.lockused = 1;
356  }
357 
358  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
360  obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
361  res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
362 #ifdef AO2_DEBUG
363  if (!res) {
364  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
365  }
366 #endif
367  break;
369  obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
370  switch (lock_how) {
371  case AO2_LOCK_REQ_MUTEX:
372  case AO2_LOCK_REQ_WRLOCK:
373  res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
374  if (!res) {
375  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
376 #ifdef AO2_DEBUG
377  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
378 #endif
379  }
380  break;
381  case AO2_LOCK_REQ_RDLOCK:
382  res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
383  if (!res) {
384  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
385 #ifdef AO2_DEBUG
386  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
387 #endif
388  }
389  break;
390  }
391  break;
393  /* The ao2 object has no lock. */
394  return 0;
396  obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
397  res = __ao2_trylock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
398  break;
399  default:
400  ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
401  user_data);
402  return -1;
403  }
404 
405  return res;
406 }
int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
Try locking– (don't block if fail)
Definition: astobj2.c:342
int __ast_rwlock_trywrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
Definition: lock.c:1228
int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
Definition: lock.c:366
int __ast_rwlock_tryrdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
Definition: lock.c:1178

Referenced by __adjust_lock(), _ast_bridge_channel_trylock(), and _ast_bridge_trylock().

◆ __ao2_unlock()

int __ao2_unlock ( void *  a,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Unlock an object.

Parameters
aA pointer to the object we want unlock.
file,func,line,var
Returns
0 on success, other values on error.

Definition at line 288 of file astobj2.c.

289 {
290  struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
291  struct astobj2_lock *obj_mutex;
292  struct astobj2_rwlock *obj_rwlock;
293  struct astobj2_lockobj *obj_lockobj;
294  int res = 0;
295  int current_value;
296 
297  if (obj == NULL) {
298  return -1;
299  }
300 
301  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
303  obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
304  res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
305 #ifdef AO2_DEBUG
306  if (!res) {
307  ast_atomic_fetchadd_int(&ao2.total_locked, -1);
308  }
309 #endif
310  break;
312  obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
313 
314  current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
315  if (current_value < 0) {
316  /* It was a WRLOCK that we are unlocking. Fix the count. */
317  ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
318  }
319  res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
320 #ifdef AO2_DEBUG
321  if (!res) {
322  ast_atomic_fetchadd_int(&ao2.total_locked, -1);
323  }
324 #endif
325  break;
327  /* The ao2 object has no lock. */
328  break;
330  obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
331  res = __ao2_unlock(obj_lockobj->lockobj.lock, file, func, line, var);
332  break;
333  default:
334  ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
335  user_data);
336  res = -1;
337  break;
338  }
339  return res;
340 }
int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
Unlock an object.
Definition: astobj2.c:288
int __ast_rwlock_unlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
Definition: lock.c:748
int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
Definition: lock.c:421

References __ao2_unlock(), __ast_pthread_mutex_unlock(), __ast_rwlock_unlock(), __INTERNAL_OBJ_CHECK, __LOG_ERROR, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_OBJ, AO2_ALLOC_OPT_LOCK_RWLOCK, ast_atomic_fetchadd_int(), ast_log, make_ari_stubs::file, INTERNAL_OBJ_LOCKOBJ, INTERNAL_OBJ_MUTEX, INTERNAL_OBJ_RWLOCK, ao2_lock_priv::lock, ao2_rwlock_priv::lock, ao2_lockobj_priv::lock, astobj2_lockobj::lockobj, astobj2_lock::mutex, NULL, ao2_rwlock_priv::num_lockers, __priv_data::options, astobj2::priv_data, astobj2_rwlock::rwlock, astobj2::user_data, astobj2_lockobj::user_data, and var.

Referenced by __ao2_unlock(), _agent_unlock(), _ast_bridge_channel_unlock(), and _ast_bridge_unlock().

◆ __ao2_weakproxy_alloc()

void* __ao2_weakproxy_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Allocate an ao2_weakproxy object.

Since
14.0.0
Parameters
data_sizeThe sizeof() of the user-defined structure.
destructor_fnThe destructor function (can be NULL)
Note
"struct ao2_weakproxy" must be the first field of any object. This can be done by using AO2_WEAKPROXY to declare your structure.

Definition at line 793 of file astobj2.c.

795 {
796  struct ao2_weakproxy *weakproxy;
797 
798  if (data_size < sizeof(*weakproxy)) {
799  ast_assert(0);
800  ast_log(LOG_ERROR, "Requested data_size smaller than minimum.\n");
801  return NULL;
802  }
803 
804  weakproxy = __ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_MUTEX,
805  tag, file, line, func);
806 
807  if (weakproxy) {
808  struct astobj2 *weakproxy_internal;
809 
810  /* Just created weakproxy, no need to check if it's valid. */
811  weakproxy_internal = INTERNAL_OBJ(weakproxy);
812  weakproxy_internal->priv_data.magic = AO2_WEAK;
813  }
814 
815  return weakproxy;
816 }
#define AO2_WEAK
Definition: astobj2.c:97
void * __ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, const char *file, int line, const char *func)
Definition: astobj2.c:768

References __ao2_alloc(), AO2_ALLOC_OPT_LOCK_MUTEX, AO2_WEAK, ast_assert, ast_log, make_ari_stubs::file, INTERNAL_OBJ, LOG_ERROR, __priv_data::magic, NULL, and astobj2::priv_data.

◆ __ao2_weakproxy_get_object()

void* __ao2_weakproxy_get_object ( void *  weakproxy,
int  flags,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Get the object associated with weakproxy.

Since
14.0.0
Parameters
weakproxyThe weakproxy to read from.
flagsOBJ_NOLOCK to avoid locking weakproxy.
Returns
A reference to the object previously set by ao2_weakproxy_set_object.
Return values
NULLEither no object was set or the previously set object has been freed.

Definition at line 889 of file astobj2.c.

891 {
892  struct astobj2 *internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
893  void *obj;
894 
895  if (!internal || internal->priv_data.magic != AO2_WEAK) {
896  /* This method is meant to be run on weakproxy objects! */
897  return NULL;
898  }
899 
900  /* We have a weak object, grab reference to object within lock */
901  if (!(flags & OBJ_NOLOCK)) {
902  ao2_lock(weakproxy);
903  }
904 
905  obj = internal->priv_data.weakptr;
906  if (obj) {
907  __ao2_ref(obj, +1, tag, file, line, func);
908  }
909 
910  if (!(flags & OBJ_NOLOCK)) {
911  ao2_unlock(weakproxy);
912  }
913 
914  return obj;
915 }
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067

References __ao2_ref(), __INTERNAL_OBJ_CHECK, ao2_lock, ao2_unlock, AO2_WEAK, make_ari_stubs::file, NULL, and OBJ_NOLOCK.

Referenced by __ao2_weakproxy_find().

◆ __ao2_weakproxy_ref_object()

int __ao2_weakproxy_ref_object ( void *  weakproxy,
int  delta,
int  flags,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Run ao2_t_ref on the object associated with weakproxy.

Since
14.0.0
Parameters
weakproxyThe weakproxy to read from.
deltaValue to add to the reference counter.
flagsOBJ_NOLOCK to avoid locking weakproxy.
Return values
-2weakproxy is not a valid ao2_weakproxy.
-1weakproxy has no associated object.
Returns
The value of the reference counter before the operation.

Definition at line 862 of file astobj2.c.

864 {
865  struct astobj2 *internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
866  int ret = -1;
867 
868  if (!internal || internal->priv_data.magic != AO2_WEAK) {
869  /* This method is meant to be run on weakproxy objects! */
870  return -2;
871  }
872 
873  /* We have a weak object, grab lock. */
874  if (!(flags & OBJ_NOLOCK)) {
875  ao2_lock(weakproxy);
876  }
877 
878  if (internal->priv_data.weakptr) {
879  ret = __ao2_ref(internal->priv_data.weakptr, delta, tag, file, line, func);
880  }
881 
882  if (!(flags & OBJ_NOLOCK)) {
883  ao2_unlock(weakproxy);
884  }
885 
886  return ret;
887 }

References __ao2_ref(), __INTERNAL_OBJ_CHECK, ao2_lock, ao2_unlock, AO2_WEAK, make_ari_stubs::file, and OBJ_NOLOCK.

◆ __ao2_weakproxy_set_object()

int __ao2_weakproxy_set_object ( void *  weakproxy,
void *  obj,
int  flags,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)

Associate weakproxy with obj.

Since
14.0.0
Parameters
weakproxyAn object created by ao2_weakproxy_alloc.
objAn ao2 object not created by ao2_weakproxy_alloc.
flagsOBJ_NOLOCK to avoid locking weakproxy.
Return values
0Success
-1Failure
Note
obj must be newly created, this procedure is not thread safe if any other code can reach obj before this procedure ends.
weakproxy may be previously existing, but must not currently have an object set.
The only way to unset an object is for it to be destroyed. Any call to this function while an object is already set will fail.

Definition at line 818 of file astobj2.c.

820 {
821  struct astobj2 *weakproxy_internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
822  struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func);
823  int ret = -1;
824 
825  if (!weakproxy_internal
826  || weakproxy_internal->priv_data.magic != AO2_WEAK) {
827  return -1;
828  }
829 
830  if (!obj_internal
831  || obj_internal->priv_data.weakptr
832  || obj_internal->priv_data.magic != AO2_MAGIC) {
833  return -1;
834  }
835 
836  if (!(flags & OBJ_NOLOCK)) {
837  ao2_lock(weakproxy);
838  }
839 
840  if (!weakproxy_internal->priv_data.weakptr) {
841  __ao2_ref(obj, +1, tag, file, line, func);
842  __ao2_ref(weakproxy, +1, tag, file, line, func);
843 
844  weakproxy_internal->priv_data.weakptr = obj;
845  obj_internal->priv_data.weakptr = weakproxy;
846 
847  ret = 0;
848  }
849 
850  if (!(flags & OBJ_NOLOCK)) {
851  ao2_unlock(weakproxy);
852  /* It is possible for obj to be accessed now. It's allowed
853  * for weakproxy to already be in a container. Another thread
854  * could have been waiting for a lock on weakproxy to retrieve
855  * the object.
856  */
857  }
858 
859  return ret;
860 }

References __ao2_ref(), __INTERNAL_OBJ_CHECK, ao2_lock, AO2_MAGIC, ao2_unlock, AO2_WEAK, make_ari_stubs::file, __priv_data::magic, OBJ_NOLOCK, astobj2::priv_data, and __priv_data::weakptr.

◆ ao2_object_get_lockaddr()

void* ao2_object_get_lockaddr ( void *  obj)

Return the mutex lock address of an object.

Parameters
[in]objA pointer to the object we want.
Returns
the address of the mutex lock, else NULL.

This function comes in handy mainly for debugging locking situations, where the locking trace code reports the lock address, this allows you to correlate against object address, to match objects to reported locks.

Warning
AO2 lock objects do not include tracking fields when DEBUG_THREADS is not enabled.
Since
1.6.1

Definition at line 476 of file astobj2.c.

477 {
478  struct astobj2 *obj;
479  struct astobj2_lock *obj_mutex;
480 
482 
483  if (obj == NULL) {
484  return NULL;
485  }
486 
487  switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
489  obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
490  return &obj_mutex->mutex.lock;
491  default:
492  break;
493  }
494 
495  return NULL;
496 }
void * user_data[0]
Definition: astobj2.c:123

References AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, INTERNAL_OBJ_CHECK, INTERNAL_OBJ_MUTEX, ao2_lock_priv::lock, astobj2_lock::mutex, NULL, __priv_data::options, astobj2::priv_data, and astobj2_lock::user_data.

Referenced by ast_serializer_shutdown_group_join(), ast_sip_session_suspend(), bridge_channel_wait(), bridge_manager_thread(), consumer_should_stay(), consumer_wait_for(), consumer_wait_for_completion(), control_wait(), db_sync_thread(), rtp_deallocate_transport(), sip_session_suspend_task(), and stasis_subscription_join().

◆ ao2_options_get()

unsigned int ao2_options_get ( void *  obj)

Retrieve the ao2 options used to create the object.

Parameters
objpointer to the (user-defined part) of an object.
Returns
options from enum ao2_alloc_opts.

Definition at line 781 of file astobj2.c.

782 {
783  struct astobj2 *orig_obj;
784 
785  orig_obj = INTERNAL_OBJ_CHECK(obj);
786  if (!orig_obj) {
787  return 0;
788  }
789  return orig_obj->priv_data.options;
790 }

References INTERNAL_OBJ_CHECK, __priv_data::options, and astobj2::priv_data.

Referenced by __ast_named_lock_get(), hash_ao2_alloc_empty_clone(), and rb_ao2_alloc_empty_clone().

◆ ao2_weakproxy_subscribe()

int ao2_weakproxy_subscribe ( void *  weakproxy,
ao2_weakproxy_notification_cb  cb,
void *  data,
int  flags 
)

Request notification when weakproxy points to NULL.

Since
14.0.0
Parameters
weakproxyThe weak object
cbProcedure to call when no real object is associated
dataPassed to cb
flagsOBJ_NOLOCK to avoid locking weakproxy.
Return values
0Success
-1Failure
Note
Callbacks are run in the reverse order of subscriptions.
This procedure will allow the same cb / data pair to be added to the same weakproxy multiple times.
It is the caller's responsibility to ensure that *data is valid until after cb() is run or ao2_weakproxy_unsubscribe is called.
If the weakproxy currently points to NULL the callback will be run immediately, without being added to the subscriber list.

Definition at line 934 of file astobj2.c.

935 {
936  struct astobj2 *weakproxy_internal = INTERNAL_OBJ_CHECK(weakproxy);
937  int ret = -1;
938  int hasobj;
939 
940  if (!weakproxy_internal || weakproxy_internal->priv_data.magic != AO2_WEAK) {
941  return -1;
942  }
943 
944  if (!(flags & OBJ_NOLOCK)) {
945  ao2_lock(weakproxy);
946  }
947 
948  hasobj = weakproxy_internal->priv_data.weakptr != NULL;
949  if (hasobj) {
950  struct ao2_weakproxy *weak = weakproxy;
951  struct ao2_weakproxy_notification *sub = ast_calloc(1, sizeof(*sub));
952 
953  if (sub) {
954  sub->cb = cb;
955  sub->data = data;
957  ret = 0;
958  }
959  }
960 
961  if (!(flags & OBJ_NOLOCK)) {
962  ao2_unlock(weakproxy);
963  }
964 
965  if (!hasobj) {
966  cb(weakproxy, data);
967  ret = 0;
968  }
969 
970  return ret;
971 }
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
struct stasis_forward * sub
Definition: res_corosync.c:240

References ao2_lock, ao2_unlock, AO2_WEAK, ast_calloc, AST_LIST_INSERT_HEAD, ao2_weakproxy_notification::cb, ao2_weakproxy_notification::data, ao2_weakproxy::destroyed_cb, INTERNAL_OBJ_CHECK, ao2_weakproxy_notification::list, __priv_data::magic, NULL, OBJ_NOLOCK, astobj2::priv_data, sub, and __priv_data::weakptr.

Referenced by __ast_named_lock_get(), __ast_sorcery_open(), AST_TEST_DEFINE(), link_topic_proxy(), and state_alloc().

◆ ao2_weakproxy_unsubscribe()

int ao2_weakproxy_unsubscribe ( void *  weakproxy,
ao2_weakproxy_notification_cb  cb,
void *  data,
int  flags 
)

Remove notification of real object destruction.

Since
14.0.0
Parameters
weakproxyThe weak object
cbCallback to remove from destroy notification list
dataData pointer to match
flagsOBJ_NOLOCK to avoid locking weakproxy. OBJ_MULTIPLE to remove all copies of the same cb / data pair.
Returns
The number of subscriptions removed.
Return values
0cb / data pair not found, nothing removed.
-1Failure due to invalid parameters.
Note
Unless flags includes OBJ_MULTIPLE, this will only remove a single copy of the cb / data pair. If it was subscribed multiple times it must be unsubscribed as many times. The OBJ_MULTIPLE flag can be used to remove matching subscriptions.
When it's time to run callbacks they are copied to a temporary list so the weakproxy can be unlocked before running. That means it's possible for this function to find nothing before the callback is run in another thread.

Definition at line 973 of file astobj2.c.

974 {
975  struct astobj2 *internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy);
976  struct ao2_weakproxy *weak;
978  int ret = 0;
979 
980  if (!internal_weakproxy || internal_weakproxy->priv_data.magic != AO2_WEAK || !destroyed_cb) {
981  return -1;
982  }
983 
984  if (!(flags & OBJ_NOLOCK)) {
985  ao2_lock(weakproxy);
986  }
987 
988  weak = weakproxy;
990  if (sub->cb == destroyed_cb && sub->data == data) {
992  ast_free(sub);
993  ret++;
994  if (!(flags & OBJ_MULTIPLE)) {
995  break;
996  }
997  }
998  }
1000 
1001  if (!(flags & OBJ_NOLOCK)) {
1002  ao2_unlock(weakproxy);
1003  }
1004 
1005  return ret;
1006 }
@ OBJ_MULTIPLE
Definition: astobj2.h:1053
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557

References ao2_lock, ao2_unlock, AO2_WEAK, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ao2_weakproxy_notification::data, ao2_weakproxy::destroyed_cb, INTERNAL_OBJ_CHECK, ao2_weakproxy_notification::list, __priv_data::magic, OBJ_MULTIPLE, OBJ_NOLOCK, astobj2::priv_data, and sub.

Referenced by AST_TEST_DEFINE().

◆ astobj2_cleanup()

static void astobj2_cleanup ( void  )
static

Definition at line 1157 of file astobj2.c.

1158 {
1159 #if defined(AO2_DEBUG)
1160  ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1161 #endif
1162 
1163  if (ast_opt_ref_debug) {
1164  fclose(ref_log);
1165  ref_log = NULL;
1166  }
1167 }
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define ast_opt_ref_debug
Definition: options.h:135
#define ARRAY_LEN(a)
Definition: utils.h:639

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_opt_ref_debug, NULL, and ref_log.

Referenced by astobj2_init().

◆ astobj2_init()

int astobj2_init ( void  )

Provided by astobj2.c

Definition at line 1169 of file astobj2.c.

1170 {
1171  char ref_filename[1024];
1172 
1173  if (ast_opt_ref_debug) {
1174  snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
1175  ref_log = fopen(ref_filename, "w");
1176  if (!ref_log) {
1177  ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
1178  }
1179  }
1180 
1182 
1183  if (container_init() != 0) {
1184  fclose(ref_log);
1185  ref_log = NULL;
1186  return -1;
1187  }
1188 
1189 #if defined(AO2_DEBUG)
1190  ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1191 #endif /* defined(AO2_DEBUG) */
1192 
1193  return 0;
1194 }
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
static void astobj2_cleanup(void)
Definition: astobj2.c:1157
int container_init(void)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
const char * ast_config_AST_LOG_DIR
Definition: options.c:159

References ARRAY_LEN, ast_cli_register_multiple, ast_config_AST_LOG_DIR, ast_log, ast_opt_ref_debug, ast_register_cleanup(), astobj2_cleanup(), container_init(), LOG_ERROR, NULL, and ref_log.

Referenced by asterisk_daemon().

◆ internal_ao2_alloc()

static void* internal_ao2_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
unsigned int  options,
void *  lockobj,
const char *  tag,
const char *  file,
int  line,
const char *  func 
)
static

Definition at line 684 of file astobj2.c.

686 {
687  /* allocation */
688  struct astobj2 *obj;
689  struct astobj2_lock *obj_mutex;
690  struct astobj2_rwlock *obj_rwlock;
691  struct astobj2_lockobj *obj_lockobj;
692  size_t overhead;
693 
694  switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
696  overhead = sizeof(*obj_mutex);
697  obj_mutex = __ast_calloc(1, overhead + data_size, file, line, func);
698  if (obj_mutex == NULL) {
699  return NULL;
700  }
701 
702  ast_mutex_init(&obj_mutex->mutex.lock);
703  obj = (struct astobj2 *) &obj_mutex->priv_data;
704  break;
706  overhead = sizeof(*obj_rwlock);
707  obj_rwlock = __ast_calloc(1, overhead + data_size, file, line, func);
708  if (obj_rwlock == NULL) {
709  return NULL;
710  }
711 
712  ast_rwlock_init(&obj_rwlock->rwlock.lock);
713  obj = (struct astobj2 *) &obj_rwlock->priv_data;
714  break;
716  overhead = sizeof(*obj);
717  obj = __ast_calloc(1, overhead + data_size, file, line, func);
718  if (obj == NULL) {
719  return NULL;
720  }
721  break;
723  lockobj = ao2_t_bump(lockobj, "set lockobj");
724  if (!lockobj) {
725  ast_log(__LOG_ERROR, file, line, func, "AO2_ALLOC_OPT_LOCK_OBJ requires a non-NULL lockobj.\n");
726  return NULL;
727  }
728 
729  overhead = sizeof(*obj_lockobj);
730  obj_lockobj = __ast_calloc(1, overhead + data_size, file, line, func);
731  if (obj_lockobj == NULL) {
732  ao2_t_ref(lockobj, -1, "release lockobj for failed alloc");
733  return NULL;
734  }
735 
736  obj_lockobj->lockobj.lock = lockobj;
737  obj = (struct astobj2 *) &obj_lockobj->priv_data;
738  break;
739  default:
740  /* Invalid option value. */
741  ast_log(__LOG_DEBUG, file, line, func, "Invalid lock option requested\n");
742  return NULL;
743  }
744 
745  /* Initialize common ao2 values. */
746  obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */
747  obj->priv_data.ref_counter = 1;
748  obj->priv_data.options = options;
749  obj->priv_data.magic = AO2_MAGIC;
750 
751 #ifdef AO2_DEBUG
752  obj->priv_data.data_size = data_size;
753  ast_atomic_fetchadd_int(&ao2.total_objects, 1);
754  ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
755  ast_atomic_fetchadd_int(&ao2.total_refs, 1);
756 #endif
757 
759  fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**%zu**%zu**,%s\n",
760  EXTERNAL_OBJ(obj), ast_get_tid(), file, line, func, overhead, data_size, tag ?: "");
761  fflush(ref_log);
762  }
763 
764  /* return a pointer to the user data */
765  return EXTERNAL_OBJ(obj);
766 }
void * __ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func) attribute_malloc
Definition: astmm.c:1635
#define EXTERNAL_OBJ(_p)
convert from a pointer _p to an astobj2 object
Definition: astobj2.c:191
#define ao2_t_bump(obj, tag)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:483
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:222
#define __LOG_DEBUG
Definition: logger.h:241
struct __priv_data priv_data
Definition: astobj2.c:122
struct __priv_data priv_data
Definition: astobj2.c:146
struct __priv_data priv_data
Definition: astobj2.c:135

References __ast_calloc(), __LOG_DEBUG, __LOG_ERROR, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_OBJ, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_ALLOC_OPT_NO_REF_DEBUG, AO2_MAGIC, ao2_t_bump, ao2_t_ref, ast_atomic_fetchadd_int(), ast_get_tid(), ast_log, ast_mutex_init, ast_rwlock_init, __priv_data::destructor_fn, EXTERNAL_OBJ, make_ari_stubs::file, ao2_lock_priv::lock, ao2_rwlock_priv::lock, ao2_lockobj_priv::lock, astobj2_lockobj::lockobj, __priv_data::magic, astobj2_lock::mutex, NULL, __priv_data::options, options, astobj2::priv_data, astobj2_lock::priv_data, astobj2_rwlock::priv_data, astobj2_lockobj::priv_data, __priv_data::ref_counter, ref_log, and astobj2_rwlock::rwlock.

Referenced by __ao2_alloc(), and __ao2_alloc_with_lockobj().

◆ internal_is_ao2_object()

int internal_is_ao2_object ( void *  user_data)

Definition at line 193 of file astobj2.c.

194 {
195  struct astobj2 *p;
196 
197  if (!user_data) {
198  return 0;
199  }
200 
201  p = INTERNAL_OBJ(user_data);
202 
203  return !p || IS_AO2_MAGIC_BAD(p) ? 0 : 1;
204 }
#define IS_AO2_MAGIC_BAD(p)
Definition: astobj2.c:98

References INTERNAL_OBJ, IS_AO2_MAGIC_BAD, and astobj2::user_data.

◆ log_bad_ao2()

void log_bad_ao2 ( void *  user_data,
const char *  file,
int  line,
const char *  func 
)

Definition at line 206 of file astobj2.c.

207 {
208  struct astobj2 *p;
209  char bad_magic[100];
210 
211  if (!user_data) {
212  __ast_assert_failed(0, "user_data is NULL", file, line, func);
213  return;
214  }
215 
216  p = INTERNAL_OBJ(user_data);
217  snprintf(bad_magic, sizeof(bad_magic), "bad magic number 0x%x for object %p",
219  __ast_assert_failed(0, bad_magic, file, line, func);
220 }

References __ast_assert_failed(), make_ari_stubs::file, INTERNAL_OBJ, __priv_data::magic, astobj2::priv_data, and astobj2::user_data.

Variable Documentation

◆ ref_log

FILE* ref_log
static