Wed Jan 8 2020 09:49:58

Asterisk developer's documentation


astobj2.c File Reference
#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/astobj2.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/paths.h"
#include <execinfo.h>

Go to the source code of this file.

Data Structures

struct  __priv_data
 
struct  ao2_container
 
struct  astobj2
 
struct  bucket
 
struct  bucket_entry
 

Macros

#define AO2_MAGIC   0xa570b123
 
#define EXTERNAL_OBJ(_p)   ((_p) == NULL ? NULL : (_p)->user_data)
 convert from a pointer _p to an astobj2 object More...
 
#define N1   20
 

Enumerations

enum  ao2_callback_type { DEFAULT, WITH_DATA }
 

Functions

void * __ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn)
 
void * __ao2_alloc_debug (size_t data_size, ao2_destructor_fn destructor_fn, char *tag, const char *file, int line, const char *funcname, int ref_debug)
 
void * __ao2_callback (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg)
 
void * __ao2_callback_data (struct ao2_container *c, const enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data)
 
void * __ao2_callback_data_debug (struct ao2_container *c, const enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data, char *tag, char *file, int line, const char *funcname)
 
void * __ao2_callback_debug (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, char *tag, char *file, int line, const char *funcname)
 
struct ao2_container__ao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
 
struct ao2_container__ao2_container_alloc_debug (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn, char *tag, char *file, int line, const char *funcname, int ref_debug)
 
void * __ao2_find (struct ao2_container *c, void *arg, enum search_flags flags)
 
void * __ao2_find_debug (struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname)
 
void * __ao2_iterator_next (struct ao2_iterator *a)
 
void * __ao2_iterator_next_debug (struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname)
 
void * __ao2_link (struct ao2_container *c, void *user_data)
 
void * __ao2_link_debug (struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
 
int __ao2_lock (void *user_data, const char *file, const char *func, int line, const char *var)
 Lock an object. More...
 
int __ao2_ref (void *user_data, const int delta)
 
int __ao2_ref_debug (void *user_data, const int delta, const char *tag, const char *file, int line, const char *funcname)
 
int __ao2_trylock (void *user_data, const char *file, const char *func, int line, const char *var)
 Try locking– (don't block if fail) More...
 
void * __ao2_unlink (struct ao2_container *c, void *user_data)
 
void * __ao2_unlink_debug (struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname)
 
int __ao2_unlock (void *user_data, const char *file, const char *func, int line, const char *var)
 Unlock an object. More...
 
void ao2_bt (void)
 
int ao2_container_count (struct ao2_container *c)
 Returns the number of elements in a container. More...
 
void ao2_iterator_destroy (struct ao2_iterator *i)
 Destroy a container iterator. More...
 
struct ao2_iterator ao2_iterator_init (struct ao2_container *c, int flags)
 Create an iterator for a container. More...
 
int ao2_match_by_addr (void *user_data, void *arg, int flags)
 another convenience function is a callback that matches on address More...
 
void * ao2_object_get_lockaddr (void *obj)
 Return the lock address of an object. More...
 
static void astobj2_cleanup (void)
 
int astobj2_init (void)
 
static int cb_true (void *user_data, void *arg, int flags)
 special callback that matches all More...
 
static int cb_true_data (void *user_data, void *arg, void *data, int flags)
 similar to cb_true, but is an ao2_callback_data_fn instead More...
 
static int cd_cb (void *obj, void *arg, int flag)
 
static int cd_cb_debug (void *obj, void *arg, int flag)
 
static void container_destruct (void *c)
 
static void container_destruct_debug (void *c)
 
static int hash_zero (const void *user_obj, const int flags)
 always zero hash function More...
 
static void * internal_ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, const char *file, int line, const char *funcname)
 
static void * internal_ao2_callback (struct ao2_container *c, const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, char *tag, char *file, int line, const char *funcname)
 
static struct ao2_containerinternal_ao2_container_alloc (struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
 
static struct ao2_containerinternal_ao2_container_alloc (struct ao2_container *c, const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
 
static void * internal_ao2_iterator_next (struct ao2_iterator *a, struct bucket_entry **q)
 
static struct bucket_entryinternal_ao2_link (struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
 
static int internal_ao2_ref (void *user_data, const int delta)
 
static struct astobj2INTERNAL_OBJ (void *user_data)
 convert from a pointer _p to a user-defined object More...
 

Variables

static FILE * ref_log
 

Macro Definition Documentation

#define AO2_MAGIC   0xa570b123

Definition at line 58 of file astobj2.c.

Referenced by internal_ao2_alloc(), and INTERNAL_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 148 of file astobj2.c.

Referenced by internal_ao2_alloc(), internal_ao2_callback(), and internal_ao2_iterator_next().

#define N1   20

Referenced by ao2_bt().

Enumeration Type Documentation

Enumerator
DEFAULT 
WITH_DATA 

Definition at line 138 of file astobj2.c.

138  {
139  DEFAULT,
140  WITH_DATA,
141 };

Function Documentation

void* __ao2_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn 
)

Definition at line 354 of file astobj2.c.

References internal_ao2_alloc().

Referenced by __ao2_container_alloc().

355 {
356  return internal_ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__);
357 }
static void * internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, const char *file, int line, const char *funcname)
Definition: astobj2.c:302
void* __ao2_alloc_debug ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
char *  tag,
const char *  file,
int  line,
const char *  funcname,
int  ref_debug 
)

Definition at line 335 of file astobj2.c.

References ast_get_tid(), and internal_ao2_alloc().

Referenced by __ao2_container_alloc_debug(), __ast_channel_alloc_ap(), _moh_class_malloc(), and ast_dummy_channel_alloc().

337 {
338  /* allocation */
339  void *obj;
340 
341  if ((obj = internal_ao2_alloc(data_size, destructor_fn, file, line, funcname)) == NULL) {
342  return NULL;
343  }
344 
345  if (ref_log) {
346  fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n", obj, ast_get_tid(), file, line, funcname, tag);
347  fflush(ref_log);
348  }
349 
350  /* return a pointer to the user data */
351  return obj;
352 }
int ast_get_tid(void)
Get current thread ID.
Definition: utils.c:2346
static void * internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, const char *file, int line, const char *funcname)
Definition: astobj2.c:302
static FILE * ref_log
Definition: astobj2.c:35
void* __ao2_callback ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg 
)

Definition at line 782 of file astobj2.c.

References DEFAULT, and internal_ao2_callback().

