#include "asterisk.h"#include "asterisk/_private.h"#include "asterisk/astobj2.h"#include "asterisk/utils.h"#include "asterisk/cli.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 |
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 | N1 20 |
| #define | REF_FILE "/tmp/refs" |
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. | |
| int | __ao2_ref (void *user_data, const int delta) |
| int | __ao2_ref_debug (void *user_data, const int delta, char *tag, 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) | |
| 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. | |
| void | ao2_bt (void) |
| int | ao2_container_count (struct ao2_container *c) |
| Returns the number of elements in a container. | |
| void | ao2_iterator_destroy (struct ao2_iterator *i) |
| 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 *obj) |
| Return the lock address of an object. | |
| 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 | 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, 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_container * | internal_ao2_container_alloc (struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
| 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 void * | internal_ao2_iterator_next (struct ao2_iterator *a, struct bucket_entry **q) |
| static struct bucket_entry * | internal_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 astobj2 * | INTERNAL_OBJ (void *user_data) |
| convert from a pointer _p to a user-defined object | |
| #define AO2_MAGIC 0xa570b123 |
Definition at line 51 of file astobj2.c.
Referenced by INTERNAL_OBJ(), and internal_ao2_alloc().
| #define EXTERNAL_OBJ | ( | _p | ) | ((_p) == NULL ? NULL : (_p)->user_data) |
convert from a pointer _p to an astobj2 object
Definition at line 133 of file astobj2.c.
Referenced by internal_ao2_alloc(), internal_ao2_callback(), and internal_ao2_iterator_next().
| #define N1 20 |
Referenced by ao2_bt().
| #define REF_FILE "/tmp/refs" |
Definition at line 28 of file astobj2.c.
Referenced by __ao2_ref_debug(), and __ao2_alloc_debug().
| enum ao2_callback_type |
| void* __ao2_alloc | ( | size_t | data_size, |
| ao2_destructor_fn | destructor_fn | ||
| ) |
Definition at line 338 of file astobj2.c.
References internal_ao2_alloc().
Referenced by __ao2_container_alloc().
{
return internal_ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__);
}
| 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 317 of file astobj2.c.
References REF_FILE, and internal_ao2_alloc().
Referenced by __ao2_container_alloc_debug(), __ast_channel_alloc_ap(), ast_dummy_channel_alloc(), and _moh_class_malloc().
{
/* allocation */
void *obj;
FILE *refo = ref_debug ? fopen(REF_FILE,"a") : NULL;
if ((obj = internal_ao2_alloc(data_size, destructor_fn, file, line, funcname)) == NULL) {
fclose(refo);
return NULL;
}
if (refo) {
fprintf(refo, "%p =1 %s:%d:%s (%s)\n", obj, file, line, funcname, tag);
fclose(refo);
}
/* return a pointer to the user data */
return obj;
}
| void* __ao2_callback | ( | struct ao2_container * | c, |
| const enum search_flags | flags, | ||
| ao2_callback_fn * | cb_fn, | ||
| void * | arg | ||
| ) |
Definition at line 766 of file astobj2.c.
References internal_ao2_callback(), and DEFAULT.
Referenced by __ao2_unlink(), __ao2_find(), 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, |
| const enum search_flags | flags, | ||
| ao2_callback_data_fn * | cb_fn, | ||
| void * | arg, | ||
| void * | data | ||
| ) |
Definition at line 780 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, |
| 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 772 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, 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 | ||
| ) |
Definition at line 758 of file astobj2.c.
References internal_ao2_callback(), and DEFAULT.
Referenced by __ao2_unlink_debug(), __ao2_find_debug(), and container_destruct_debug().
{
return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
}
| struct ao2_container* __ao2_container_alloc | ( | const unsigned int | n_buckets, |
| ao2_hash_fn * | hash_fn, | ||
| ao2_callback_fn * | cmp_fn | ||
| ) | [read] |
Definition at line 438 of file astobj2.c.
References __ao2_alloc(), container_destruct(), and internal_ao2_container_alloc().
Referenced by 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);
return internal_ao2_container_alloc(c, num_buckets, hash_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 | ||
| ) | [read] |
Definition at line 425 of file astobj2.c.
References __ao2_alloc_debug(), container_destruct_debug(), and internal_ao2_container_alloc().
{
/* 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_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug);
return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
}
| void* __ao2_find | ( | struct ao2_container * | c, |
| void * | arg, | ||
| enum search_flags | flags | ||
| ) |
Definition at line 794 of file astobj2.c.
References __ao2_callback(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
{
return __ao2_callback(c, flags, c->cmp_fn, arg);
}
| 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 789 of file astobj2.c.
References __ao2_callback_debug(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
{
return __ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
}
| void* __ao2_iterator_next | ( | struct ao2_iterator * | a | ) |
Definition at line 915 of file astobj2.c.
References internal_ao2_iterator_next(), __ao2_ref(), ao2_iterator::flags, AO2_ITERATOR_DONTLOCK, ao2_unlock, and ao2_iterator::c.
{
struct bucket_entry *p = NULL;
void *ret = NULL;
ret = internal_ao2_iterator_next(a, &p);
if (p) {
/* inc refcount of returned object */
__ao2_ref(ret, 1);
}
if (!(a->flags & AO2_ITERATOR_DONTLOCK))
ao2_unlock(a->c);
return ret;
}
| void* __ao2_iterator_next_debug | ( | struct ao2_iterator * | a, |
| char * | tag, | ||
| char * | file, | ||
| int | line, | ||
| const char * | funcname | ||
| ) |
Definition at line 897 of file astobj2.c.
References internal_ao2_iterator_next(), __ao2_ref_debug(), ao2_iterator::flags, AO2_ITERATOR_DONTLOCK, ao2_unlock, and ao2_iterator::c.
{
struct bucket_entry *p;
void *ret = NULL;
ret = internal_ao2_iterator_next(a, &p);
if (p) {
/* inc refcount of returned object */
__ao2_ref_debug(ret, 1, tag, file, line, funcname);
}
if (!(a->flags & AO2_ITERATOR_DONTLOCK))
ao2_unlock(a->c);
return ret;
}
| void* __ao2_link | ( | struct ao2_container * | c, |
| void * | user_data | ||
| ) |
Definition at line 515 of file astobj2.c.
References internal_ao2_link(), __ao2_ref(), and ao2_unlock.
Referenced by internal_ao2_callback().
{
struct bucket_entry *p = internal_ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);
if (p) {
__ao2_ref(user_data, +1);
ao2_unlock(c);
}
return p;
}
| void* __ao2_link_debug | ( | struct ao2_container * | c, |
| void * | user_data, | ||
| char * | tag, | ||
| char * | file, | ||
| int | line, | ||
| const char * | funcname | ||
| ) |
Definition at line 504 of file astobj2.c.
References internal_ao2_link(), __ao2_ref_debug(), and ao2_unlock.
Referenced by internal_ao2_callback().
{
struct bucket_entry *p = internal_ao2_link(c, user_data, file, line, funcname);
if (p) {
__ao2_ref_debug(user_data, +1, tag, file, line, funcname);
ao2_unlock(c);
}
return p;
}
| int __ao2_lock | ( | void * | a, |
| 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 146 of file astobj2.c.
References INTERNAL_OBJ(), ast_atomic_fetchadd_int(), __ast_pthread_mutex_lock(), astobj2::priv_data, and __priv_data::lock.
{
struct astobj2 *p = INTERNAL_OBJ(user_data);
if (p == NULL)
return -1;
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif
return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock);
}
| int __ao2_ref | ( | void * | user_data, |
| const int | delta | ||
| ) |
Definition at line 225 of file astobj2.c.
References INTERNAL_OBJ(), and internal_ao2_ref().
Referenced by __ao2_link(), internal_ao2_callback(), __ao2_iterator_next(), and cd_cb().
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
if (obj == NULL)
return -1;
return internal_ao2_ref(user_data, delta);
}
| int __ao2_ref_debug | ( | void * | user_data, |
| const int | delta, | ||
| char * | tag, | ||
| char * | file, | ||
| int | line, | ||
| const char * | funcname | ||
| ) |
Definition at line 205 of file astobj2.c.
References INTERNAL_OBJ(), REF_FILE, astobj2::priv_data, __priv_data::ref_counter, __priv_data::destructor_fn, and internal_ao2_ref().
Referenced by __ao2_link_debug(), internal_ao2_callback(), __ao2_iterator_next_debug(), cd_cb_debug(), dialog_ref_debug(), and dialog_unref_debug().
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
if (obj == NULL)
return -1;
if (delta != 0) {
FILE *refo = fopen(REF_FILE,"a");
fprintf(refo, "%p %s%d %s:%d:%s (%s) [@%d]\n", user_data, (delta<0? "":"+"), delta, file, line, funcname, tag, obj ? obj->priv_data.ref_counter : -1);
fclose(refo);
}
if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */
FILE *refo = fopen(REF_FILE,"a");
fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag);
fclose(refo);
}
return internal_ao2_ref(user_data, delta);
}
| int __ao2_trylock | ( | void * | a, |
| 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 174 of file astobj2.c.
References INTERNAL_OBJ(), __ast_pthread_mutex_trylock(), astobj2::priv_data, __priv_data::lock, and ast_atomic_fetchadd_int().
{
struct astobj2 *p = INTERNAL_OBJ(user_data);
int ret;
if (p == NULL)
return -1;
ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock);
#ifdef AO2_DEBUG
if (!ret)
ast_atomic_fetchadd_int(&ao2.total_locked, 1);
#endif
return ret;
}
| void* __ao2_unlink | ( | struct ao2_container * | c, |
| void * | user_data | ||
| ) |
Definition at line 549 of file astobj2.c.
References INTERNAL_OBJ(), __ao2_callback(), OBJ_UNLINK, OBJ_POINTER, OBJ_NODATA, and ao2_match_by_addr.
{
if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */
return NULL;
__ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
return NULL;
}
| void* __ao2_unlink_debug | ( | struct ao2_container * | c, |
| void * | user_data, | ||
| char * | tag, | ||
| char * | file, | ||
| int | line, | ||
| const char * | funcname | ||
| ) |
Definition at line 538 of file astobj2.c.
References INTERNAL_OBJ(), __ao2_callback_debug(), OBJ_UNLINK, OBJ_POINTER, OBJ_NODATA, and ao2_match_by_addr.
{
if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */
return NULL;
__ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname);
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 160 of file astobj2.c.
References INTERNAL_OBJ(), ast_atomic_fetchadd_int(), __ast_pthread_mutex_unlock(), astobj2::priv_data, and __priv_data::lock.
{
struct astobj2 *p = INTERNAL_OBJ(user_data);
if (p == NULL)
return -1;
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_locked, -1);
#endif
return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock);
}
| void ao2_bt | ( | void | ) |
Definition at line 83 of file astobj2.c.
References N1, ast_bt_get_symbols(), ast_verbose(), and free.
{
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]);
}
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 454 of file astobj2.c.
References ao2_container::elements.
Referenced by meetme_data_provider_get(), __queues_show(), cc_cli_output_status(), handle_cli_iax2_show_callno_limits(), get_unused_callno(), locals_show(), _sip_show_peers(), ast_active_channels(), data_provider_release(), data_provider_release_all(), __ast_data_register(), ast_data_search_match(), lock_broker(), unload_module(), ast_tone_zone_count(), match_filter(), __ast_manager_event_multichan(), handle_show_hints(), handle_show_hint(), ast_merge_contexts_and_delete(), hints_data_provider_get(), cleanup(), endelm(), cli_fax_show_sessions(), data_odbc_provider_handler(), ast_srtp_unprotect(), pthread_timer_open(), do_timing(), and cli_tps_report().
{
return c->elements;
}
| void ao2_iterator_destroy | ( | struct ao2_iterator * | i | ) |
Destroy a container iterator.
destroy an iterator
Definition at line 817 of file astobj2.c.
References ao2_ref, ao2_iterator::c, ao2_iterator::flags, AO2_ITERATOR_MALLOCD, and ast_free.
Referenced by complete_meetmecmd(), meetme_show_cmd(), conf_queue_dtmf(), conf_run(), action_meetmelist(), get_member_status(), handle_statechange(), extension_state_cb(), clear_queue(), rt_handle_member_record(), free_members(), find_queue_by_name_rt(), update_realtime_members(), num_available_members(), compare_weight(), update_queue(), try_calling(), interface_exists(), dump_queue_members(), set_member_paused(), set_member_penalty(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), clear_stats(), __queues_show(), complete_queue(), manager_queues_summary(), manager_queues_status(), complete_queue_remove_member(), queues_data_provider_get(), unload_module(), kill_duplicate_offers(), complete_core_id(), cli_list_devices(), cli_console_active(), destroy_pvts(), stop_streams(), iax2_getpeername(), handle_cli_iax2_show_callno_limits(), complete_iax2_peers(), iax2_getpeertrunk(), handle_cli_iax2_show_users(), __iax2_show_peers(), complete_iax2_unregister(), manager_iax2_show_peer_list(), check_access(), authenticate_reply(), prune_users(), prune_peers(), poke_all_peers(), peers_data_provider_get(), users_data_provider_get(), local_devicestate(), locals_show(), manager_optimize_away(), find_call(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), _sip_show_peers(), sip_prune_realtime(), complete_sip_user(), complete_sipch(), complete_sip_peer(), complete_sip_registered_peer(), sip_show_channel(), sip_show_history(), sip_poke_all_peers(), ast_channel_iterator_destroy(), data_provider_release_all(), __ast_data_search_cmp_structure(), ast_data_search_match(), data_filter_find(), data_result_generate_node(), data_get_xml_add_child(), ast_data_iterator_end(), __data_result_print_cli(), data_provider_print_cli(), data_result_manager_output(), do_parking_thread(), build_dialplan_useage_map(), handle_feature_show(), handle_parkedcalls(), manager_parking_status(), dialgroup_read(), handle_showmanconn(), authenticate(), purge_sessions(), __ast_manager_event_multichan(), find_session(), find_session_by_nonce(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), handle_show_hints(), complete_core_show_hint(), handle_show_hint(), hints_data_provider_get(), calendar_query_exec(), handle_show_calendars(), handle_show_calendar(), alias_show(), fax_session_tab_complete(), cli_fax_show_sessions(), moh_rescan_files(), handle_cli_moh_show_files(), handle_cli_moh_show_classes(), handle_cli_odbc_show(), reload(), delete_users(), delete_routes(), delete_profiles(), pp_each_user_helper(), handle_show_routes(), and ast_srtp_unprotect().
| 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 802 of file astobj2.c.
References ao2_iterator::c, ao2_iterator::flags, and ao2_ref.
Referenced by complete_meetmecmd(), meetme_show_cmd(), conf_queue_dtmf(), conf_run(), action_meetmelist(), get_member_status(), handle_statechange(), extension_state_cb(), clear_queue(), rt_handle_member_record(), free_members(), find_queue_by_name_rt(), update_realtime_members(), num_available_members(), compare_weight(), update_queue(), try_calling(), interface_exists(), dump_queue_members(), set_member_paused(), set_member_penalty(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), clear_stats(), __queues_show(), complete_queue(), manager_queues_summary(), manager_queues_status(), complete_queue_remove_member(), queues_data_provider_get_helper(), queues_data_provider_get(), unload_module(), internal_ao2_callback(), complete_core_id(), cli_list_devices(), cli_console_active(), destroy_pvts(), stop_streams(), iax2_getpeername(), handle_cli_iax2_show_callno_limits(), complete_iax2_peers(), iax2_getpeertrunk(), handle_cli_iax2_show_users(), __iax2_show_peers(), complete_iax2_unregister(), manager_iax2_show_peer_list(), check_access(), authenticate_reply(), prune_users(), prune_peers(), poke_all_peers(), peers_data_provider_get(), users_data_provider_get(), local_devicestate(), locals_show(), manager_optimize_away(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), _sip_show_peers(), sip_prune_realtime(), complete_sip_user(), complete_sipch(), complete_sip_peer(), complete_sip_registered_peer(), sip_show_channel(), sip_show_history(), sip_poke_all_peers(), ast_channel_iterator_all_new(), data_provider_release_all(), __ast_data_search_cmp_structure(), ast_data_search_match(), data_filter_find(), data_result_generate_node(), data_get_xml_add_child(), ast_data_iterator_init(), __data_result_print_cli(), data_provider_print_cli(), data_result_manager_output(), do_parking_thread(), build_dialplan_useage_map(), handle_feature_show(), handle_parkedcalls(), manager_parking_status(), dialgroup_read(), ast_tone_zone_iterator_init(), complete_country(), handle_showmanconn(), authenticate(), purge_sessions(), __ast_manager_event_multichan(), find_session(), find_session_by_nonce(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), handle_show_hints(), complete_core_show_hint(), handle_show_hint(), ast_merge_contexts_and_delete(), hints_data_provider_get(), calendar_query_exec(), handle_show_calendars(), handle_show_calendar(), alias_show(), fax_session_tab_complete(), cli_fax_show_sessions(), moh_rescan_files(), handle_cli_moh_show_files(), handle_cli_moh_show_classes(), handle_cli_odbc_show(), data_odbc_provider_handler(), reload(), delete_users(), delete_routes(), delete_profiles(), pp_each_user_helper(), handle_show_routes(), ast_srtp_unprotect(), tps_taskprocessor_tab_complete(), and cli_tps_report().
{
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 | ||
| ) |
| void* ao2_object_get_lockaddr | ( | void * | obj | ) |
Return the 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 190 of file astobj2.c.
References INTERNAL_OBJ(), astobj2::priv_data, and __priv_data::lock.
{
struct astobj2 *p = INTERNAL_OBJ(obj);
if (p == NULL)
return NULL;
return &p->priv_data.lock;
}
| int astobj2_init | ( | void | ) |
Provided by astobj2.c
Definition at line 1121 of file astobj2.c.
References ast_cli_register_multiple(), and ARRAY_LEN.
Referenced by main().
{
#ifdef AO2_DEBUG
ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
#endif
return 0;
}
| static int cb_true | ( | void * | user_data, |
| void * | arg, | ||
| int | flags | ||
| ) | [static] |
special callback that matches all
Definition at line 562 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 570 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 936 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 942 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 948 of file astobj2.c.
References __ao2_callback(), OBJ_UNLINK, cd_cb(), ao2_container::n_buckets, AST_LIST_REMOVE_HEAD, ao2_container::buckets, bucket_entry::entry, ast_free, and ast_atomic_fetchadd_int().
Referenced by __ao2_container_alloc().
{
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 968 of file astobj2.c.
References __ao2_callback_debug(), OBJ_UNLINK, cd_cb_debug(), ao2_container::n_buckets, AST_LIST_REMOVE_HEAD, ao2_container::buckets, bucket_entry::entry, ast_free, and ast_atomic_fetchadd_int().
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 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 396 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, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | funcname | ||
| ) | [static] |
Definition at line 284 of file astobj2.c.
References __ast_calloc(), ast_calloc, ast_mutex_init, astobj2::priv_data, __priv_data::lock, __priv_data::magic, AO2_MAGIC, __priv_data::data_size, __priv_data::ref_counter, __priv_data::destructor_fn, ast_atomic_fetchadd_int(), and EXTERNAL_OBJ.
Referenced by __ao2_alloc_debug(), and __ao2_alloc().
{
/* allocation */
struct astobj2 *obj;
if (data_size < sizeof(void *))
data_size = sizeof(void *);
#if defined(__AST_DEBUG_MALLOC)
obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname);
#else
obj = ast_calloc(1, sizeof(*obj) + data_size);
#endif
if (obj == NULL)
return NULL;
ast_mutex_init(&obj->priv_data.lock);
obj->priv_data.magic = AO2_MAGIC;
obj->priv_data.data_size = data_size;
obj->priv_data.ref_counter = 1;
obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */
#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, |
| 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.
Definition at line 583 of file astobj2.c.
References last, INTERNAL_OBJ(), OBJ_MULTIPLE, OBJ_NODATA, __ao2_container_alloc(), ast_calloc, ao2_ref, WITH_DATA, cb_true_data(), cb_true(), OBJ_POINTER, ao2_container::hash_fn, ao2_container::n_buckets, OBJ_CONTINUE, ao2_lock, AST_LIST_TRAVERSE_SAFE_BEGIN, ao2_container::buckets, bucket_entry::entry, match(), CMP_MATCH, CMP_STOP, EXTERNAL_OBJ, bucket_entry::astobj, OBJ_UNLINK, __ao2_ref_debug(), __ao2_ref(), __ao2_link_debug(), __ao2_link(), ast_atomic_fetchadd_int(), ao2_container::version, AST_LIST_REMOVE_CURRENT, ao2_container::elements, ast_free, AST_LIST_TRAVERSE_SAFE_END, ao2_unlock, ao2_iterator_init(), AO2_ITERATOR_DONTLOCK, AO2_ITERATOR_UNLINK, and AO2_ITERATOR_MALLOCD.
Referenced by __ao2_callback_debug(), __ao2_callback(), __ao2_callback_data_debug(), and __ao2_callback_data().
{
int i, start, last; /* search boundaries */
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.
*/
if (!(multi_container = __ao2_container_alloc(1, NULL, NULL))) {
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)) /* we know hash can handle this case */
start = i = c->hash_fn(arg, flags & OBJ_POINTER) % 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;
}
ao2_lock(c); /* avoid modifications to the content */
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, funcname);
else
__ao2_ref(ret, 1);
}
}
/* If we are in OBJ_MULTIPLE mode and OBJ_NODATE 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, tag, file, line, funcname);
} else {
__ao2_link(multi_container, ret);
}
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, funcname);
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;
}
}
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_DONTLOCK | 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, |
| const uint | n_buckets, | ||
| ao2_hash_fn * | hash_fn, | ||
| ao2_callback_fn * | cmp_fn | ||
| ) | [static, read] |
Referenced by __ao2_container_alloc_debug(), and __ao2_container_alloc().
| 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, read] |
Definition at line 404 of file astobj2.c.
References ao2_container::version, ao2_container::n_buckets, ao2_container::hash_fn, hash_zero(), ao2_container::cmp_fn, and ast_atomic_fetchadd_int().
{
/* 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 * | a, |
| struct bucket_entry ** | q | ||
| ) | [static] |
Definition at line 830 of file astobj2.c.
References INTERNAL_OBJ(), ao2_iterator::c, ao2_iterator::flags, AO2_ITERATOR_DONTLOCK, ao2_lock, ao2_container::version, ao2_iterator::c_version, ao2_iterator::obj, AST_LIST_NEXT, bucket_entry::entry, ao2_iterator::bucket, ao2_iterator::version, ao2_container::n_buckets, AST_LIST_TRAVERSE, ao2_container::buckets, bucket_entry::version, EXTERNAL_OBJ, bucket_entry::astobj, AO2_ITERATOR_UNLINK, ast_atomic_fetchadd_int(), AST_LIST_REMOVE, ao2_container::elements, and ast_free.
Referenced by __ao2_iterator_next_debug(), and __ao2_iterator_next().
{
int lim;
struct bucket_entry *p = NULL;
void *ret = NULL;
*q = NULL;
if (INTERNAL_OBJ(a->c) == NULL)
return NULL;
if (!(a->flags & AO2_ITERATOR_DONTLOCK))
ao2_lock(a->c);
/* optimization. If the container is unchanged and
* we have a pointer, try follow it
*/
if (a->c->version == a->c_version && (p = a->obj)) {
if ((p = AST_LIST_NEXT(p, entry)))
goto found;
/* nope, start from the next bucket */
a->bucket++;
a->version = 0;
a->obj = NULL;
}
lim = a->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 (; a->bucket < lim; a->bucket++, a->version = 0) {
/* scan the current bucket */
AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
if (p->version > a->version)
goto found;
}
}
found:
if (p) {
ret = EXTERNAL_OBJ(p->astobj);
if (a->flags & AO2_ITERATOR_UNLINK) {
/* we are going to modify the container, so update version */
ast_atomic_fetchadd_int(&a->c->version, 1);
AST_LIST_REMOVE(&a->c->buckets[a->bucket], p, entry);
/* update number of elements */
ast_atomic_fetchadd_int(&a->c->elements, -1);
a->version = 0;
a->obj = NULL;
a->c_version = a->c->version;
ast_free(p);
} else {
a->version = p->version;
a->obj = p;
a->c_version = a->c->version;
/* inc refcount of returned object */
*q = p;
}
}
return ret;
}
| static struct bucket_entry * internal_ao2_link | ( | struct ao2_container * | c, |
| void * | user_data, | ||
| const char * | file, | ||
| int | line, | ||
| const char * | func | ||
| ) | [static, read] |
Definition at line 474 of file astobj2.c.
References INTERNAL_OBJ(), ast_calloc, OBJ_POINTER, ao2_lock, bucket_entry::astobj, bucket_entry::version, ast_atomic_fetchadd_int(), and AST_LIST_INSERT_TAIL.
Referenced by __ao2_link_debug(), and __ao2_link().
{
int i;
/* 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));
ao2_lock(c);
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);
/* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */
return p;
}
| static int internal_ao2_ref | ( | void * | user_data, |
| const int | delta | ||
| ) | [static] |
Definition at line 235 of file astobj2.c.
References INTERNAL_OBJ(), astobj2::priv_data, __priv_data::ref_counter, ast_atomic_fetchadd_int(), ast_log(), LOG_ERROR, __priv_data::destructor_fn, ast_mutex_destroy, __priv_data::lock, __priv_data::data_size, and ast_free.
Referenced by __ao2_ref_debug(), and __ao2_ref().
{
struct astobj2 *obj = INTERNAL_OBJ(user_data);
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
/* this case must never happen */
if (current_value < 0)
ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);
if (current_value <= 0) { /* last reference, destroy the object */
if (obj->priv_data.destructor_fn != NULL) {
obj->priv_data.destructor_fn(user_data);
}
ast_mutex_destroy(&obj->priv_data.lock);
#ifdef AO2_DEBUG
ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
ast_atomic_fetchadd_int(&ao2.total_objects, -1);
#endif
/* 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(struct astobj2 *) + sizeof(void *) );
ast_free(obj);
}
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 105 of file astobj2.c.
References ast_log(), LOG_ERROR, AO2_MAGIC, astobj2::priv_data, and __priv_data::magic.
Referenced by __ao2_lock(), __ao2_unlock(), __ao2_trylock(), ao2_object_get_lockaddr(), __ao2_ref_debug(), __ao2_ref(), internal_ao2_ref(), internal_ao2_link(), __ao2_unlink_debug(), __ao2_unlink(), internal_ao2_callback(), and internal_ao2_iterator_next().