#include "asterisk.h"#include "asterisk/_private.h"#include "asterisk/astobj2.h"#include "asterisk/linkedlists.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 | ao2_lock_priv |
| struct | ao2_rwlock_priv |
| struct | astobj2 |
| struct | astobj2_lock |
| struct | astobj2_rwlock |
| struct | bucket |
| struct | bucket_entry |
Defines | |
| #define | AO2_MAGIC 0xa570b123 |
| #define | EXTERNAL_OBJ(_p) ((_p) == NULL ? NULL : (_p)->user_data) |
| convert from a pointer _p to an astobj2 object | |
| #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 | N1 20 |
Enumerations | |
| enum | ao2_callback_type { DEFAULT, WITH_DATA } |
Functions | |
| void * | __ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options) |
| void * | __ao2_alloc_debug (size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, const char *file, int line, const char *func, int ref_debug) |
| void * | __ao2_callback (struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg) |
| void * | __ao2_callback_data (struct ao2_container *c, enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data) |
| void * | __ao2_callback_data_debug (struct ao2_container *c, enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file, int line, const char *func) |
| void * | __ao2_callback_debug (struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line, const char *func) |
| void | __ao2_cleanup (void *obj) |
| void | __ao2_cleanup_debug (void *obj, const char *file, int line, const char *function) |
| struct ao2_container * | __ao2_container_alloc (unsigned int options, unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
| struct ao2_container * | __ao2_container_alloc_debug (unsigned int options, unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn, const char *tag, const char *file, int line, const char *func, int ref_debug) |
| struct ao2_container * | __ao2_container_clone (struct ao2_container *orig, enum search_flags flags) |
| Create a clone/copy of the given container. | |
| struct ao2_container * | __ao2_container_clone_debug (struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug) |
| void * | __ao2_find (struct ao2_container *c, const void *arg, enum search_flags flags) |
| void * | __ao2_find_debug (struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, const char *file, int line, const char *func) |
| void * | __ao2_global_obj_ref (struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name) |
| void | __ao2_global_obj_release (struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name) |
| void * | __ao2_global_obj_replace (struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name) |
| int | __ao2_global_obj_replace_unref (struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name) |
| void * | __ao2_iterator_next (struct ao2_iterator *iter) |
| void * | __ao2_iterator_next_debug (struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func) |
| void * | __ao2_link (struct ao2_container *c, void *obj_new, int flags) |
| void * | __ao2_link_debug (struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func) |
| 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. | |
| int | __ao2_ref (void *user_data, int delta) |
| int | __ao2_ref_debug (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) | |
| void * | __ao2_unlink (struct ao2_container *c, void *user_data, int flags) |
| void * | __ao2_unlink_debug (struct ao2_container *c, void *user_data, int flags, const char *tag, const char *file, int line, const char *func) |
| int | __ao2_unlock (void *user_data, const char *file, const char *func, int line, const char *var) |
| Unlock an object. | |
| static enum ao2_lock_req | adjust_lock (void *user_data, enum ao2_lock_req lock_how, int keep_stronger) |
| void | ao2_bt (void) |
| int | ao2_container_count (struct ao2_container *c) |
| Returns the number of elements in a container. | |
| int | ao2_container_dup (struct ao2_container *dest, struct ao2_container *src, enum search_flags flags) |
| Copy all object references in the src container into the dest container. | |
| void | ao2_iterator_cleanup (struct ao2_iterator *iter) |
| void | ao2_iterator_destroy (struct ao2_iterator *iter) |
| Destroy a container iterator. | |
| struct ao2_iterator | ao2_iterator_init (struct ao2_container *c, int flags) |
| Create an iterator for a container. | |
| int | ao2_match_by_addr (void *user_data, void *arg, int flags) |
| another convenience function is a callback that matches on address | |
| void * | ao2_object_get_lockaddr (void *user_data) |
| Return the mutex lock address of an object. | |
| 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 | |
| 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 | |
| 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 | dup_obj_cb (void *obj, void *arg, int flags) |
| static int | hash_zero (const void *user_obj, const int flags) |
| always zero hash function | |
| static void * | internal_ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *file, int line, const char *func) |
| static void * | internal_ao2_callback (struct ao2_container *c, enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, const char *tag, const char *file, int line, const char *func) |
| static struct ao2_container * | internal_ao2_container_alloc (struct ao2_container *c, unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
| static void * | internal_ao2_iterator_next (struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func) |
| static struct bucket_entry * | internal_ao2_link (struct ao2_container *c, void *user_data, int flags, const char *tag, const char *file, int line, const char *func) |
| static int | internal_ao2_ref (void *user_data, int delta, const char *file, int line, const char *func) |
| static struct astobj2 * | INTERNAL_OBJ (void *user_data) |
| convert from a pointer _p to a user-defined object | |
Variables | |
| static FILE * | ref_log |
| #define AO2_MAGIC 0xa570b123 |
Definition at line 63 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
Definition at line 179 of file astobj2.c.
Referenced by internal_ao2_alloc(), internal_ao2_callback(), and internal_ao2_iterator_next().
| #define INTERNAL_OBJ_MUTEX | ( | user_data | ) | ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock))) |
Definition at line 132 of file astobj2.c.
Referenced by __ao2_lock(), __ao2_trylock(), __ao2_unlock(), ao2_object_get_lockaddr(), and internal_ao2_ref().
| #define INTERNAL_OBJ_RWLOCK | ( | user_data | ) | ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock))) |
Definition at line 135 of file astobj2.c.
Referenced by __ao2_lock(), __ao2_trylock(), __ao2_unlock(), adjust_lock(), and internal_ao2_ref().
| #define N1 20 |
Referenced by ao2_bt().
| enum ao2_callback_type |
| void* __ao2_alloc | ( | size_t | data_size, |
| ao2_destructor_fn | destructor_fn, | ||
| unsigned int | options | ||
| ) |
Definition at line 638 of file astobj2.c.
References internal_ao2_alloc().
Referenced by __ao2_container_alloc().
{
return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__);
}
| void* __ao2_alloc_debug | ( | size_t | data_size, |
| ao2_destructor_fn | destructor_fn, | ||
| unsigned int | options, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func, | ||
| int | ref_debug | ||
| ) |
Definition at line 619 of file astobj2.c.
References ast_get_tid(), and internal_ao2_alloc().
Referenced by __ao2_container_alloc_debug(), __ast_channel_internal_alloc(), and _moh_class_malloc().
{
/* allocation */
void *obj;
if ((obj = internal_ao2_alloc(data_size, destructor_fn, options, file, line, func)) == NULL) {
return NULL;
}
if (ref_log) {
fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n", obj, ast_get_tid(), file, line, func, tag);
fflush(ref_log);
}
/* return a pointer to the user data */
return obj;
}
| void* __ao2_callback | ( | struct ao2_container * | c, |
| enum search_flags | flags, | ||
| ao2_callback_fn * | cb_fn, | ||
| void * | arg | ||
| ) |
Definition at line 1202 of file astobj2.c.
References DEFAULT, and internal_ao2_callback().
Referenced by __ao2_find(), __ao2_unlink(), ao2_container_dup(), and container_destruct().
{
return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
}
| void* __ao2_callback_data | ( | struct ao2_container * | c, |
| enum search_flags | flags, | ||
| ao2_callback_data_fn * | cb_fn, | ||
| void * | arg, | ||
| void * | data | ||
| ) |
Definition at line 1215 of file astobj2.c.
References internal_ao2_callback(), and WITH_DATA.
{
return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
}
| void* __ao2_callback_data_debug | ( | struct ao2_container * | c, |
| enum search_flags | flags, | ||
| ao2_callback_data_fn * | cb_fn, | ||
| void * | arg, | ||
| void * | data, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) |
Definition at line 1208 of file astobj2.c.
References internal_ao2_callback(), and WITH_DATA.
{
return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, func);
}
| void* __ao2_callback_debug | ( | struct ao2_container * | c, |
| enum search_flags | flags, | ||
| ao2_callback_fn * | cb_fn, | ||
| void * | arg, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) |
Definition at line 1195 of file astobj2.c.
References DEFAULT, and internal_ao2_callback().
Referenced by __ao2_find_debug(), __ao2_unlink_debug(), and container_destruct_debug().
{
return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, func);
}
| void __ao2_cleanup | ( | void * | obj | ) |
| void __ao2_cleanup_debug | ( | void * | obj, |
| const char * | file, | ||
| int | line, | ||
| const char * | function | ||
| ) |
Definition at line 1548 of file astobj2.c.
References __ao2_ref_debug().
{
if (obj) {
__ao2_ref_debug(obj, -1, "ao2_cleanup", file, line, function);
}
}
| struct ao2_container* __ao2_container_alloc | ( | unsigned int | options, |
| unsigned int | n_buckets, | ||
| ao2_hash_fn * | hash_fn, | ||
| ao2_callback_fn * | cmp_fn | ||
| ) | [read] |
Definition at line 849 of file astobj2.c.
References __ao2_alloc(), container_destruct(), and internal_ao2_container_alloc().
Referenced by __ao2_container_clone(), and internal_ao2_callback().
{
/* XXX maybe consistency check on arguments ? */
/* compute the container size */
const unsigned int num_buckets = hash_fn ? n_buckets : 1;
size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
struct ao2_container *c = __ao2_alloc(container_size, container_destruct, options);
return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
}
| struct ao2_container* __ao2_container_alloc_debug | ( | unsigned int | options, |
| unsigned int | n_buckets, | ||
| ao2_hash_fn * | hash_fn, | ||
| ao2_callback_fn * | cmp_fn, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func, | ||
| int | ref_debug | ||
| ) | [read] |
Definition at line 836 of file astobj2.c.
References __ao2_alloc_debug(), container_destruct(), container_destruct_debug(), and internal_ao2_container_alloc().
Referenced by __ao2_container_clone_debug().
{
/* XXX maybe consistency check on arguments ? */
/* compute the container size */
unsigned int num_buckets = hash_fn ? n_buckets : 1;
size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
struct ao2_container *c = __ao2_alloc_debug(container_size, ref_debug ? container_destruct_debug : container_destruct, options, tag, file, line, func, ref_debug);
return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
}
| struct ao2_container* __ao2_container_clone | ( | struct ao2_container * | orig, |
| enum search_flags | flags | ||
| ) | [read] |
Create a clone/copy of the given container.
| orig | Container to copy all object references from. |
| flags | OBJ_NOLOCK if a lock is already held on the container. |
| Clone | container on success. |
| NULL | on error. |
Definition at line 1475 of file astobj2.c.
References __ao2_container_alloc(), __ao2_ref(), ao2_container_dup(), ao2_unlock, ao2_wrlock, ao2_container::cmp_fn, ao2_container::hash_fn, INTERNAL_OBJ(), ao2_container::n_buckets, OBJ_NOLOCK, __priv_data::options, and astobj2::priv_data.
{
struct ao2_container *clone;
struct astobj2 *orig_obj;
unsigned int options;
int failed;
orig_obj = INTERNAL_OBJ(orig);
if (!orig_obj) {
return NULL;
}
options = orig_obj->priv_data.options;
/* Create the clone container with the same properties as the original. */
clone = __ao2_container_alloc(options, orig->n_buckets, orig->hash_fn, orig->cmp_fn);
if (!clone) {
return NULL;
}
if (flags & OBJ_NOLOCK) {
ao2_wrlock(clone);
}
failed = ao2_container_dup(clone, orig, flags);
if (flags & OBJ_NOLOCK) {
ao2_unlock(clone);
}
if (failed) {
/* Object copy into the clone container failed. */
__ao2_ref(clone, -1);
clone = NULL;
}
return clone;
}
| struct ao2_container* __ao2_container_clone_debug | ( | struct ao2_container * | orig, |
| enum search_flags | flags, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func, | ||
| int | ref_debug | ||
| ) | [read] |
Definition at line 1509 of file astobj2.c.
References __ao2_container_alloc_debug(), __ao2_ref(), __ao2_ref_debug(), ao2_container_dup(), ao2_unlock, ao2_wrlock, ao2_container::cmp_fn, ao2_container::hash_fn, INTERNAL_OBJ(), ao2_container::n_buckets, OBJ_NOLOCK, __priv_data::options, and astobj2::priv_data.
{
struct ao2_container *clone;
struct astobj2 *orig_obj;
unsigned int options;
int failed;
orig_obj = INTERNAL_OBJ(orig);
if (!orig_obj) {
return NULL;
}
options = orig_obj->priv_data.options;
/* Create the clone container with the same properties as the original. */
clone = __ao2_container_alloc_debug(options, orig->n_buckets, orig->hash_fn,
orig->cmp_fn, tag, file, line, func, ref_debug);
if (!clone) {
return NULL;
}
if (flags & OBJ_NOLOCK) {
ao2_wrlock(clone);
}
failed = ao2_container_dup(clone, orig, flags);
if (flags & OBJ_NOLOCK) {
ao2_unlock(clone);
}
if (failed) {
/* Object copy into the clone container failed. */
if (ref_debug) {
__ao2_ref_debug(clone, -1, tag, file, line, func);
} else {
__ao2_ref(clone, -1);
}
clone = NULL;
}
return clone;
}
| void* __ao2_find | ( | struct ao2_container * | c, |
| const void * | arg, | ||
| enum search_flags | flags | ||
| ) |
Definition at line 1232 of file astobj2.c.
References __ao2_callback(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
{
void *arged = (void *) arg;/* Done to avoid compiler const warning */
return __ao2_callback(c, flags, c->cmp_fn, arged);
}
| void* __ao2_find_debug | ( | struct ao2_container * | c, |
| const void * | arg, | ||
| enum search_flags | flags, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) |
the find function just invokes the default callback with some reasonable flags.
Definition at line 1224 of file astobj2.c.
References __ao2_callback_debug(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
{
void *arged = (void *) arg;/* Done to avoid compiler const warning */
return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
}
| void* __ao2_global_obj_ref | ( | struct ao2_global_obj * | holder, |
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func, | ||
| const char * | name | ||
| ) |
Definition at line 714 of file astobj2.c.
References __ao2_ref(), __ao2_ref_debug(), __ast_rwlock_rdlock(), __ast_rwlock_unlock(), ast_log(), ao2_global_obj::lock, LOG_ERROR, and ao2_global_obj::obj.
{
void *obj;
if (!holder) {
/* For sanity */
ast_log(LOG_ERROR, "Must be called with a global object!\n");
return NULL;
}
if (__ast_rwlock_rdlock(file, line, func, &holder->lock, name)) {
/* Could not get the read lock. */
return NULL;
}
obj = holder->obj;
if (obj) {
if (tag) {
__ao2_ref_debug(obj, +1, tag, file, line, func);
} else {
__ao2_ref(obj, +1);
}
}
__ast_rwlock_unlock(file, line, func, &holder->lock, name);
return obj;
}
| void __ao2_global_obj_release | ( | struct ao2_global_obj * | holder, |
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func, | ||
| const char * | name | ||
| ) |
Definition at line 644 of file astobj2.c.
References __ao2_ref(), __ao2_ref_debug(), __ast_rwlock_unlock(), __ast_rwlock_wrlock(), ast_log(), ao2_global_obj::lock, LOG_ERROR, and ao2_global_obj::obj.
{
if (!holder) {
/* For sanity */
ast_log(LOG_ERROR, "Must be called with a global object!\n");
return;
}
if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
/* Could not get the write lock. */
return;
}
/* Release the held ao2 object. */
if (holder->obj) {
if (tag) {
__ao2_ref_debug(holder->obj, -1, tag, file, line, func);
} else {
__ao2_ref(holder->obj, -1);
}
holder->obj = NULL;
}
__ast_rwlock_unlock(file, line, func, &holder->lock, name);
}
| void* __ao2_global_obj_replace | ( | struct ao2_global_obj * | holder, |
| void * | obj, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func, | ||
| const char * | name | ||
| ) |
Definition at line 669 of file astobj2.c.
References __ao2_ref(), __ao2_ref_debug(), __ast_rwlock_unlock(), __ast_rwlock_wrlock(), ast_log(), ao2_global_obj::lock, LOG_ERROR, and ao2_global_obj::obj.
Referenced by __ao2_global_obj_replace_unref().
{
void *obj_old;
if (!holder) {
/* For sanity */
ast_log(LOG_ERROR, "Must be called with a global object!\n");
return NULL;
}
if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
/* Could not get the write lock. */
return NULL;
}
if (obj) {
if (tag) {
__ao2_ref_debug(obj, +1, tag, file, line, func);
} else {
__ao2_ref(obj, +1);
}
}
obj_old = holder->obj;
holder->obj = obj;
__ast_rwlock_unlock(file, line, func, &holder->lock, name);
return obj_old;
}
| int __ao2_global_obj_replace_unref | ( | struct ao2_global_obj * | holder, |
| void * | obj, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func, | ||
| const char * | name | ||
| ) |
Definition at line 698 of file astobj2.c.
References __ao2_global_obj_replace(), __ao2_ref(), and __ao2_ref_debug().
{
void *obj_old;
obj_old = __ao2_global_obj_replace(holder, obj, tag, file, line, func, name);
if (obj_old) {
if (tag) {
__ao2_ref_debug(obj_old, -1, tag, file, line, func);
} else {
__ao2_ref(obj_old, -1);
}
return 1;
}
return 0;
}
| void* __ao2_iterator_next | ( | struct ao2_iterator * | iter | ) |
Definition at line 1369 of file astobj2.c.
References internal_ao2_iterator_next().
{
return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
}
| void* __ao2_iterator_next_debug | ( | struct ao2_iterator * | iter, |
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) |
Definition at line 1364 of file astobj2.c.
References internal_ao2_iterator_next().
{
return internal_ao2_iterator_next(iter, tag, file, line, func);
}
| void* __ao2_link | ( | struct ao2_container * | c, |
| void * | obj_new, | ||
| int | flags | ||
| ) |
Definition at line 928 of file astobj2.c.
References internal_ao2_link().
Referenced by dup_obj_cb(), and internal_ao2_callback().
{
return internal_ao2_link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
}
| void* __ao2_link_debug | ( | struct ao2_container * | c, |
| void * | obj_new, | ||
| int | flags, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) |
Definition at line 923 of file astobj2.c.
References internal_ao2_link().
Referenced by internal_ao2_callback().
{
return internal_ao2_link(c, obj_new, flags, tag, file, line, func);
}
| 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.
| a | A pointer to the object we want to lock. |
Definition at line 181 of file astobj2.c.
References __ast_pthread_mutex_lock(), __ast_rwlock_rdlock(), __ast_rwlock_wrlock(), __LOG_ERROR, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ast_atomic_fetchadd_int(), ast_log(), INTERNAL_OBJ(), INTERNAL_OBJ_MUTEX, INTERNAL_OBJ_RWLOCK, ao2_rwlock_priv::lock, ao2_lock_priv::lock, astobj2_lock::mutex, ao2_rwlock_priv::num_lockers, __priv_data::options, astobj2::priv_data, and astobj2_rwlock::rwlock.
Referenced by _ast_bridge_lock().
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
int res = 0;
if (obj == NULL) {
return -1;
}
switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
case AO2_ALLOC_OPT_LOCK_MUTEX:
obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
#ifdef AO2_DEBUG
if (!res) {
ast_atomic_fetchadd_int(&ao2.total_locked, 1);
}
#endif
break;
case AO2_ALLOC_OPT_LOCK_RWLOCK:
obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
switch (lock_how) {
case AO2_LOCK_REQ_MUTEX:
case AO2_LOCK_REQ_WRLOCK:
res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
if (!res) {
ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif
}
break;
case AO2_LOCK_REQ_RDLOCK:
res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
if (!res) {
ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif
}
break;
}
break;
case AO2_ALLOC_OPT_LOCK_NOLOCK:
/* The ao2 object has no lock. */
break;
default:
ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
user_data);
return -1;
}
return res;
}
| int __ao2_ref | ( | void * | user_data, |
| int | delta | ||
| ) |
Definition at line 539 of file astobj2.c.
References internal_ao2_ref().
Referenced by __ao2_container_clone(), __ao2_container_clone_debug(), __ao2_global_obj_ref(), __ao2_global_obj_release(), __ao2_global_obj_replace(), __ao2_global_obj_replace_unref(), ao2_container_dup(), cd_cb(), internal_ao2_callback(), internal_ao2_iterator_next(), and internal_ao2_link().
{
return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__);
}
| int __ao2_ref_debug | ( | void * | user_data, |
| int | delta, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) |
Definition at line 517 of file astobj2.c.
References ast_get_tid(), internal_ao2_ref(), INTERNAL_OBJ(), astobj2::priv_data, and __priv_data::ref_counter.
Referenced by __ao2_cleanup_debug(), __ao2_container_clone_debug(), __ao2_global_obj_ref(), __ao2_global_obj_release(), __ao2_global_obj_replace(), __ao2_global_obj_replace_unref(), cd_cb_debug(), dialog_ref_debug(), dialog_unref_debug(), internal_ao2_callback(), internal_ao2_iterator_next(), and internal_ao2_link().
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
if (ref_log && user_data) {
if (obj && obj->priv_data.ref_counter + delta == 0) {
fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n", user_data, delta, ast_get_tid(), file, line, func, tag);
fflush(ref_log);
} else if (delta != 0) {
fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data, (delta < 0 ? "" : "+"),
delta, ast_get_tid(), file, line, func, obj ? obj->priv_data.ref_counter : -1, tag);
fflush(ref_log);
}
}
if (obj == NULL) {
return -1;
}
return internal_ao2_ref(user_data, delta, file, line, func);
}
| 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)
| a | A pointer to the object we want to lock. |
Definition at line 287 of file astobj2.c.
References __ast_pthread_mutex_trylock(), __ast_rwlock_tryrdlock(), __ast_rwlock_trywrlock(), __LOG_ERROR, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ast_atomic_fetchadd_int(), ast_log(), INTERNAL_OBJ(), INTERNAL_OBJ_MUTEX, INTERNAL_OBJ_RWLOCK, ao2_rwlock_priv::lock, ao2_lock_priv::lock, astobj2_lock::mutex, ao2_rwlock_priv::num_lockers, __priv_data::options, astobj2::priv_data, and astobj2_rwlock::rwlock.
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
int res = 0;
if (obj == NULL) {
return -1;
}
switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
case AO2_ALLOC_OPT_LOCK_MUTEX:
obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
#ifdef AO2_DEBUG
if (!res) {
ast_atomic_fetchadd_int(&ao2.total_locked, 1);
}
#endif
break;
case AO2_ALLOC_OPT_LOCK_RWLOCK:
obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
switch (lock_how) {
case AO2_LOCK_REQ_MUTEX:
case AO2_LOCK_REQ_WRLOCK:
res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
if (!res) {
ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif
}
break;
case AO2_LOCK_REQ_RDLOCK:
res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
if (!res) {
ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif
}
break;
}
break;
case AO2_ALLOC_OPT_LOCK_NOLOCK:
/* The ao2 object has no lock. */
return 0;
default:
ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
user_data);
return -1;
}
return res;
}
| void* __ao2_unlink | ( | struct ao2_container * | c, |
| void * | user_data, | ||
| int | flags | ||
| ) |
Definition at line 958 of file astobj2.c.
References __ao2_callback(), ao2_match_by_addr(), INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
{
if (INTERNAL_OBJ(user_data) == NULL) { /* safety check on the argument */
return NULL;
}
flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
__ao2_callback(c, flags, ao2_match_by_addr, user_data);
return NULL;
}
| void* __ao2_unlink_debug | ( | struct ao2_container * | c, |
| void * | user_data, | ||
| int | flags, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) |
Definition at line 945 of file astobj2.c.
References __ao2_callback_debug(), ao2_match_by_addr(), INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
{
if (INTERNAL_OBJ(user_data) == NULL) { /* safety check on the argument */
return NULL;
}
flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
__ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
return NULL;
}
| int __ao2_unlock | ( | void * | a, |
| const char * | file, | ||
| const char * | func, | ||
| int | line, | ||
| const char * | var | ||
| ) |
Unlock an object.
| a | A pointer to the object we want unlock. |
Definition at line 238 of file astobj2.c.
References __ast_pthread_mutex_unlock(), __ast_rwlock_unlock(), __LOG_ERROR, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_RWLOCK, ast_atomic_fetchadd_int(), ast_log(), INTERNAL_OBJ(), INTERNAL_OBJ_MUTEX, INTERNAL_OBJ_RWLOCK, ao2_rwlock_priv::lock, ao2_lock_priv::lock, astobj2_lock::mutex, ao2_rwlock_priv::num_lockers, __priv_data::options, astobj2::priv_data, and astobj2_rwlock::rwlock.
Referenced by _ast_bridge_unlock().
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
int res = 0;
int current_value;
if (obj == NULL) {
return -1;
}
switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
case AO2_ALLOC_OPT_LOCK_MUTEX:
obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
#ifdef AO2_DEBUG
if (!res) {
ast_atomic_fetchadd_int(&ao2.total_locked, -1);
}
#endif
break;
case AO2_ALLOC_OPT_LOCK_RWLOCK:
obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
if (current_value < 0) {
/* It was a WRLOCK that we are unlocking. Fix the count. */
ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
}
res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
#ifdef AO2_DEBUG
if (!res) {
ast_atomic_fetchadd_int(&ao2.total_locked, -1);
}
#endif
break;
case AO2_ALLOC_OPT_LOCK_NOLOCK:
/* The ao2 object has no lock. */
break;
default:
ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
user_data);
res = -1;
break;
}
return res;
}
| static enum ao2_lock_req adjust_lock | ( | void * | user_data, |
| enum ao2_lock_req | lock_how, | ||
| int | keep_stronger | ||
| ) | [static] |
Definition at line 362 of file astobj2.c.
References AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ao2_rdlock, ao2_unlock, ao2_wrlock, ast_log(), INTERNAL_OBJ(), INTERNAL_OBJ_RWLOCK, LOG_ERROR, ao2_rwlock_priv::num_lockers, __priv_data::options, astobj2::priv_data, and astobj2_rwlock::rwlock.
Referenced by internal_ao2_callback(), internal_ao2_iterator_next(), and internal_ao2_link().
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
struct astobj2_rwlock *obj_rwlock;
enum ao2_lock_req orig_lock;
switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
case AO2_ALLOC_OPT_LOCK_RWLOCK:
obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
if (obj_rwlock->rwlock.num_lockers < 0) {
orig_lock = AO2_LOCK_REQ_WRLOCK;
} else {
orig_lock = AO2_LOCK_REQ_RDLOCK;
}
switch (lock_how) {
case AO2_LOCK_REQ_MUTEX:
lock_how = AO2_LOCK_REQ_WRLOCK;
/* Fall through */
case AO2_LOCK_REQ_WRLOCK:
if (lock_how != orig_lock) {
/* Switch from read lock to write lock. */
ao2_unlock(user_data);
ao2_wrlock(user_data);
}
break;
case AO2_LOCK_REQ_RDLOCK:
if (!keep_stronger && lock_how != orig_lock) {
/* Switch from write lock to read lock. */
ao2_unlock(user_data);
ao2_rdlock(user_data);
}
break;
}
break;
default:
ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
/* Fall through */
case AO2_ALLOC_OPT_LOCK_NOLOCK:
case AO2_ALLOC_OPT_LOCK_MUTEX:
orig_lock = AO2_LOCK_REQ_MUTEX;
break;
}
return orig_lock;
}
| void ao2_bt | ( | void | ) |
Definition at line 115 of file astobj2.c.
References ast_bt_get_symbols(), ast_std_free(), ast_verbose(), and N1.
{
int c, i;
#define N1 20
void *addresses[N1];
char **strings;
c = backtrace(addresses, N1);
strings = ast_bt_get_symbols(addresses,c);
ast_verbose("backtrace returned: %d\n", c);
for(i = 0; i < c; i++) {
ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
}
ast_std_free(strings);
}
| int ao2_container_count | ( | struct ao2_container * | c | ) |
Returns the number of elements in a container.
return the number of elements in the container
Definition at line 864 of file astobj2.c.
References ao2_container::elements.
Referenced by __ast_data_register(), __ast_manager_event_multichan(), __queues_show(), _sip_show_peers(), action_confbridgekick(), action_confbridgelist(), action_confbridgelistrooms(), action_confbridgesetsinglevideosrc(), action_confbridgestartrecord(), action_confbridgestoprecord(), action_lock_unlock_helper(), action_mute_unmute_helper(), ast_active_channels(), ast_data_search_match(), ast_format_cap_get_type(), ast_format_cap_identical(), ast_format_cap_is_empty(), ast_format_cap_joint(), ast_get_namedgroups(), ast_merge_contexts_and_delete(), ast_namedgroups_intersect(), ast_srtp_unprotect(), ast_tone_zone_count(), build_format_list_array(), calc_metric(), cc_cli_output_status(), cleanup(), cli_fax_show_sessions(), cli_tps_report(), data_odbc_provider_handler(), data_provider_release(), data_provider_release_all(), do_timing(), endelm(), func_confbridge_info(), get_device_state_causing_channels(), get_unused_callno(), handle_cli_iax2_show_callno_limits(), handle_manager_show_events(), handle_show_hint(), handle_show_hints(), handle_statechange(), hints_data_provider_get(), joint_copy_helper(), locals_show(), lock_broker(), match_filter(), meetme_data_provider_get(), member_add_to_queue(), pthread_timer_open(), queue_exec(), queue_function_mem_read(), queues_data_provider_get_helper(), sla_in_use(), try_calling(), unload_module(), and xmpp_show_clients().
{
return c->elements;
}
| int ao2_container_dup | ( | struct ao2_container * | dest, |
| struct ao2_container * | src, | ||
| enum search_flags | flags | ||
| ) |
Copy all object references in the src container into the dest container.
| dest | Container to copy src object references into. |
| src | Container to copy all object references from. |
| flags | OBJ_NOLOCK if a lock is already held on both containers. Otherwise, the src container is locked first. |
| 0 | on success. |
| -1 | on error. |
Definition at line 1448 of file astobj2.c.
References __ao2_callback(), __ao2_ref(), ao2_rdlock, ao2_unlock, ao2_wrlock, dup_obj_cb(), OBJ_MULTIPLE, OBJ_NODATA, OBJ_NOLOCK, and OBJ_UNLINK.
Referenced by __ao2_container_clone(), and __ao2_container_clone_debug().
{
void *obj;
int res = 0;
if (!(flags & OBJ_NOLOCK)) {
ao2_rdlock(src);
ao2_wrlock(dest);
}
obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
if (obj) {
/* Failed to put this obj into the dest container. */
__ao2_ref(obj, -1);
/* Remove all items from the dest container. */
__ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
NULL);
res = -1;
}
if (!(flags & OBJ_NOLOCK)) {
ao2_unlock(dest);
ao2_unlock(src);
}
return res;
}
| void ao2_iterator_cleanup | ( | struct ao2_iterator * | iter | ) |
Definition at line 1562 of file astobj2.c.
References ao2_iterator_destroy().
{
if (iter) {
ao2_iterator_destroy(iter);
}
}
| void ao2_iterator_destroy | ( | struct ao2_iterator * | iter | ) |
Destroy a container iterator.
destroy an iterator
Definition at line 1257 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(), aco_set_defaults(), action_confbridgelistrooms(), action_meetmelist(), add_ice_to_sdp(), alias_show(), ao2_iterator_cleanup(), ast_channel_iterator_destroy(), ast_data_iterator_end(), ast_data_search_match(), ast_format_cap_get_type(), ast_format_cap_has_joint(), ast_format_cap_has_type(), ast_format_cap_identical(), ast_format_cap_iter_end(), ast_format_cap_joint(), ast_format_cap_to_old_bitfield(), ast_merge_contexts_and_delete(), ast_msg_var_iterator_destroy(), ast_pickup_find_by_group(), ast_print_namedgroups(), 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(), build_format_list_array(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_display_named_acl_list(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_confbridge_name(), 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(), config_hook_exec(), 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(), delete_profiles(), delete_routes(), delete_users(), 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_ringing_channel(), find_session(), find_session_by_nonce(), free_members(), get_device_state_causing_channels(), get_member_status(), handle_cli_confbridge_list(), 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_manager_show_event(), handle_manager_show_events(), handle_parkedcalls(), handle_presencechange(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_show_named_acl_cmd(), handle_show_routes(), handle_showmanconn(), handle_skel_show_games(), handle_skel_show_levels(), handle_statechange(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), jingle_add_google_candidates_to_transport(), jingle_add_ice_udp_candidates_to_transport(), jingle_request(), joint_copy_helper(), kill_duplicate_offers(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), manager_sip_peer_status(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), msg_func_write(), num_available_members(), peers_data_provider_get(), poke_all_peers(), pp_each_user_helper(), prune_peers(), prune_users(), purge_sessions(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), rt_handle_member_record(), set_member_paused(), set_member_value(), sip_keepalive_all_peers(), 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(), users_data_provider_get(), xmpp_pubsub_create_affiliations(), xmpp_show_buddies(), and xmpp_show_clients().
| struct ao2_iterator ao2_iterator_init | ( | struct ao2_container * | c, |
| int | flags | ||
| ) | [read] |
Create an iterator for a container.
initialize an iterator so we start from the first object
Definition at line 1242 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(), aco_set_defaults(), action_confbridgelistrooms(), action_meetmelist(), add_ice_to_sdp(), alias_show(), ast_channel_iterator_all_new(), ast_data_iterator_init(), ast_data_search_match(), ast_format_cap_get_type(), ast_format_cap_has_joint(), ast_format_cap_has_type(), ast_format_cap_identical(), ast_format_cap_iter_start(), ast_format_cap_joint(), ast_format_cap_to_old_bitfield(), ast_merge_contexts_and_delete(), ast_msg_var_iterator_init(), ast_pickup_find_by_group(), ast_print_namedgroups(), ast_srtp_unprotect(), ast_tone_zone_iterator_init(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), build_format_list_array(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_display_named_acl_list(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_confbridge_name(), 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(), config_hook_exec(), 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(), delete_profiles(), delete_routes(), delete_users(), destroy_pvts(), dialgroup_read(), do_parking_thread(), dump_queue_members(), extension_state_cb(), fax_session_tab_complete(), find_queue_by_name_rt(), find_ringing_channel(), find_session(), find_session_by_nonce(), free_members(), get_device_state_causing_channels(), get_member_status(), handle_cli_confbridge_list(), 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_manager_show_event(), handle_parkedcalls(), handle_presencechange(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_show_named_acl_cmd(), handle_show_routes(), handle_showmanconn(), handle_skel_show_games(), handle_skel_show_levels(), handle_statechange(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), internal_ao2_callback(), jingle_add_google_candidates_to_transport(), jingle_add_ice_udp_candidates_to_transport(), jingle_request(), joint_copy_helper(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_parkinglot_list(), manager_queues_status(), manager_queues_summary(), manager_sip_peer_status(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), msg_func_write(), num_available_members(), peers_data_provider_get(), poke_all_peers(), pp_each_user_helper(), prune_peers(), prune_users(), purge_sessions(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), rt_handle_member_record(), set_member_paused(), set_member_value(), sip_keepalive_all_peers(), 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(), users_data_provider_get(), xmpp_pubsub_create_affiliations(), xmpp_show_buddies(), and xmpp_show_clients().
{
struct ao2_iterator a = {
.c = c,
.flags = flags
};
ao2_ref(c, +1);
return a;
}
| int ao2_match_by_addr | ( | void * | user_data, |
| void * | arg, | ||
| int | flags | ||
| ) |
another convenience function is a callback that matches on address
A common ao2_callback is one that matches by address.
Definition at line 936 of file astobj2.c.
References CMP_MATCH, and CMP_STOP.
Referenced by __ao2_unlink(), __ao2_unlink_debug(), load_module(), and load_odbc_config().
| void* ao2_object_get_lockaddr | ( | void * | obj | ) |
Return the mutex lock address of an object.
| [in] | obj | A pointer to the object we want. |
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.
Definition at line 408 of file astobj2.c.
References AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, INTERNAL_OBJ(), INTERNAL_OBJ_MUTEX, ao2_lock_priv::lock, astobj2_lock::mutex, __priv_data::options, and astobj2::priv_data.
Referenced by bridge_channel_join_multithreaded(), bridge_channel_join_singlethreaded(), and db_sync_thread().
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
struct astobj2_lock *obj_mutex;
if (obj == NULL) {
return NULL;
}
switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
case AO2_ALLOC_OPT_LOCK_MUTEX:
obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
return &obj_mutex->mutex.lock;
default:
break;
}
return NULL;
}
| static void astobj2_cleanup | ( | void | ) | [static] |
Definition at line 1714 of file astobj2.c.
References ARRAY_LEN, and ast_cli_unregister_multiple().
Referenced by astobj2_init().
{
#ifdef AO2_DEBUG
ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
#endif
#ifdef REF_DEBUG
fclose(ref_log);
ref_log = NULL;
#endif
}
| int astobj2_init | ( | void | ) |
Provided by astobj2.c
Definition at line 1726 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().
{
#ifdef REF_DEBUG
char ref_filename[1024];
#endif
#ifdef REF_DEBUG
snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
ref_log = fopen(ref_filename, "w");
if (!ref_log) {
ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
}
#endif
#ifdef AO2_DEBUG
ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
#endif
ast_register_atexit(astobj2_cleanup);
return 0;
}
| static int cb_true | ( | void * | user_data, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
special callback that matches all
Definition at line 973 of file astobj2.c.
References CMP_MATCH.
Referenced by internal_ao2_callback().
{
return CMP_MATCH;
}
| 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 981 of file astobj2.c.
References CMP_MATCH.
Referenced by internal_ao2_callback().
{
return CMP_MATCH;
}
| static int cd_cb | ( | void * | obj, |
| void * | arg, | ||
| int | flag | ||
| ) | [static] |
Definition at line 1377 of file astobj2.c.
References __ao2_ref().
Referenced by container_destruct().
{
__ao2_ref(obj, -1);
return 0;
}
| static int cd_cb_debug | ( | void * | obj, |
| void * | arg, | ||
| int | flag | ||
| ) | [static] |
Definition at line 1383 of file astobj2.c.
References __ao2_ref_debug().
Referenced by container_destruct_debug().
{
__ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__);
return 0;
}
| static void container_destruct | ( | void * | c | ) | [static] |
Definition at line 1389 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().
{
struct ao2_container *c = _c;
int i;
__ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
for (i = 0; i < c->n_buckets; i++) {
struct bucket_entry *current;
while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
ast_free(current);
}
}
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_containers, -1);
#endif
}
| static void container_destruct_debug | ( | void * | c | ) | [static] |
Definition at line 1409 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().
{
struct ao2_container *c = _c;
int i;
__ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
for (i = 0; i < c->n_buckets; i++) {
struct bucket_entry *current;
while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
ast_free(current);
}
}
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_containers, -1);
#endif
}
| static int dup_obj_cb | ( | void * | obj, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
Definition at line 1441 of file astobj2.c.
References __ao2_link(), CMP_MATCH, CMP_STOP, and OBJ_NOLOCK.
Referenced by ao2_container_dup().
{
struct ao2_container *dest = arg;
return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
}
| 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.
Definition at line 806 of file astobj2.c.
Referenced by internal_ao2_container_alloc().
{
return 0;
}
| static void* internal_ao2_alloc | ( | size_t | data_size, |
| ao2_destructor_fn | destructor_fn, | ||
| unsigned int | options, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) | [static] |
Definition at line 544 of file astobj2.c.
References __ast_calloc(), __AST_DEBUG_MALLOC, __LOG_DEBUG, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_MAGIC, ast_atomic_fetchadd_int(), ast_calloc, ast_log(), ast_mutex_init, ast_rwlock_init, __priv_data::data_size, __priv_data::destructor_fn, EXTERNAL_OBJ, ao2_rwlock_priv::lock, ao2_lock_priv::lock, __priv_data::magic, astobj2_lock::mutex, __priv_data::options, astobj2::priv_data, astobj2_rwlock::priv_data, astobj2_lock::priv_data, __priv_data::ref_counter, and astobj2_rwlock::rwlock.
Referenced by __ao2_alloc(), and __ao2_alloc_debug().
{
/* allocation */
struct astobj2 *obj;
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
if (data_size < sizeof(void *)) {
/*
* We always alloc at least the size of a void *,
* for debugging purposes.
*/
data_size = sizeof(void *);
}
switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
case AO2_ALLOC_OPT_LOCK_MUTEX:
#if defined(__AST_DEBUG_MALLOC)
obj_mutex = __ast_calloc(1, sizeof(*obj_mutex) + data_size, file, line, func);
#else
obj_mutex = ast_calloc(1, sizeof(*obj_mutex) + data_size);
#endif
if (obj_mutex == NULL) {
return NULL;
}
ast_mutex_init(&obj_mutex->mutex.lock);
obj = (struct astobj2 *) &obj_mutex->priv_data;
break;
case AO2_ALLOC_OPT_LOCK_RWLOCK:
#if defined(__AST_DEBUG_MALLOC)
obj_rwlock = __ast_calloc(1, sizeof(*obj_rwlock) + data_size, file, line, func);
#else
obj_rwlock = ast_calloc(1, sizeof(*obj_rwlock) + data_size);
#endif
if (obj_rwlock == NULL) {
return NULL;
}
ast_rwlock_init(&obj_rwlock->rwlock.lock);
obj = (struct astobj2 *) &obj_rwlock->priv_data;
break;
case AO2_ALLOC_OPT_LOCK_NOLOCK:
#if defined(__AST_DEBUG_MALLOC)
obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, func);
#else
obj = ast_calloc(1, sizeof(*obj) + data_size);
#endif
if (obj == NULL) {
return NULL;
}
break;
default:
/* Invalid option value. */
ast_log(__LOG_DEBUG, file, line, func, "Invalid lock option requested\n");
return NULL;
}
/* Initialize common ao2 values. */
obj->priv_data.ref_counter = 1;
obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */
obj->priv_data.data_size = data_size;
obj->priv_data.options = options;
obj->priv_data.magic = AO2_MAGIC;
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_objects, 1);
ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
ast_atomic_fetchadd_int(&ao2.total_refs, 1);
#endif
/* return a pointer to the user data */
return EXTERNAL_OBJ(obj);
}
| static void* internal_ao2_callback | ( | struct ao2_container * | c, |
| enum search_flags | flags, | ||
| void * | cb_fn, | ||
| void * | arg, | ||
| void * | data, | ||
| enum ao2_callback_type | type, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) | [static] |
Browse the container using different stategies accoding the flags.
Definition at line 994 of file astobj2.c.
References __ao2_container_alloc(), __ao2_link(), __ao2_link_debug(), __ao2_ref(), __ao2_ref_debug(), adjust_lock(), AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_iterator_init(), AO2_ITERATOR_MALLOCD, AO2_ITERATOR_UNLINK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ao2_rdlock, ao2_ref, ao2_unlock, ao2_wrlock, 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_KEY, OBJ_MULTIPLE, OBJ_NODATA, OBJ_NOLOCK, 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().
{
int i, start, last; /* search boundaries */
enum ao2_lock_req orig_lock;
void *ret = NULL;
ao2_callback_fn *cb_default = NULL;
ao2_callback_data_fn *cb_withdata = NULL;
struct ao2_container *multi_container = NULL;
struct ao2_iterator *multi_iterator = NULL;
if (INTERNAL_OBJ(c) == NULL) { /* safety check on the argument */
return NULL;
}
/*
* This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
* turned off. This if statement checks for the special condition
* where multiple items may need to be returned.
*/
if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
/* we need to return an ao2_iterator with the results,
* as there could be more than one. the iterator will
* hold the only reference to a container that has all the
* matching objects linked into it, so when the iterator
* is destroyed, the container will be automatically
* destroyed as well.
*/
multi_container = __ao2_container_alloc(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
if (!multi_container) {
return NULL;
}
if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
ao2_ref(multi_container, -1);
return NULL;
}
}
/* override the match function if necessary */
if (cb_fn == NULL) { /* if NULL, match everything */
if (type == WITH_DATA) {
cb_withdata = cb_true_data;
} else {
cb_default = cb_true;
}
} else {
/* We do this here to avoid the per object casting penalty (even though
that is probably optimized away anyway). */
if (type == WITH_DATA) {
cb_withdata = cb_fn;
} else {
cb_default = cb_fn;
}
}
/*
* XXX this can be optimized.
* If we have a hash function and lookup by pointer,
* run the hash function. Otherwise, scan the whole container
* (this only for the time being. We need to optimize this.)
*/
if ((flags & (OBJ_POINTER | OBJ_KEY))) {
/* we know hash can handle this case */
start = i = c->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)) % c->n_buckets;
} else {
/* don't know, let's scan all buckets */
start = i = -1; /* XXX this must be fixed later. */
}
/* determine the search boundaries: i..last-1 */
if (i < 0) {
start = i = 0;
last = c->n_buckets;
} else if ((flags & OBJ_CONTINUE)) {
last = c->n_buckets;
} else {
last = i + 1;
}
/* avoid modifications to the content */
if (flags & OBJ_NOLOCK) {
if (flags & OBJ_UNLINK) {
orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
} else {
orig_lock = adjust_lock(c, AO2_LOCK_REQ_RDLOCK, 1);
}
} else {
orig_lock = AO2_LOCK_REQ_MUTEX;
if (flags & OBJ_UNLINK) {
ao2_wrlock(c);
} else {
ao2_rdlock(c);
}
}
for (; i < last ; i++) {
/* scan the list with prev-cur pointers */
struct bucket_entry *cur;
AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
int match = (CMP_MATCH | CMP_STOP);
if (type == WITH_DATA) {
match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
} else {
match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
}
/* we found the object, performing operations according flags */
if (match == 0) { /* no match, no stop, continue */
continue;
} else if (match == CMP_STOP) { /* no match but stop, we are done */
i = last;
break;
}
/* we have a match (CMP_MATCH) here */
if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */
/* it is important to handle this case before the unlink */
ret = EXTERNAL_OBJ(cur->astobj);
if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
if (tag) {
__ao2_ref_debug(ret, 1, tag, file, line, func);
} else {
__ao2_ref(ret, 1);
}
}
}
/* If we are in OBJ_MULTIPLE mode and OBJ_NODATA is off,
* link the object into the container that will hold the results.
*/
if (ret && (multi_container != NULL)) {
if (tag) {
__ao2_link_debug(multi_container, ret, flags, tag, file, line, func);
} else {
__ao2_link(multi_container, ret, flags);
}
ret = NULL;
}
if (flags & OBJ_UNLINK) { /* must unlink */
/* we are going to modify the container, so update version */
ast_atomic_fetchadd_int(&c->version, 1);
AST_LIST_REMOVE_CURRENT(entry);
/* update number of elements */
ast_atomic_fetchadd_int(&c->elements, -1);
/* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container
* must be decremented.
* - When unlinking with OBJ_MULTIPLE the ref from the original container
* must be decremented regardless if OBJ_NODATA is used. This is because the result is
* returned in a new container that already holds its own ref for the object. If the ref
* from the original container is not accounted for here a memory leak occurs. */
if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) {
if (tag)
__ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, func);
else
__ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
}
ast_free(cur); /* free the link record */
}
if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
/* We found our only (or last) match, so force an exit from
the outside loop. */
i = last;
break;
}
}
AST_LIST_TRAVERSE_SAFE_END;
if (ret) {
break;
}
if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
/* Move to the beginning to ensure we check every bucket */
i = -1;
last = start;
}
}
if (flags & OBJ_NOLOCK) {
adjust_lock(c, orig_lock, 0);
} else {
ao2_unlock(c);
}
/* if multi_container was created, we are returning multiple objects */
if (multi_container != NULL) {
*multi_iterator = ao2_iterator_init(multi_container,
AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
ao2_ref(multi_container, -1);
return multi_iterator;
} else {
return ret;
}
}
| static struct ao2_container* internal_ao2_container_alloc | ( | struct ao2_container * | c, |
| unsigned int | n_buckets, | ||
| ao2_hash_fn * | hash_fn, | ||
| ao2_callback_fn * | cmp_fn | ||
| ) | [static, read] |
Definition at line 814 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.
Referenced by __ao2_container_alloc(), and __ao2_container_alloc_debug().
{
/* XXX maybe consistency check on arguments ? */
/* compute the container size */
if (!c) {
return NULL;
}
c->version = 1; /* 0 is a reserved value here */
c->n_buckets = hash_fn ? n_buckets : 1;
c->hash_fn = hash_fn ? hash_fn : hash_zero;
c->cmp_fn = cmp_fn;
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_containers, 1);
#endif
return c;
}
| static void* internal_ao2_iterator_next | ( | struct ao2_iterator * | iter, |
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) | [static] |
Definition at line 1270 of file astobj2.c.
References __ao2_ref(), __ao2_ref_debug(), adjust_lock(), AO2_ITERATOR_DONTLOCK, AO2_ITERATOR_UNLINK, AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_RDLOCK, AO2_LOCK_REQ_WRLOCK, ao2_rdlock, ao2_unlock, ao2_wrlock, 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, bucket_entry::version, ao2_iterator::version, and ao2_container::version.
Referenced by __ao2_iterator_next(), and __ao2_iterator_next_debug().
{
int lim;
enum ao2_lock_req orig_lock;
struct bucket_entry *p = NULL;
void *ret;
if (INTERNAL_OBJ(iter->c) == NULL) {
return NULL;
}
if (iter->flags & AO2_ITERATOR_DONTLOCK) {
if (iter->flags & AO2_ITERATOR_UNLINK) {
orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_WRLOCK, 1);
} else {
orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
}
} else {
orig_lock = AO2_LOCK_REQ_MUTEX;
if (iter->flags & AO2_ITERATOR_UNLINK) {
ao2_wrlock(iter->c);
} else {
ao2_rdlock(iter->c);
}
}
/* optimization. If the container is unchanged and
* we have a pointer, try follow it
*/
if (iter->c->version == iter->c_version && (p = iter->obj)) {
if ((p = AST_LIST_NEXT(p, entry))) {
goto found;
}
/* nope, start from the next bucket */
iter->bucket++;
iter->version = 0;
iter->obj = NULL;
}
lim = iter->c->n_buckets;
/* Browse the buckets array, moving to the next
* buckets if we don't find the entry in the current one.
* Stop when we find an element with version number greater
* than the current one (we reset the version to 0 when we
* switch buckets).
*/
for (; iter->bucket < lim; iter->bucket++, iter->version = 0) {
/* scan the current bucket */
AST_LIST_TRAVERSE(&iter->c->buckets[iter->bucket], p, entry) {
if (p->version > iter->version) {
goto found;
}
}
}
found:
if (p) {
ret = EXTERNAL_OBJ(p->astobj);
if (iter->flags & AO2_ITERATOR_UNLINK) {
/* we are going to modify the container, so update version */
ast_atomic_fetchadd_int(&iter->c->version, 1);
AST_LIST_REMOVE(&iter->c->buckets[iter->bucket], p, entry);
/* update number of elements */
ast_atomic_fetchadd_int(&iter->c->elements, -1);
iter->version = 0;
iter->obj = NULL;
iter->c_version = iter->c->version;
ast_free(p);
} else {
iter->version = p->version;
iter->obj = p;
iter->c_version = iter->c->version;
/* inc refcount of returned object */
if (tag) {
__ao2_ref_debug(ret, 1, tag, file, line, func);
} else {
__ao2_ref(ret, 1);
}
}
} else {
ret = NULL;
}
if (iter->flags & AO2_ITERATOR_DONTLOCK) {
adjust_lock(iter->c, orig_lock, 0);
} else {
ao2_unlock(iter->c);
}
return ret;
}
| static struct bucket_entry* internal_ao2_link | ( | struct ao2_container * | c, |
| void * | user_data, | ||
| int | flags, | ||
| const char * | tag, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) | [static, read] |
Definition at line 872 of file astobj2.c.
References __ao2_ref(), __ao2_ref_debug(), adjust_lock(), AO2_LOCK_REQ_MUTEX, AO2_LOCK_REQ_WRLOCK, ao2_unlock, ao2_wrlock, ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, bucket_entry::astobj, ao2_container::buckets, ao2_container::elements, bucket_entry::entry, ao2_container::hash_fn, INTERNAL_OBJ(), ao2_container::n_buckets, OBJ_NOLOCK, OBJ_POINTER, ao2_container::version, and bucket_entry::version.
Referenced by __ao2_link(), and __ao2_link_debug().
{
int i;
enum ao2_lock_req orig_lock;
/* create a new list entry */
struct bucket_entry *p;
struct astobj2 *obj = INTERNAL_OBJ(user_data);
if (obj == NULL) {
return NULL;
}
if (INTERNAL_OBJ(c) == NULL) {
return NULL;
}
p = ast_calloc(1, sizeof(*p));
if (!p) {
return NULL;
}
i = abs(c->hash_fn(user_data, OBJ_POINTER));
if (flags & OBJ_NOLOCK) {
orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
} else {
ao2_wrlock(c);
orig_lock = AO2_LOCK_REQ_MUTEX;
}
i %= c->n_buckets;
p->astobj = obj;
p->version = ast_atomic_fetchadd_int(&c->version, 1);
AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
ast_atomic_fetchadd_int(&c->elements, 1);
if (tag) {
__ao2_ref_debug(user_data, +1, tag, file, line, func);
} else {
__ao2_ref(user_data, +1);
}
if (flags & OBJ_NOLOCK) {
adjust_lock(c, orig_lock, 0);
} else {
ao2_unlock(c);
}
return p;
}
| static int internal_ao2_ref | ( | void * | user_data, |
| int | delta, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) | [static] |
Definition at line 428 of file astobj2.c.
References __LOG_ERROR, AO2_ALLOC_OPT_LOCK_MASK, AO2_ALLOC_OPT_LOCK_MUTEX, AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_ALLOC_OPT_LOCK_RWLOCK, ast_atomic_fetchadd_int(), ast_free, ast_log(), ast_mutex_destroy, ast_rwlock_destroy, __priv_data::data_size, __priv_data::destructor_fn, INTERNAL_OBJ(), INTERNAL_OBJ_MUTEX, INTERNAL_OBJ_RWLOCK, ao2_rwlock_priv::lock, ao2_lock_priv::lock, astobj2_lock::mutex, __priv_data::options, astobj2::priv_data, __priv_data::ref_counter, and astobj2_rwlock::rwlock.
Referenced by __ao2_ref(), and __ao2_ref_debug().
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
int current_value;
int ret;
if (obj == NULL) {
return -1;
}
/* if delta is 0, just return the refcount */
if (delta == 0) {
return obj->priv_data.ref_counter;
}
/* we modify with an atomic operation the reference counter */
ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
current_value = ret + delta;
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_refs, delta);
#endif
if (0 < current_value) {
/* The object still lives. */
return ret;
}
/* this case must never happen */
if (current_value < 0) {
ast_log(__LOG_ERROR, file, line, func,
"Invalid refcount %d on ao2 object %p\n", current_value, user_data);
}
/* last reference, destroy the object */
if (obj->priv_data.destructor_fn != NULL) {
obj->priv_data.destructor_fn(user_data);
}
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
ast_atomic_fetchadd_int(&ao2.total_objects, -1);
#endif
switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
case AO2_ALLOC_OPT_LOCK_MUTEX:
obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
ast_mutex_destroy(&obj_mutex->mutex.lock);
/*
* For safety, zero-out the astobj2_lock header and also the
* first word of the user-data, which we make sure is always
* allocated.
*/
memset(obj_mutex, '\0', sizeof(*obj_mutex) + sizeof(void *) );
ast_free(obj_mutex);
break;
case AO2_ALLOC_OPT_LOCK_RWLOCK:
obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
ast_rwlock_destroy(&obj_rwlock->rwlock.lock);
/*
* For safety, zero-out the astobj2_rwlock header and also the
* first word of the user-data, which we make sure is always
* allocated.
*/
memset(obj_rwlock, '\0', sizeof(*obj_rwlock) + sizeof(void *) );
ast_free(obj_rwlock);
break;
case AO2_ALLOC_OPT_LOCK_NOLOCK:
/*
* For safety, zero-out the astobj2 header and also the first
* word of the user-data, which we make sure is always
* allocated.
*/
memset(obj, '\0', sizeof(*obj) + sizeof(void *) );
ast_free(obj);
break;
default:
ast_log(__LOG_ERROR, file, line, func,
"Invalid lock option on ao2 object %p\n", user_data);
break;
}
return ret;
}
| static struct astobj2* INTERNAL_OBJ | ( | void * | user_data | ) | [static, read] |
convert from a pointer _p to a user-defined object
Definition at line 143 of file astobj2.c.
References AO2_MAGIC, ast_assert, ast_log(), LOG_ERROR, __priv_data::magic, and astobj2::priv_data.
Referenced by __ao2_container_clone(), __ao2_container_clone_debug(), __ao2_lock(), __ao2_ref_debug(), __ao2_trylock(), __ao2_unlink(), __ao2_unlink_debug(), __ao2_unlock(), adjust_lock(), ao2_object_get_lockaddr(), internal_ao2_callback(), internal_ao2_iterator_next(), internal_ao2_link(), and internal_ao2_ref().
{
struct astobj2 *p;
if (!user_data) {
ast_log(LOG_ERROR, "user_data is NULL\n");
return NULL;
}
p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
if (AO2_MAGIC != p->priv_data.magic) {
if (p->priv_data.magic) {
ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
p->priv_data.magic, user_data);
} else {
ast_log(LOG_ERROR,
"bad magic number for object %p. Object is likely destroyed.\n",
user_data);
}
ast_assert(0);
return NULL;
}
return p;
}