Referenced by __ao2_find(), __ao2_unlink(), and container_destruct().

784 {
785  return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
786 }
static void * internal_ao2_callback(struct ao2_container *c, const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, char *tag, char *file, int line, const char *funcname)
Definition: astobj2.c:599
void* __ao2_callback_data ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_data_fn cb_fn,
void *  arg,
void *  data 
)

Definition at line 796 of file astobj2.c.

References internal_ao2_callback(), and WITH_DATA.

798 {
799  return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
800 }
static void * internal_ao2_callback(struct ao2_container *c, const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, char *tag, char *file, int line, const char *funcname)
Definition: astobj2.c:599
void* __ao2_callback_data_debug ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_data_fn cb_fn,
void *  arg,
void *  data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 788 of file astobj2.c.

References internal_ao2_callback(), and WITH_DATA.

792 {
793  return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
794 }
static void * internal_ao2_callback(struct ao2_container *c, const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, char *tag, char *file, int line, const char *funcname)
Definition: astobj2.c:599
void* __ao2_callback_debug ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 774 of file astobj2.c.

References DEFAULT, and internal_ao2_callback().

Referenced by __ao2_find_debug(), __ao2_unlink_debug(), and container_destruct_debug().

778 {
779  return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
780 }
static void * internal_ao2_callback(struct ao2_container *c, const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, char *tag, char *file, int line, const char *funcname)
Definition: astobj2.c:599
struct ao2_container* __ao2_container_alloc ( const unsigned int  n_buckets,
ao2_hash_fn hash_fn,
ao2_callback_fn cmp_fn 
)

Definition at line 454 of file astobj2.c.

References __ao2_alloc(), container_destruct(), and internal_ao2_container_alloc().

456 {
457  /* XXX maybe consistency check on arguments ? */
458  /* compute the container size */
459 
460  const unsigned int num_buckets = hash_fn ? n_buckets : 1;
461  size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
462  struct ao2_container *c = __ao2_alloc(container_size, container_destruct);
463 
464  return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
465 }
static void container_destruct(void *c)
Definition: astobj2.c:964
static struct ao2_container * internal_ao2_container_alloc(struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
void * __ao2_alloc(const size_t data_size, ao2_destructor_fn destructor_fn)
Definition: astobj2.c:354
ao2_hash_fn * hash_fn
Event type specific hash function.
Definition: event.c:165
ao2_callback_fn * cmp_fn
Definition: astobj2.c:393
struct ao2_container* __ao2_container_alloc_debug ( const unsigned int  n_buckets,
ao2_hash_fn hash_fn,
ao2_callback_fn cmp_fn,
char *  tag,
char *  file,
int  line,
const char *  funcname,
int  ref_debug 
)

Definition at line 441 of file astobj2.c.

References __ao2_alloc_debug(), container_destruct(), container_destruct_debug(), and internal_ao2_container_alloc().

444 {
445  /* XXX maybe consistency check on arguments ? */
446  /* compute the container size */
447  const unsigned int num_buckets = hash_fn ? n_buckets : 1;
448  size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
449  struct ao2_container *c = __ao2_alloc_debug(container_size, ref_debug ? container_destruct_debug : container_destruct, tag, file, line, funcname, ref_debug);
450 
451  return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
452 }
static void container_destruct(void *c)
Definition: astobj2.c:964
static struct ao2_container * internal_ao2_container_alloc(struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
int n_buckets
Definition: astobj2.c:394
static void container_destruct_debug(void *c)
Definition: astobj2.c:984
void * __ao2_alloc_debug(const size_t data_size, ao2_destructor_fn destructor_fn, char *tag, const char *file, int line, const char *funcname, int ref_debug)
Definition: astobj2.c:335
ao2_hash_fn * hash_fn
Event type specific hash function.
Definition: event.c:165
ao2_callback_fn * cmp_fn
Definition: astobj2.c:393
void* __ao2_find ( struct ao2_container c,
void *  arg,
enum search_flags  flags 
)

Definition at line 810 of file astobj2.c.

References __ao2_callback(), and ao2_container::cmp_fn.

Referenced by _get_mohbyname().

811 {
812  return __ao2_callback(c, flags, c->cmp_fn, arg);
813 }
void * __ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg)
Definition: astobj2.c:782
ao2_callback_fn * cmp_fn
Definition: astobj2.c:393
void* __ao2_find_debug ( struct ao2_container c,
void *  arg,
enum search_flags  flags,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

the find function just invokes the default callback with some reasonable flags.

Definition at line 805 of file astobj2.c.

References __ao2_callback_debug(), and ao2_container::cmp_fn.

Referenced by _get_mohbyname().

806 {
807  return __ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
808 }
void * __ao2_callback_debug(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, char *tag, char *file, int line, const char *funcname)
Definition: astobj2.c:774
ao2_callback_fn * cmp_fn
Definition: astobj2.c:393
void* __ao2_iterator_next ( struct ao2_iterator a)

Definition at line 931 of file astobj2.c.

References __ao2_ref(), AO2_ITERATOR_DONTLOCK, ao2_unlock, ao2_iterator::c, ao2_iterator::flags, and internal_ao2_iterator_next().

932 {
933  struct bucket_entry *p = NULL;
934  void *ret = NULL;
935 
936  ret = internal_ao2_iterator_next(a, &p);
937 
938  if (p) {
939  /* inc refcount of returned object */
940  __ao2_ref(ret, 1);
941  }
942 
943  if (!(a->flags & AO2_ITERATOR_DONTLOCK))
944  ao2_unlock(a->c);
945 
946  return ret;
947 }
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_container * c
Definition: astobj2.h:1055
int __ao2_ref(void *o, int delta)
Definition: astobj2.c:248
Definition: astobj2.c:480
static void * internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_entry **q)
Definition: astobj2.c:846
void* __ao2_iterator_next_debug ( struct ao2_iterator a,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 913 of file astobj2.c.

References __ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_unlock, ao2_iterator::c, ao2_iterator::flags, and internal_ao2_iterator_next().

914 {
915  struct bucket_entry *p;
916  void *ret = NULL;
917 
918  ret = internal_ao2_iterator_next(a, &p);
919 
920  if (p) {
921  /* inc refcount of returned object */
922  __ao2_ref_debug(ret, 1, tag, file, line, funcname);
923  }
924 
925  if (!(a->flags & AO2_ITERATOR_DONTLOCK))
926  ao2_unlock(a->c);
927 
928  return ret;
929 }
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_container * c
Definition: astobj2.h:1055
Definition: astobj2.c:480
int __ao2_ref_debug(void *o, int delta, const char *tag, const char *file, int line, const char *funcname)
Definition: astobj2.c:219
static void * internal_ao2_iterator_next(struct ao2_iterator *a, struct bucket_entry **q)
Definition: astobj2.c:846
void* __ao2_link ( struct ao2_container c,
void *  user_data 
)

Definition at line 531 of file astobj2.c.

References __ao2_ref(), ao2_unlock, and internal_ao2_link().

Referenced by internal_ao2_callback().

532 {
533  struct bucket_entry *p = internal_ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);
534 
535  if (p) {
536  __ao2_ref(user_data, +1);
537  ao2_unlock(c);
538  }
539  return p;
540 }
static struct bucket_entry * internal_ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
Definition: astobj2.c:490
#define ao2_unlock(a)
Definition: astobj2.h:497
int __ao2_ref(void *o, int delta)
Definition: astobj2.c:248
Definition: astobj2.c:480
void* __ao2_link_debug ( struct ao2_container c,
void *  user_data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 520 of file astobj2.c.

References __ao2_ref_debug(), ao2_unlock, and internal_ao2_link().

Referenced by internal_ao2_callback().

521 {
522  struct bucket_entry *p = internal_ao2_link(c, user_data, file, line, funcname);
523 
524  if (p) {
525  __ao2_ref_debug(user_data, +1, tag, file, line, funcname);
526  ao2_unlock(c);
527  }
528  return p;
529 }
static struct bucket_entry * internal_ao2_link(struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
Definition: astobj2.c:490
#define ao2_unlock(a)
Definition: astobj2.h:497
Definition: astobj2.c:480
int __ao2_ref_debug(void *o, int delta, const char *tag, const char *file, int line, const char *funcname)
Definition: astobj2.c:219
int __ao2_lock ( void *  a,
const char *  file,
const char *  func,
int  line,
const char *  var 
)

Lock an object.

Parameters
aA pointer to the object we want to lock.
Returns
0 on success, other values on error.

Definition at line 161 of file astobj2.c.

References __ast_pthread_mutex_lock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.

162 {
163  struct astobj2 *p = INTERNAL_OBJ(user_data);
164 
165  if (p == NULL)
166  return -1;
167 
168 #ifdef AO2_DEBUG
169  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
170 #endif
171 
172  return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock);
173 }
#define var
Definition: ast_expr2f.c:606
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
void * user_data[0]
Definition: astobj2.c:66
int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
Definition: lock.c:177
struct __priv_data priv_data
Definition: astobj2.c:65
ast_mutex_t lock
Definition: astobj2.c:48
int __ao2_ref ( void *  user_data,
const int  delta 
)

Definition at line 248 of file astobj2.c.

References internal_ao2_ref().

Referenced by __ao2_iterator_next(), __ao2_link(), cd_cb(), and internal_ao2_callback().

249 {
250  return internal_ao2_ref(user_data, delta);
251 }
static int internal_ao2_ref(void *user_data, const int delta)
Definition: astobj2.c:253
void * user_data[0]
Definition: astobj2.c:66
int __ao2_ref_debug ( void *  user_data,
const int  delta,
const char *  tag,
const char *  file,
int  line,
const char *  funcname 
)

Definition at line 219 of file astobj2.c.

References ast_get_tid(), internal_ao2_ref(), and INTERNAL_OBJ().

Referenced by __ao2_iterator_next_debug(), __ao2_link_debug(), cd_cb_debug(), dialog_ref_debug(), dialog_unref_debug(), and internal_ao2_callback().

220 {
221  struct astobj2 *obj = INTERNAL_OBJ(user_data);
222  int old_refcount = -1;
223 
224  if (obj) {
225  old_refcount = internal_ao2_ref(user_data, delta);
226  }
227 
228  if (ref_log && user_data) {
229  if (!obj) {
230  /* Invalid object: Bad magic number. */
231  fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
232  user_data, delta, ast_get_tid(), file, line, funcname, tag);
233  fflush(ref_log);
234  } else if (old_refcount + delta == 0) {
235  fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n",
236  user_data, delta, ast_get_tid(), file, line, funcname, tag);
237  fflush(ref_log);
238  } else if (delta != 0) {
239  fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data, (delta < 0 ? "" : "+"),
240  delta, ast_get_tid(), file, line, funcname, old_refcount, tag);
241  fflush(ref_log);
242  }
243  }
244 
245  return old_refcount;
246 }
static int internal_ao2_ref(void *user_data, const int delta)
Definition: astobj2.c:253
int ast_get_tid(void)
Get current thread ID.
Definition: utils.c:2346
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
void * user_data[0]
Definition: astobj2.c:66
static FILE * ref_log
Definition: astobj2.c:35
int __ao2_trylock ( void *  a,
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.
Returns
0 on success, other values on error.

Definition at line 189 of file astobj2.c.

References __ast_pthread_mutex_trylock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.

190 {
191  struct astobj2 *p = INTERNAL_OBJ(user_data);
192  int ret;
193 
194  if (p == NULL)
195  return -1;
196  ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock);
197 
198 #ifdef AO2_DEBUG
199  if (!ret)
200  ast_atomic_fetchadd_int(&ao2.total_locked, 1);
201 #endif
202  return ret;
203 }
#define var
Definition: ast_expr2f.c:606
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
void * user_data[0]
Definition: astobj2.c:66
struct __priv_data priv_data
Definition: astobj2.c:65
int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
Definition: lock.c:317
ast_mutex_t lock
Definition: astobj2.c:48
void* __ao2_unlink ( struct ao2_container c,
void *  user_data 
)

Definition at line 565 of file astobj2.c.

References __ao2_callback(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.

566 {
567  if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */
568  return NULL;
569 
571 
572  return NULL;
573 }
void * __ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg)
Definition: astobj2.c:782
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
ao2_callback_fn ao2_match_by_addr
a very common callback is one that matches by address.
Definition: astobj2.h:646
void * user_data[0]
Definition: astobj2.c:66
void* __ao2_unlink_debug ( struct ao2_container c,
void *  user_data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 554 of file astobj2.c.

References __ao2_callback_debug(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.

556 {
557  if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */
558  return NULL;
559 
561 
562  return NULL;
563 }
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
void * __ao2_callback_debug(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, char *tag, char *file, int line, const char *funcname)
Definition: astobj2.c:774
ao2_callback_fn ao2_match_by_addr
a very common callback is one that matches by address.
Definition: astobj2.h:646
void * user_data[0]
Definition: astobj2.c:66
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.
Returns
0 on success, other values on error.

Definition at line 175 of file astobj2.c.

References __ast_pthread_mutex_unlock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.

176 {
177  struct astobj2 *p = INTERNAL_OBJ(user_data);
178 
179  if (p == NULL)
180  return -1;
181 
182 #ifdef AO2_DEBUG
183  ast_atomic_fetchadd_int(&ao2.total_locked, -1);
184 #endif
185 
186  return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock);
187 }
#define var
Definition: ast_expr2f.c:606
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
Definition: lock.c:399
void * user_data[0]
Definition: astobj2.c:66
struct __priv_data priv_data
Definition: astobj2.c:65
ast_mutex_t lock
Definition: astobj2.c:48
void ao2_bt ( void  )

Definition at line 90 of file astobj2.c.

References ast_bt_get_symbols(), ast_std_free(), ast_verbose(), and N1.

91 {
92  int c, i;
93 #define N1 20
94  void *addresses[N1];
95  char **strings;
96 
97  c = backtrace(addresses, N1);
98  strings = ast_bt_get_symbols(addresses,c);
99  ast_verbose("backtrace returned: %d\n", c);
100  for(i = 0; i < c; i++) {
101  ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
102  }
103  ast_std_free(strings);
104 }
void ast_std_free(void *ptr)
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
char ** ast_bt_get_symbols(void **addresses, size_t num_frames)
Definition: logger.c:1335
#define N1
void ao2_iterator_destroy ( struct ao2_iterator i)

Destroy a container iterator.

destroy an iterator

Definition at line 833 of file astobj2.c.

References AO2_ITERATOR_MALLOCD, ao2_ref, ast_free, ao2_iterator::c, and ao2_iterator::flags.

Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __iax2_show_peers(), __queues_show(), _sip_show_peers(), action_meetmelist(), alias_show(), ast_channel_iterator_destroy(), ast_data_iterator_end(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_srtp_unprotect(), ast_var_indications(), ast_var_indications_table(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), complete_userno(), conf_queue_dtmf(), data_filter_find(), data_get_xml_add_child(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), destroy_pvts(), dialgroup_read(), do_parking_thread(), dump_queue_members(), extension_state_cb(), fax_session_tab_complete(), find_call(), find_queue_by_name_rt(), find_session(), find_session_by_nonce(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_indication_show(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_odbc_show(), handle_cli_status(), handle_feature_show(), handle_parkedcalls(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_showmanconn(), handle_statechange(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), kill_duplicate_offers(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), num_available_members(), peers_data_provider_get(), poke_all_peers(), prune_peers(), prune_users(), purge_sessions(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_queuememberpaused(), queue_function_queuememberstatus(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), sla_calc_station_delays(), sla_change_trunk_state(), sla_queue_event_conf(), sla_show_stations(), sla_show_trunks(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().

834 {
835  ao2_ref(i->c, -1);
836  if (i->flags & AO2_ITERATOR_MALLOCD) {
837  ast_free(i);
838  } else {
839  i->c = NULL;
840  }
841 }
struct ao2_container * c
Definition: astobj2.h:1055
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ast_free(a)
Definition: astmm.h:97
struct ao2_iterator ao2_iterator_init ( struct ao2_container c,
int  flags 
)

Create an iterator for a container.

initialize an iterator so we start from the first object

Definition at line 818 of file astobj2.c.

References ao2_ref, ao2_iterator::c, and ao2_iterator::flags.

Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __iax2_show_peers(), __queues_show(), action_meetmelist(), alias_show(), ast_channel_iterator_all_new(), ast_data_iterator_init(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_srtp_unprotect(), ast_tone_zone_iterator_init(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), complete_userno(), conf_queue_dtmf(), data_filter_find(), data_get_xml_add_child(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), destroy_pvts(), dialgroup_read(), do_parking_thread(), dump_queue_members(), extension_state_cb(), fax_session_tab_complete(), find_queue_by_name_rt(), find_session(), find_session_by_nonce(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_odbc_show(), handle_cli_status(), handle_feature_show(), handle_parkedcalls(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_showmanconn(), handle_statechange(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), internal_ao2_callback(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), num_available_members(), peers_data_provider_get(), poke_all_peers(), prune_peers(), prune_users(), purge_sessions(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_queuememberpaused(), queue_function_queuememberstatus(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), sla_calc_station_delays(), sla_change_trunk_state(), sla_queue_event_conf(), sla_show_stations(), sla_show_trunks(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().

819 {
820  struct ao2_iterator a = {
821  .c = c,
822  .flags = flags
823  };
824 
825  ao2_ref(c, +1);
826 
827  return a;
828 }
struct ao2_container * c
Definition: astobj2.h:1055
#define ao2_ref(o, delta)
Definition: astobj2.h:472
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
int ao2_match_by_addr ( void *  user_data,
void *  arg,
int  flags 
)

another convenience function is a callback that matches on address

Definition at line 545 of file astobj2.c.

References CMP_MATCH, and CMP_STOP.

546 {
547  return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
548 }
void* ao2_object_get_lockaddr ( void *  obj)

Return the lock address of an object.

Parameters
[in]objA pointer to the object we want.
Returns
the address of the 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.

Since
1.6.1

Definition at line 205 of file astobj2.c.

References INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.

206 {
207  struct astobj2 *p = INTERNAL_OBJ(obj);
208 
209  if (p == NULL)
210  return NULL;
211 
212  return &p->priv_data.lock;
213 }
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
struct __priv_data priv_data
Definition: astobj2.c:65
ast_mutex_t lock
Definition: astobj2.c:48
static void astobj2_cleanup ( void  )
static

Definition at line 1137 of file astobj2.c.

References ARRAY_LEN, and ast_cli_unregister_multiple().

Referenced by astobj2_init().

1138 {
1139 #ifdef AO2_DEBUG
1140  ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1141 #endif
1142 
1143 #ifdef REF_DEBUG
1144  fclose(ref_log);
1145  ref_log = NULL;
1146 #endif
1147 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static FILE * ref_log
Definition: astobj2.c:35
int astobj2_init ( void  )

Provided by astobj2.c

Definition at line 1150 of file astobj2.c.

References ARRAY_LEN, ast_cli_register_multiple(), ast_config_AST_LOG_DIR, ast_log(), ast_register_atexit(), astobj2_cleanup(), and LOG_ERROR.

Referenced by main().

1151 {
1152 #ifdef REF_DEBUG
1153  char ref_filename[1024];
1154 #endif
1155 
1156 #ifdef REF_DEBUG
1157  snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
1158  ref_log = fopen(ref_filename, "w");
1159  if (!ref_log) {
1160  ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
1161  }
1162 #endif
1163 
1164 #ifdef AO2_DEBUG
1165  ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1166 #endif
1167 
1169  return 0;
1170 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static void astobj2_cleanup(void)
Definition: astobj2.c:1137
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:998
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
const char * ast_config_AST_LOG_DIR
Definition: asterisk.c:263
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static FILE * ref_log
Definition: astobj2.c:35
static int cb_true ( void *  user_data,
void *  arg,
int  flags 
)
static

special callback that matches all

Definition at line 578 of file astobj2.c.

References CMP_MATCH.

Referenced by internal_ao2_callback().

579 {
580  return CMP_MATCH;
581 }
static int cb_true_data ( void *  user_data,
void *  arg,
void *  data,
int  flags 
)
static

similar to cb_true, but is an ao2_callback_data_fn instead

Definition at line 586 of file astobj2.c.

References CMP_MATCH.

Referenced by internal_ao2_callback().

587 {
588  return CMP_MATCH;
589 }
static int cd_cb ( void *  obj,
void *  arg,
int  flag 
)
static

Definition at line 952 of file astobj2.c.

References __ao2_ref().

Referenced by container_destruct().

953 {
954  __ao2_ref(obj, -1);
955  return 0;
956 }
int __ao2_ref(void *o, int delta)
Definition: astobj2.c:248
static int cd_cb_debug ( void *  obj,
void *  arg,
int  flag 
)
static

Definition at line 958 of file astobj2.c.

References __ao2_ref_debug().

Referenced by container_destruct_debug().

959 {
960  __ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__);
961  return 0;
962 }
int __ao2_ref_debug(void *o, int delta, const char *tag, const char *file, int line, const char *funcname)
Definition: astobj2.c:219
static void container_destruct ( void *  c)
static

Definition at line 964 of file astobj2.c.

References __ao2_callback(), ast_atomic_fetchadd_int(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb(), bucket_entry::entry, ao2_container::n_buckets, and OBJ_UNLINK.

Referenced by __ao2_container_alloc(), and __ao2_container_alloc_debug().

965 {
966  struct ao2_container *c = _c;
967  int i;
968 
969  __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
970 
971  for (i = 0; i < c->n_buckets; i++) {
972  struct bucket_entry *current;
973 
974  while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
975  ast_free(current);
976  }
977  }
978 
979 #ifdef AO2_DEBUG
980  ast_atomic_fetchadd_int(&ao2.total_containers, -1);
981 #endif
982 }
static int cd_cb(void *obj, void *arg, int flag)
Definition: astobj2.c:952
int n_buckets
Definition: astobj2.c:394
void * __ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg)
Definition: astobj2.c:782
struct bucket_entry::@222 entry
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
Definition: astobj2.c:480
struct bucket buckets[0]
Definition: astobj2.c:400
static void container_destruct_debug ( void *  c)
static

Definition at line 984 of file astobj2.c.

References __ao2_callback_debug(), ast_atomic_fetchadd_int(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb_debug(), bucket_entry::entry, ao2_container::n_buckets, and OBJ_UNLINK.

Referenced by __ao2_container_alloc_debug().

985 {
986  struct ao2_container *c = _c;
987  int i;
988 
989  __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
990 
991  for (i = 0; i < c->n_buckets; i++) {
992  struct bucket_entry *current;
993 
994  while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
995  ast_free(current);
996  }
997  }
998 
999 #ifdef AO2_DEBUG
1000  ast_atomic_fetchadd_int(&ao2.total_containers, -1);
1001 #endif
1002 }
int n_buckets
Definition: astobj2.c:394
struct bucket_entry::@222 entry
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
static int cd_cb_debug(void *obj, void *arg, int flag)
Definition: astobj2.c:958
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
#define ast_free(a)
Definition: astmm.h:97
void * __ao2_callback_debug(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, char *tag, char *file, int line, const char *funcname)
Definition: astobj2.c:774
Definition: astobj2.c:480
struct bucket buckets[0]
Definition: astobj2.c:400
static int hash_zero ( const void *  user_obj,
const int  flags 
)
static

always zero hash function

it is convenient to have a hash function that always returns 0. This is basically used when we want to have a container that is a simple linked list.

Returns
0

Definition at line 412 of file astobj2.c.

Referenced by internal_ao2_container_alloc().

413 {
414  return 0;
415 }
static void* internal_ao2_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
const char *  file,
int  line,
const char *  funcname 
)
static

Definition at line 302 of file astobj2.c.

References __ast_calloc(), AO2_MAGIC, ast_atomic_fetchadd_int(), ast_calloc, ast_mutex_init, __priv_data::data_size, __priv_data::destructor_fn, EXTERNAL_OBJ, __priv_data::lock, __priv_data::magic, astobj2::priv_data, and __priv_data::ref_counter.

Referenced by __ao2_alloc(), and __ao2_alloc_debug().

303 {
304  /* allocation */
305  struct astobj2 *obj;
306 
307  if (data_size < sizeof(void *))
308  data_size = sizeof(void *);
309 
310 #if defined(__AST_DEBUG_MALLOC)
311  obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname);
312 #else
313  obj = ast_calloc(1, sizeof(*obj) + data_size);
314 #endif
315 
316  if (obj == NULL)
317  return NULL;
318 
320  obj->priv_data.magic = AO2_MAGIC;
321  obj->priv_data.data_size = data_size;
322  obj->priv_data.ref_counter = 1;
323  obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */
324 
325 #ifdef AO2_DEBUG
326  ast_atomic_fetchadd_int(&ao2.total_objects, 1);
327  ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
328  ast_atomic_fetchadd_int(&ao2.total_refs, 1);
329 #endif
330 
331  /* return a pointer to the user data */
332  return EXTERNAL_OBJ(obj);
333 }
int ref_counter
Definition: astobj2.c:49
size_t data_size
Definition: astobj2.c:52
void * __ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
#define AO2_MAGIC
Definition: astobj2.c:58
ao2_destructor_fn destructor_fn
Definition: astobj2.c:50
#define EXTERNAL_OBJ(_p)
convert from a pointer _p to an astobj2 object
Definition: astobj2.c:148
#define ast_calloc(a, b)
Definition: astmm.h:82
struct __priv_data priv_data
Definition: astobj2.c:65
#define ast_mutex_init(pmutex)
Definition: lock.h:152
ast_mutex_t lock
Definition: astobj2.c:48
uint32_t magic
Definition: astobj2.c:55
static void * internal_ao2_callback ( struct ao2_container c,
const enum search_flags  flags,
void *  cb_fn,
void *  arg,
void *  data,
enum ao2_callback_type  type,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)
static

Browse the container using different stategies accoding the flags.

Returns
Is a pointer to an object or to a list of object if OBJ_MULTIPLE is specified. Luckily, for debug purposes, the added args (tag, file, line, funcname) aren't an excessive load to the system, as the callback should not be called as often as, say, the ao2_ref func is called.

Definition at line 599 of file astobj2.c.

References __ao2_link(), __ao2_link_debug(), __ao2_ref(), __ao2_ref_debug(), ao2_container_alloc, AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), AO2_ITERATOR_MALLOCD, AO2_ITERATOR_UNLINK, ao2_lock, ao2_ref, ao2_unlock, ast_atomic_fetchadd_int(), ast_calloc, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, bucket_entry::astobj, ao2_container::buckets, cb_true(), cb_true_data(), CMP_MATCH, CMP_STOP, ao2_container::elements, bucket_entry::entry, EXTERNAL_OBJ, ao2_container::hash_fn, INTERNAL_OBJ(), last, match(), ao2_container::n_buckets, OBJ_CONTINUE, OBJ_MULTIPLE, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, ao2_container::version, and WITH_DATA.

Referenced by __ao2_callback(), __ao2_callback_data(), __ao2_callback_data_debug(), and __ao2_callback_debug().

602 {
603  int i, start, last; /* search boundaries */
604  void *ret = NULL;
605  ao2_callback_fn *cb_default = NULL;
606  ao2_callback_data_fn *cb_withdata = NULL;
607  struct ao2_container *multi_container = NULL;
608  struct ao2_iterator *multi_iterator = NULL;
609 
610  if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */
611  return NULL;
612 
613  /*
614  * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
615  * turned off. This if statement checks for the special condition
616  * where multiple items may need to be returned.
617  */
618  if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
619  /* we need to return an ao2_iterator with the results,
620  * as there could be more than one. the iterator will
621  * hold the only reference to a container that has all the
622  * matching objects linked into it, so when the iterator
623  * is destroyed, the container will be automatically
624  * destroyed as well.
625  */
626  if (!(multi_container = ao2_container_alloc(1, NULL, NULL))) {
627  return NULL;
628  }
629  if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
630  ao2_ref(multi_container, -1);
631  return NULL;
632  }
633  }
634 
635  /* override the match function if necessary */
636  if (cb_fn == NULL) { /* if NULL, match everything */
637  if (type == WITH_DATA) {
638  cb_withdata = cb_true_data;
639  } else {
640  cb_default = cb_true;
641  }
642  } else {
643  /* We do this here to avoid the per object casting penalty (even though
644  that is probably optimized away anyway). */
645  if (type == WITH_DATA) {
646  cb_withdata = cb_fn;
647  } else {
648  cb_default = cb_fn;
649  }
650  }
651 
652  /*
653  * XXX this can be optimized.
654  * If we have a hash function and lookup by pointer,
655  * run the hash function. Otherwise, scan the whole container
656  * (this only for the time being. We need to optimize this.)
657  */
658  if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
659  start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
660  else /* don't know, let's scan all buckets */
661  start = i = -1; /* XXX this must be fixed later. */
662 
663  /* determine the search boundaries: i..last-1 */
664  if (i < 0) {
665  start = i = 0;
666  last = c->n_buckets;
667  } else if ((flags & OBJ_CONTINUE)) {
668  last = c->n_buckets;
669  } else {
670  last = i + 1;
671  }
672 
673  ao2_lock(c); /* avoid modifications to the content */
674 
675  for (; i < last ; i++) {
676  /* scan the list with prev-cur pointers */
677  struct bucket_entry *cur;
678 
680  int match = (CMP_MATCH | CMP_STOP);
681 
682  if (type == WITH_DATA) {
683  match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
684  } else {
685  match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
686  }
687 
688  /* we found the object, performing operations according flags */
689  if (match == 0) { /* no match, no stop, continue */
690  continue;
691  } else if (match == CMP_STOP) { /* no match but stop, we are done */
692  i = last;
693  break;
694  }
695 
696  /* we have a match (CMP_MATCH) here */
697  if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */
698  /* it is important to handle this case before the unlink */
699  ret = EXTERNAL_OBJ(cur->astobj);
700  if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
701  if (tag)
702  __ao2_ref_debug(ret, 1, tag, file, line, funcname);
703  else
704  __ao2_ref(ret, 1);
705  }
706  }
707 
708  /* If we are in OBJ_MULTIPLE mode and OBJ_NODATE is off,
709  * link the object into the container that will hold the results.
710  */
711  if (ret && (multi_container != NULL)) {
712  if (tag) {
713  __ao2_link_debug(multi_container, ret, tag, file, line, funcname);
714  } else {
715  __ao2_link(multi_container, ret);
716  }
717  ret = NULL;
718  }
719 
720  if (flags & OBJ_UNLINK) { /* must unlink */
721  /* we are going to modify the container, so update version */
724  /* update number of elements */
726 
727  /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container
728  * must be decremented.
729  * - When unlinking with OBJ_MULTIPLE the ref from the original container
730  * must be decremented regardless if OBJ_NODATA is used. This is because the result is
731  * returned in a new container that already holds its own ref for the object. If the ref
732  * from the original container is not accounted for here a memory leak occurs. */
733  if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) {
734  if (tag)
735  __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, funcname);
736  else
737  __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
738  }
739  ast_free(cur); /* free the link record */
740  }
741 
742  if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
743  /* We found our only (or last) match, so force an exit from
744  the outside loop. */
745  i = last;
746  break;
747  }
748  }
750 
751  if (ret) {
752  break;
753  }
754 
755  if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
756  /* Move to the beginning to ensure we check every bucket */
757  i = -1;
758  last = start;
759  }
760  }
761  ao2_unlock(c);
762 
763  /* if multi_container was created, we are returning multiple objects */
764  if (multi_container != NULL) {
765  *multi_iterator = ao2_iterator_init(multi_container,
767  ao2_ref(multi_container, -1);
768  return multi_iterator;
769  } else {
770  return ret;
771  }
772 }
struct astobj2 * astobj
Definition: astobj2.c:483
int n_buckets
Definition: astobj2.c:394
Continue if a match is not found in the hashed out bucket.
Definition: astobj2.h:687
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
struct bucket_entry::@222 entry
void * __ao2_link_debug(struct ao2_container *c, void *new_obj, char *tag, char *file, int line, const char *funcname)
Definition: astobj2.c:520
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
struct sla_ringing_trunk * last
Definition: app_meetme.c:965
int __ao2_ref(void *o, int delta)
Definition: astobj2.c:248
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
#define ao2_ref(o, delta)
Definition: astobj2.h:472
#define ao2_lock(a)
Definition: astobj2.h:488
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
#define EXTERNAL_OBJ(_p)
convert from a pointer _p to an astobj2 object
Definition: astobj2.c:148
static int cb_true_data(void *user_data, void *arg, void *data, int flags)
similar to cb_true, but is an ao2_callback_data_fn instead
Definition: astobj2.c:586
#define ast_free(a)
Definition: astmm.h:97
static const char type[]
Definition: chan_nbs.c:57
static int cb_true(void *user_data, void *arg, int flags)
special callback that matches all
Definition: astobj2.c:578
int elements
Definition: astobj2.c:396
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
#define ast_calloc(a, b)
Definition: astmm.h:82
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
Definition: astobj2.c:480
int __ao2_ref_debug(void *o, int delta, const char *tag, const char *file, int line, const char *funcname)
Definition: astobj2.c:219
ao2_hash_fn * hash_fn
Definition: astobj2.c:392
static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2069
void * __ao2_link(struct ao2_container *c, void *newobj)
Definition: astobj2.c:531
int( ao2_callback_data_fn)(void *obj, void *arg, void *data, int flags)
Type of a generic callback function.
Definition: astobj2.h:643
int( ao2_callback_fn)(void *obj, void *arg, int flags)
Type of a generic callback function.
Definition: astobj2.h:631
struct bucket buckets[0]
Definition: astobj2.c:400
static struct ao2_container* internal_ao2_container_alloc ( struct ao2_container c,
const uint  n_buckets,
ao2_hash_fn hash_fn,
ao2_callback_fn cmp_fn 
)
static
static struct ao2_container* internal_ao2_container_alloc ( struct ao2_container c,
const unsigned int  n_buckets,
ao2_hash_fn hash_fn,
ao2_callback_fn cmp_fn 
)
static

Definition at line 420 of file astobj2.c.

References ast_atomic_fetchadd_int(), ao2_container::cmp_fn, ao2_container::hash_fn, hash_zero(), ao2_container::n_buckets, and ao2_container::version.

422 {
423  /* XXX maybe consistency check on arguments ? */
424  /* compute the container size */
425 
426  if (!c)
427  return NULL;
428 
429  c->version = 1; /* 0 is a reserved value here */
430  c->n_buckets = hash_fn ? n_buckets : 1;
431  c->hash_fn = hash_fn ? hash_fn : hash_zero;
432  c->cmp_fn = cmp_fn;
433 
434 #ifdef AO2_DEBUG
435  ast_atomic_fetchadd_int(&ao2.total_containers, 1);
436 #endif
437 
438  return c;
439 }
int n_buckets
Definition: astobj2.c:394
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
static int hash_zero(const void *user_obj, const int flags)
always zero hash function
Definition: astobj2.c:412
ao2_hash_fn * hash_fn
Definition: astobj2.c:392
ao2_hash_fn * hash_fn
Event type specific hash function.
Definition: event.c:165
ao2_callback_fn * cmp_fn
Definition: astobj2.c:393
static void * internal_ao2_iterator_next ( struct ao2_iterator a,
struct bucket_entry **  q 
)
static

Definition at line 846 of file astobj2.c.

References AO2_ITERATOR_DONTLOCK, AO2_ITERATOR_UNLINK, ao2_lock, ast_atomic_fetchadd_int(), ast_free, AST_LIST_NEXT, AST_LIST_REMOVE, AST_LIST_TRAVERSE, bucket_entry::astobj, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, ao2_container::elements, bucket_entry::entry, EXTERNAL_OBJ, ao2_iterator::flags, INTERNAL_OBJ(), ao2_container::n_buckets, ao2_iterator::obj, ao2_container::version, bucket_entry::version, and ao2_iterator::version.

Referenced by __ao2_iterator_next(), and __ao2_iterator_next_debug().

847 {
848  int lim;
849  struct bucket_entry *p = NULL;
850  void *ret = NULL;
851 
852  *q = NULL;
853 
854  if (INTERNAL_OBJ(a->c) == NULL)
855  return NULL;
856 
857  if (!(a->flags & AO2_ITERATOR_DONTLOCK))
858  ao2_lock(a->c);
859 
860  /* optimization. If the container is unchanged and
861  * we have a pointer, try follow it
862  */
863  if (a->c->version == a->c_version && (p = a->obj)) {
864  if ((p = AST_LIST_NEXT(p, entry)))
865  goto found;
866  /* nope, start from the next bucket */
867  a->bucket++;
868  a->version = 0;
869  a->obj = NULL;
870  }
871 
872  lim = a->c->n_buckets;
873 
874  /* Browse the buckets array, moving to the next
875  * buckets if we don't find the entry in the current one.
876  * Stop when we find an element with version number greater
877  * than the current one (we reset the version to 0 when we
878  * switch buckets).
879  */
880  for (; a->bucket < lim; a->bucket++, a->version = 0) {
881  /* scan the current bucket */
882  AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
883  if (p->version > a->version)
884  goto found;
885  }
886  }
887 
888 found:
889  if (p) {
890  ret = EXTERNAL_OBJ(p->astobj);
891  if (a->flags & AO2_ITERATOR_UNLINK) {
892  /* we are going to modify the container, so update version */
894  AST_LIST_REMOVE(&a->c->buckets[a->bucket], p, entry);
895  /* update number of elements */
897  a->version = 0;
898  a->obj = NULL;
899  a->c_version = a->c->version;
900  ast_free(p);
901  } else {
902  a->version = p->version;
903  a->obj = p;
904  a->c_version = a->c->version;
905  /* inc refcount of returned object */
906  *q = p;
907  }
908  }
909 
910  return ret;
911 }
struct astobj2 * astobj
Definition: astobj2.c:483
unsigned int c_version
Definition: astobj2.h:1061
int n_buckets
Definition: astobj2.c:394
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
struct bucket_entry::@222 entry
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:841
struct ao2_container * c
Definition: astobj2.h:1055
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
#define ao2_lock(a)
Definition: astobj2.h:488
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
#define EXTERNAL_OBJ(_p)
convert from a pointer _p to an astobj2 object
Definition: astobj2.c:148
void * obj
Definition: astobj2.h:1063
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_free(a)
Definition: astmm.h:97
int elements
Definition: astobj2.c:396
Definition: astobj2.c:480
int version
Definition: astobj2.c:482
unsigned int version
Definition: astobj2.h:1065
struct bucket buckets[0]
Definition: astobj2.c:400
static struct bucket_entry * internal_ao2_link ( struct ao2_container c,
void *  user_data,
const char *  file,
int  line,
const char *  func 
)
static

Definition at line 490 of file astobj2.c.

References ao2_lock, ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, bucket_entry::astobj, INTERNAL_OBJ(), OBJ_POINTER, and bucket_entry::version.

Referenced by __ao2_link(), and __ao2_link_debug().

491 {
492  int i;
493  /* create a new list entry */
494  struct bucket_entry *p;
495  struct astobj2 *obj = INTERNAL_OBJ(user_data);
496 
497  if (obj == NULL)
498  return NULL;
499 
500  if (INTERNAL_OBJ(c) == NULL)
501  return NULL;
502 
503  p = ast_calloc(1, sizeof(*p));
504  if (!p)
505  return NULL;
506 
507  i = abs(c->hash_fn(user_data, OBJ_POINTER));
508 
509  ao2_lock(c);
510  i %= c->n_buckets;
511  p->astobj = obj;
513  AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
515 
516  /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */
517  return p;
518 }
struct astobj2 * astobj
Definition: astobj2.c:483
int n_buckets
Definition: astobj2.c:394
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
#define ao2_lock(a)
Definition: astobj2.h:488
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
int elements
Definition: astobj2.c:396
void * user_data[0]
Definition: astobj2.c:66
#define ast_calloc(a, b)
Definition: astmm.h:82
Definition: astobj2.c:480
ao2_hash_fn * hash_fn
Definition: astobj2.c:392
int version
Definition: astobj2.c:482
struct bucket buckets[0]
Definition: astobj2.c:400
static int internal_ao2_ref ( void *  user_data,
const int  delta 
)
static

Definition at line 253 of file astobj2.c.

References ast_atomic_fetchadd_int(), ast_free, ast_log(), ast_mutex_destroy, __priv_data::data_size, __priv_data::destructor_fn, INTERNAL_OBJ(), __priv_data::lock, LOG_ERROR, astobj2::priv_data, and __priv_data::ref_counter.

Referenced by __ao2_ref(), and __ao2_ref_debug().

254 {
255  struct astobj2 *obj = INTERNAL_OBJ(user_data);
256  int current_value;
257  int ret;
258 
259  if (obj == NULL)
260  return -1;
261 
262  /* if delta is 0, just return the refcount */
263  if (delta == 0)
264  return (obj->priv_data.ref_counter);
265 
266  /* we modify with an atomic operation the reference counter */
267  ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
268  current_value = ret + delta;
269 
270 #ifdef AO2_DEBUG
271  ast_atomic_fetchadd_int(&ao2.total_refs, delta);
272 #endif
273 
274  /* this case must never happen */
275  if (current_value < 0)
276  ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);
277 
278  if (current_value <= 0) { /* last reference, destroy the object */
279  if (obj->priv_data.destructor_fn != NULL) {
281  }
282 
284 #ifdef AO2_DEBUG
285  ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
286  ast_atomic_fetchadd_int(&ao2.total_objects, -1);
287 #endif
288  /* for safety, zero-out the astobj2 header and also the
289  * first word of the user-data, which we make sure is always
290  * allocated. */
291  memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) );
292  ast_free(obj);
293  }
294 
295  return ret;
296 }
int ref_counter
Definition: astobj2.c:49
size_t data_size
Definition: astobj2.c:52
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return * the previous value of *p. This can be used to handle reference co...
Definition: lock.h:603
ao2_destructor_fn destructor_fn
Definition: astobj2.c:50
static struct astobj2 * INTERNAL_OBJ(void *user_data)
convert from a pointer _p to a user-defined object
Definition: astobj2.c:112
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_free(a)
Definition: astmm.h:97
void * user_data[0]
Definition: astobj2.c:66
struct __priv_data priv_data
Definition: astobj2.c:65
#define ast_mutex_destroy(a)
Definition: lock.h:154
ast_mutex_t lock
Definition: astobj2.c:48
static struct astobj2* INTERNAL_OBJ ( void *  user_data)
static

convert from a pointer _p to a user-defined object

Returns
the pointer to the astobj2 structure

Definition at line 112 of file astobj2.c.

References AO2_MAGIC, ast_assert, ast_log(), LOG_ERROR, __priv_data::magic, and astobj2::priv_data.

Referenced by __ao2_lock(), __ao2_ref_debug(), __ao2_trylock(), __ao2_unlink(), __ao2_unlink_debug(), __ao2_unlock(), ao2_object_get_lockaddr(), internal_ao2_callback(), internal_ao2_iterator_next(), internal_ao2_link(), and internal_ao2_ref().

113 {
114  struct astobj2 *p;
115 
116  if (!user_data) {
117  ast_log(LOG_ERROR, "user_data is NULL\n");
118  return NULL;
119  }
120 
121  p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
122  if (AO2_MAGIC != p->priv_data.magic) {
123  if (p->priv_data.magic) {
124  ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
126  } else {
128  "bad magic number for object %p. Object is likely destroyed.\n",
129  user_data);
130  }
131  ast_assert(0);
132  return NULL;
133  }
134 
135  return p;
136 }
#define ast_assert(a)
Definition: utils.h:738
#define AO2_MAGIC
Definition: astobj2.c:58
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void * user_data[0]
Definition: astobj2.c:66
struct __priv_data priv_data
Definition: astobj2.c:65
uint32_t magic
Definition: astobj2.c:55

Variable Documentation

FILE* ref_log
static

Definition at line 35 of file astobj2.c.