#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, const char *tag, const char *file, int line, const char *funcname) |
int | __ao2_trylock (void *user_data, const char *file, const char *func, int line, const char *var) |
Try locking-- (don't block if fail). | |
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 unsigned int 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 uint 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 56 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 145 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 33 of file astobj2.c.
Referenced by __ao2_alloc_debug(), and __ao2_ref_debug().
enum ao2_callback_type |
void* __ao2_alloc | ( | size_t | data_size, | |
ao2_destructor_fn | destructor_fn | |||
) |
Definition at line 349 of file astobj2.c.
References internal_ao2_alloc().
Referenced by __ao2_container_alloc().
00350 { 00351 return internal_ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__); 00352 }
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 329 of file astobj2.c.
References internal_ao2_alloc(), and REF_FILE.
Referenced by __ao2_container_alloc_debug(), __ast_channel_alloc_ap(), __ast_dummy_channel_alloc(), and _moh_class_malloc().
00331 { 00332 /* allocation */ 00333 void *obj; 00334 FILE *refo; 00335 00336 if ((obj = internal_ao2_alloc(data_size, destructor_fn, file, line, funcname)) == NULL) { 00337 return NULL; 00338 } 00339 00340 if (ref_debug && (refo = fopen(REF_FILE, "a"))) { 00341 fprintf(refo, "%p =1 %s:%d:%s (%s)\n", obj, file, line, funcname, tag); 00342 fclose(refo); 00343 } 00344 00345 /* return a pointer to the user data */ 00346 return obj; 00347 }
void* __ao2_callback | ( | struct ao2_container * | c, | |
const enum search_flags | flags, | |||
ao2_callback_fn * | cb_fn, | |||
void * | arg | |||
) |
Definition at line 777 of file astobj2.c.
References DEFAULT, and internal_ao2_callback().
Referenced by __ao2_find(), __ao2_unlink(), and container_destruct().
00779 { 00780 return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL); 00781 }
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 791 of file astobj2.c.
References internal_ao2_callback(), and WITH_DATA.
00793 { 00794 return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL); 00795 }
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 783 of file astobj2.c.
References internal_ao2_callback(), and WITH_DATA.
00787 { 00788 return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname); 00789 }
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 769 of file astobj2.c.
References DEFAULT, and internal_ao2_callback().
Referenced by __ao2_find_debug(), __ao2_unlink_debug(), and container_destruct_debug().
00773 { 00774 return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname); 00775 }
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 449 of file astobj2.c.
References __ao2_alloc(), container_destruct(), and internal_ao2_container_alloc().
Referenced by internal_ao2_callback().
00451 { 00452 /* XXX maybe consistency check on arguments ? */ 00453 /* compute the container size */ 00454 00455 const unsigned int num_buckets = hash_fn ? n_buckets : 1; 00456 size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket); 00457 struct ao2_container *c = __ao2_alloc(container_size, container_destruct); 00458 00459 return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn); 00460 }
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 436 of file astobj2.c.
References __ao2_alloc_debug(), container_destruct_debug(), and internal_ao2_container_alloc().
00439 { 00440 /* XXX maybe consistency check on arguments ? */ 00441 /* compute the container size */ 00442 const unsigned int num_buckets = hash_fn ? n_buckets : 1; 00443 size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket); 00444 struct ao2_container *c = __ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug); 00445 00446 return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn); 00447 }
void* __ao2_find | ( | struct ao2_container * | c, | |
void * | arg, | |||
enum search_flags | flags | |||
) |
Definition at line 805 of file astobj2.c.
References __ao2_callback(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
00806 { 00807 return __ao2_callback(c, flags, c->cmp_fn, arg); 00808 }
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 800 of file astobj2.c.
References __ao2_callback_debug(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
00801 { 00802 return __ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname); 00803 }
void* __ao2_iterator_next | ( | struct ao2_iterator * | a | ) |
Definition at line 926 of file astobj2.c.
References __ao2_ref(), AO2_ITERATOR_DONTLOCK, ao2_unlock, ao2_iterator::c, ao2_iterator::flags, and internal_ao2_iterator_next().
00927 { 00928 struct bucket_entry *p = NULL; 00929 void *ret = NULL; 00930 00931 ret = internal_ao2_iterator_next(a, &p); 00932 00933 if (p) { 00934 /* inc refcount of returned object */ 00935 __ao2_ref(ret, 1); 00936 } 00937 00938 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00939 ao2_unlock(a->c); 00940 00941 return ret; 00942 }
void* __ao2_iterator_next_debug | ( | struct ao2_iterator * | a, | |
char * | tag, | |||
char * | file, | |||
int | line, | |||
const char * | funcname | |||
) |
Definition at line 908 of file astobj2.c.
References __ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_unlock, ao2_iterator::c, ao2_iterator::flags, and internal_ao2_iterator_next().
00909 { 00910 struct bucket_entry *p; 00911 void *ret = NULL; 00912 00913 ret = internal_ao2_iterator_next(a, &p); 00914 00915 if (p) { 00916 /* inc refcount of returned object */ 00917 __ao2_ref_debug(ret, 1, tag, file, line, funcname); 00918 } 00919 00920 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00921 ao2_unlock(a->c); 00922 00923 return ret; 00924 }
void* __ao2_link | ( | struct ao2_container * | c, | |
void * | user_data | |||
) |
Definition at line 526 of file astobj2.c.
References __ao2_ref(), ao2_unlock, and internal_ao2_link().
Referenced by internal_ao2_callback().
00527 { 00528 struct bucket_entry *p = internal_ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__); 00529 00530 if (p) { 00531 __ao2_ref(user_data, +1); 00532 ao2_unlock(c); 00533 } 00534 return p; 00535 }
void* __ao2_link_debug | ( | struct ao2_container * | c, | |
void * | user_data, | |||
char * | tag, | |||
char * | file, | |||
int | line, | |||
const char * | funcname | |||
) |
Definition at line 515 of file astobj2.c.
References __ao2_ref_debug(), ao2_unlock, and internal_ao2_link().
Referenced by internal_ao2_callback().
00516 { 00517 struct bucket_entry *p = internal_ao2_link(c, user_data, file, line, funcname); 00518 00519 if (p) { 00520 __ao2_ref_debug(user_data, +1, tag, file, line, funcname); 00521 ao2_unlock(c); 00522 } 00523 return p; 00524 }
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 158 of file astobj2.c.
References __ast_pthread_mutex_lock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00159 { 00160 struct astobj2 *p = INTERNAL_OBJ(user_data); 00161 00162 if (p == NULL) 00163 return -1; 00164 00165 #ifdef AO2_DEBUG 00166 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00167 #endif 00168 00169 return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock); 00170 }
int __ao2_ref | ( | void * | user_data, | |
const int | delta | |||
) |
Definition at line 242 of file astobj2.c.
References internal_ao2_ref().
Referenced by __ao2_iterator_next(), __ao2_link(), cd_cb(), and internal_ao2_callback().
00243 { 00244 return internal_ao2_ref(user_data, delta); 00245 }
int __ao2_ref_debug | ( | void * | user_data, | |
const int | delta, | |||
const char * | tag, | |||
const char * | file, | |||
int | line, | |||
const char * | funcname | |||
) |
Definition at line 217 of file astobj2.c.
References __priv_data::destructor_fn, internal_ao2_ref(), INTERNAL_OBJ(), astobj2::priv_data, __priv_data::ref_counter, and REF_FILE.
Referenced by __ao2_iterator_next_debug(), __ao2_link_debug(), cd_cb_debug(), dialog_ref_debug(), dialog_unref_debug(), and internal_ao2_callback().
00218 { 00219 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00220 00221 if (obj == NULL) 00222 return -1; 00223 00224 if (delta != 0) { 00225 FILE *refo = fopen(REF_FILE, "a"); 00226 if (refo) { 00227 fprintf(refo, "%p %s%d %s:%d:%s (%s) [@%d]\n", user_data, (delta < 0 ? "" : "+"), 00228 delta, file, line, funcname, tag, obj ? obj->priv_data.ref_counter : -1); 00229 fclose(refo); 00230 } 00231 } 00232 if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */ 00233 FILE *refo = fopen(REF_FILE, "a"); 00234 if (refo) { 00235 fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag); 00236 fclose(refo); 00237 } 00238 } 00239 return internal_ao2_ref(user_data, delta); 00240 }
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 186 of file astobj2.c.
References __ast_pthread_mutex_trylock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00187 { 00188 struct astobj2 *p = INTERNAL_OBJ(user_data); 00189 int ret; 00190 00191 if (p == NULL) 00192 return -1; 00193 ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock); 00194 00195 #ifdef AO2_DEBUG 00196 if (!ret) 00197 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00198 #endif 00199 return ret; 00200 }
void* __ao2_unlink | ( | struct ao2_container * | c, | |
void * | user_data | |||
) |
Definition at line 560 of file astobj2.c.
References __ao2_callback(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00561 { 00562 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00563 return NULL; 00564 00565 __ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data); 00566 00567 return NULL; 00568 }
void* __ao2_unlink_debug | ( | struct ao2_container * | c, | |
void * | user_data, | |||
char * | tag, | |||
char * | file, | |||
int | line, | |||
const char * | funcname | |||
) |
Definition at line 549 of file astobj2.c.
References __ao2_callback_debug(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00551 { 00552 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00553 return NULL; 00554 00555 __ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname); 00556 00557 return NULL; 00558 }
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 172 of file astobj2.c.
References __ast_pthread_mutex_unlock(), ast_atomic_fetchadd_int(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00173 { 00174 struct astobj2 *p = INTERNAL_OBJ(user_data); 00175 00176 if (p == NULL) 00177 return -1; 00178 00179 #ifdef AO2_DEBUG 00180 ast_atomic_fetchadd_int(&ao2.total_locked, -1); 00181 #endif 00182 00183 return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock); 00184 }
void ao2_bt | ( | void | ) |
Definition at line 88 of file astobj2.c.
References ast_bt_get_symbols(), ast_verbose, free, and N1.
00089 { 00090 int c, i; 00091 #define N1 20 00092 void *addresses[N1]; 00093 char **strings; 00094 00095 c = backtrace(addresses, N1); 00096 strings = ast_bt_get_symbols(addresses,c); 00097 ast_verbose("backtrace returned: %d\n", c); 00098 for(i = 0; i < c; i++) { 00099 ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]); 00100 } 00101 free(strings); 00102 }
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 465 of file astobj2.c.
References ao2_container::elements.
Referenced by __ast_data_register(), __ast_manager_event_multichan(), __queues_show(), _sip_show_peers(), ast_active_channels(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_srtp_unprotect(), ast_tone_zone_count(), 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_monitor(), do_timing(), endelm(), get_unused_callno(), handle_cli_iax2_show_callno_limits(), handle_show_hint(), handle_show_hints(), hints_data_provider_get(), locals_show(), lock_broker(), match_filter(), meetme_data_provider_get(), member_add_to_queue(), pthread_timer_open(), queue_exec(), queue_function_qac(), queues_data_provider_get_helper(), try_calling(), and unload_module().
00466 { 00467 return c->elements; 00468 }
void ao2_iterator_destroy | ( | struct ao2_iterator * | i | ) |
Destroy a container iterator.
destroy an iterator
Definition at line 828 of file astobj2.c.
References AO2_ITERATOR_MALLOCD, ao2_ref, ast_free, ao2_iterator::c, and ao2_iterator::flags.
Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __iax2_show_peers(), __queues_show(), _sip_show_peers(), action_meetmelist(), alias_show(), ast_channel_iterator_destroy(), ast_data_iterator_end(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_srtp_unprotect(), ast_var_indications(), ast_var_indications_table(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), complete_userno(), conf_queue_dtmf(), data_filter_find(), data_get_xml_add_child(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), 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_session(), find_session_by_nonce(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_indication_show(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_odbc_show(), handle_feature_show(), handle_parkedcalls(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_show_routes(), handle_showmanconn(), handle_statechange(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), kill_duplicate_offers(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), num_available_members(), peers_data_provider_get(), poke_all_peers(), pp_each_user_helper(), prune_peers(), prune_users(), purge_sessions(), queue_function_qac(), 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_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().
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 813 of file astobj2.c.
References ao2_ref, ao2_iterator::c, and ao2_iterator::flags.
Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __iax2_show_peers(), __queues_show(), action_meetmelist(), alias_show(), ast_channel_iterator_all_new(), ast_data_iterator_init(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_srtp_unprotect(), ast_tone_zone_iterator_init(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), complete_userno(), conf_queue_dtmf(), data_filter_find(), data_get_xml_add_child(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), 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_session(), find_session_by_nonce(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_odbc_show(), handle_feature_show(), handle_parkedcalls(), handle_show_calendar(), handle_show_calendars(), handle_show_hint(), handle_show_hints(), handle_show_routes(), handle_showmanconn(), handle_statechange(), hints_data_provider_get(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), internal_ao2_callback(), local_devicestate(), locals_show(), manager_iax2_show_peer_list(), manager_optimize_away(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), meetme_menu_admin_extended(), meetme_show_cmd(), moh_rescan_files(), num_available_members(), peers_data_provider_get(), poke_all_peers(), pp_each_user_helper(), prune_peers(), prune_users(), purge_sessions(), queue_function_qac(), 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_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().
00814 { 00815 struct ao2_iterator a = { 00816 .c = c, 00817 .flags = flags 00818 }; 00819 00820 ao2_ref(c, +1); 00821 00822 return a; 00823 }
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 202 of file astobj2.c.
References INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00203 { 00204 struct astobj2 *p = INTERNAL_OBJ(obj); 00205 00206 if (p == NULL) 00207 return NULL; 00208 00209 return &p->priv_data.lock; 00210 }
int astobj2_init | ( | void | ) |
Provided by astobj2.c
Definition at line 1132 of file astobj2.c.
References ARRAY_LEN, and ast_cli_register_multiple().
Referenced by main().
01133 { 01134 #ifdef AO2_DEBUG 01135 ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); 01136 #endif 01137 01138 return 0; 01139 }
static int cb_true | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) | [static] |
special callback that matches all
Definition at line 573 of file astobj2.c.
References CMP_MATCH.
Referenced by internal_ao2_callback().
00574 { 00575 return CMP_MATCH; 00576 }
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 581 of file astobj2.c.
References CMP_MATCH.
Referenced by internal_ao2_callback().
00582 { 00583 return CMP_MATCH; 00584 }
static int cd_cb | ( | void * | obj, | |
void * | arg, | |||
int | flag | |||
) | [static] |
Definition at line 947 of file astobj2.c.
References __ao2_ref().
Referenced by container_destruct().
00948 { 00949 __ao2_ref(obj, -1); 00950 return 0; 00951 }
static int cd_cb_debug | ( | void * | obj, | |
void * | arg, | |||
int | flag | |||
) | [static] |
Definition at line 953 of file astobj2.c.
References __ao2_ref_debug().
Referenced by container_destruct_debug().
00954 { 00955 __ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00956 return 0; 00957 }
static void container_destruct | ( | void * | c | ) | [static] |
Definition at line 959 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().
00960 { 00961 struct ao2_container *c = _c; 00962 int i; 00963 00964 __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL); 00965 00966 for (i = 0; i < c->n_buckets; i++) { 00967 struct bucket_entry *current; 00968 00969 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00970 ast_free(current); 00971 } 00972 } 00973 00974 #ifdef AO2_DEBUG 00975 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00976 #endif 00977 }
static void container_destruct_debug | ( | void * | c | ) | [static] |
Definition at line 979 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().
00980 { 00981 struct ao2_container *c = _c; 00982 int i; 00983 00984 __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00985 00986 for (i = 0; i < c->n_buckets; i++) { 00987 struct bucket_entry *current; 00988 00989 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00990 ast_free(current); 00991 } 00992 } 00993 00994 #ifdef AO2_DEBUG 00995 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00996 #endif 00997 }
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 407 of file astobj2.c.
Referenced by internal_ao2_container_alloc().
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 296 of file astobj2.c.
References __ast_calloc(), AO2_MAGIC, ast_atomic_fetchadd_int(), ast_calloc, ast_mutex_init, __priv_data::data_size, __priv_data::destructor_fn, EXTERNAL_OBJ, __priv_data::lock, __priv_data::magic, astobj2::priv_data, and __priv_data::ref_counter.
Referenced by __ao2_alloc(), and __ao2_alloc_debug().
00297 { 00298 /* allocation */ 00299 struct astobj2 *obj; 00300 00301 if (data_size < sizeof(void *)) 00302 data_size = sizeof(void *); 00303 00304 #if defined(__AST_DEBUG_MALLOC) 00305 obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname); 00306 #else 00307 obj = ast_calloc(1, sizeof(*obj) + data_size); 00308 #endif 00309 00310 if (obj == NULL) 00311 return NULL; 00312 00313 ast_mutex_init(&obj->priv_data.lock); 00314 obj->priv_data.magic = AO2_MAGIC; 00315 obj->priv_data.data_size = data_size; 00316 obj->priv_data.ref_counter = 1; 00317 obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */ 00318 00319 #ifdef AO2_DEBUG 00320 ast_atomic_fetchadd_int(&ao2.total_objects, 1); 00321 ast_atomic_fetchadd_int(&ao2.total_mem, data_size); 00322 ast_atomic_fetchadd_int(&ao2.total_refs, 1); 00323 #endif 00324 00325 /* return a pointer to the user data */ 00326 return EXTERNAL_OBJ(obj); 00327 }
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 594 of file astobj2.c.
References __ao2_container_alloc(), __ao2_link(), __ao2_link_debug(), __ao2_ref(), __ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), AO2_ITERATOR_MALLOCD, AO2_ITERATOR_UNLINK, ao2_lock, ao2_ref, ao2_unlock, ast_atomic_fetchadd_int(), ast_calloc, ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, bucket_entry::astobj, ao2_container::buckets, cb_true(), cb_true_data(), CMP_MATCH, CMP_STOP, ao2_container::elements, bucket_entry::entry, EXTERNAL_OBJ, ao2_container::hash_fn, INTERNAL_OBJ(), last, match(), ao2_container::n_buckets, OBJ_CONTINUE, OBJ_MULTIPLE, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, ao2_container::version, and WITH_DATA.
Referenced by __ao2_callback(), __ao2_callback_data(), __ao2_callback_data_debug(), and __ao2_callback_debug().
00597 { 00598 int i, start, last; /* search boundaries */ 00599 void *ret = NULL; 00600 ao2_callback_fn *cb_default = NULL; 00601 ao2_callback_data_fn *cb_withdata = NULL; 00602 struct ao2_container *multi_container = NULL; 00603 struct ao2_iterator *multi_iterator = NULL; 00604 00605 if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */ 00606 return NULL; 00607 00608 /* 00609 * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA 00610 * turned off. This if statement checks for the special condition 00611 * where multiple items may need to be returned. 00612 */ 00613 if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) { 00614 /* we need to return an ao2_iterator with the results, 00615 * as there could be more than one. the iterator will 00616 * hold the only reference to a container that has all the 00617 * matching objects linked into it, so when the iterator 00618 * is destroyed, the container will be automatically 00619 * destroyed as well. 00620 */ 00621 if (!(multi_container = __ao2_container_alloc(1, NULL, NULL))) { 00622 return NULL; 00623 } 00624 if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) { 00625 ao2_ref(multi_container, -1); 00626 return NULL; 00627 } 00628 } 00629 00630 /* override the match function if necessary */ 00631 if (cb_fn == NULL) { /* if NULL, match everything */ 00632 if (type == WITH_DATA) { 00633 cb_withdata = cb_true_data; 00634 } else { 00635 cb_default = cb_true; 00636 } 00637 } else { 00638 /* We do this here to avoid the per object casting penalty (even though 00639 that is probably optimized away anyway). */ 00640 if (type == WITH_DATA) { 00641 cb_withdata = cb_fn; 00642 } else { 00643 cb_default = cb_fn; 00644 } 00645 } 00646 00647 /* 00648 * XXX this can be optimized. 00649 * If we have a hash function and lookup by pointer, 00650 * run the hash function. Otherwise, scan the whole container 00651 * (this only for the time being. We need to optimize this.) 00652 */ 00653 if ((flags & OBJ_POINTER)) /* we know hash can handle this case */ 00654 start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets; 00655 else /* don't know, let's scan all buckets */ 00656 start = i = -1; /* XXX this must be fixed later. */ 00657 00658 /* determine the search boundaries: i..last-1 */ 00659 if (i < 0) { 00660 start = i = 0; 00661 last = c->n_buckets; 00662 } else if ((flags & OBJ_CONTINUE)) { 00663 last = c->n_buckets; 00664 } else { 00665 last = i + 1; 00666 } 00667 00668 ao2_lock(c); /* avoid modifications to the content */ 00669 00670 for (; i < last ; i++) { 00671 /* scan the list with prev-cur pointers */ 00672 struct bucket_entry *cur; 00673 00674 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) { 00675 int match = (CMP_MATCH | CMP_STOP); 00676 00677 if (type == WITH_DATA) { 00678 match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags); 00679 } else { 00680 match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags); 00681 } 00682 00683 /* we found the object, performing operations according flags */ 00684 if (match == 0) { /* no match, no stop, continue */ 00685 continue; 00686 } else if (match == CMP_STOP) { /* no match but stop, we are done */ 00687 i = last; 00688 break; 00689 } 00690 00691 /* we have a match (CMP_MATCH) here */ 00692 if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */ 00693 /* it is important to handle this case before the unlink */ 00694 ret = EXTERNAL_OBJ(cur->astobj); 00695 if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) { 00696 if (tag) 00697 __ao2_ref_debug(ret, 1, tag, file, line, funcname); 00698 else 00699 __ao2_ref(ret, 1); 00700 } 00701 } 00702 00703 /* If we are in OBJ_MULTIPLE mode and OBJ_NODATE is off, 00704 * link the object into the container that will hold the results. 00705 */ 00706 if (ret && (multi_container != NULL)) { 00707 if (tag) { 00708 __ao2_link_debug(multi_container, ret, tag, file, line, funcname); 00709 } else { 00710 __ao2_link(multi_container, ret); 00711 } 00712 ret = NULL; 00713 } 00714 00715 if (flags & OBJ_UNLINK) { /* must unlink */ 00716 /* we are going to modify the container, so update version */ 00717 ast_atomic_fetchadd_int(&c->version, 1); 00718 AST_LIST_REMOVE_CURRENT(entry); 00719 /* update number of elements */ 00720 ast_atomic_fetchadd_int(&c->elements, -1); 00721 00722 /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container 00723 * must be decremented. 00724 * - When unlinking with OBJ_MULTIPLE the ref from the original container 00725 * must be decremented regardless if OBJ_NODATA is used. This is because the result is 00726 * returned in a new container that already holds its own ref for the object. If the ref 00727 * from the original container is not accounted for here a memory leak occurs. */ 00728 if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) { 00729 if (tag) 00730 __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, funcname); 00731 else 00732 __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1); 00733 } 00734 ast_free(cur); /* free the link record */ 00735 } 00736 00737 if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) { 00738 /* We found our only (or last) match, so force an exit from 00739 the outside loop. */ 00740 i = last; 00741 break; 00742 } 00743 } 00744 AST_LIST_TRAVERSE_SAFE_END; 00745 00746 if (ret) { 00747 break; 00748 } 00749 00750 if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) { 00751 /* Move to the beginning to ensure we check every bucket */ 00752 i = -1; 00753 last = start; 00754 } 00755 } 00756 ao2_unlock(c); 00757 00758 /* if multi_container was created, we are returning multiple objects */ 00759 if (multi_container != NULL) { 00760 *multi_iterator = ao2_iterator_init(multi_container, 00761 AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD); 00762 ao2_ref(multi_container, -1); 00763 return multi_iterator; 00764 } else { 00765 return ret; 00766 } 00767 }
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 415 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.
00417 { 00418 /* XXX maybe consistency check on arguments ? */ 00419 /* compute the container size */ 00420 00421 if (!c) 00422 return NULL; 00423 00424 c->version = 1; /* 0 is a reserved value here */ 00425 c->n_buckets = hash_fn ? n_buckets : 1; 00426 c->hash_fn = hash_fn ? hash_fn : hash_zero; 00427 c->cmp_fn = cmp_fn; 00428 00429 #ifdef AO2_DEBUG 00430 ast_atomic_fetchadd_int(&ao2.total_containers, 1); 00431 #endif 00432 00433 return c; 00434 }
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(), and __ao2_container_alloc_debug().
static void * internal_ao2_iterator_next | ( | struct ao2_iterator * | a, | |
struct bucket_entry ** | q | |||
) | [static] |
Definition at line 841 of file astobj2.c.
References AO2_ITERATOR_DONTLOCK, AO2_ITERATOR_UNLINK, ao2_lock, ast_atomic_fetchadd_int(), ast_free, AST_LIST_NEXT, AST_LIST_REMOVE, AST_LIST_TRAVERSE, bucket_entry::astobj, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, ao2_container::elements, bucket_entry::entry, EXTERNAL_OBJ, ao2_iterator::flags, INTERNAL_OBJ(), ao2_container::n_buckets, ao2_iterator::obj, bucket_entry::version, ao2_iterator::version, and ao2_container::version.
Referenced by __ao2_iterator_next(), and __ao2_iterator_next_debug().
00842 { 00843 int lim; 00844 struct bucket_entry *p = NULL; 00845 void *ret = NULL; 00846 00847 *q = NULL; 00848 00849 if (INTERNAL_OBJ(a->c) == NULL) 00850 return NULL; 00851 00852 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00853 ao2_lock(a->c); 00854 00855 /* optimization. If the container is unchanged and 00856 * we have a pointer, try follow it 00857 */ 00858 if (a->c->version == a->c_version && (p = a->obj)) { 00859 if ((p = AST_LIST_NEXT(p, entry))) 00860 goto found; 00861 /* nope, start from the next bucket */ 00862 a->bucket++; 00863 a->version = 0; 00864 a->obj = NULL; 00865 } 00866 00867 lim = a->c->n_buckets; 00868 00869 /* Browse the buckets array, moving to the next 00870 * buckets if we don't find the entry in the current one. 00871 * Stop when we find an element with version number greater 00872 * than the current one (we reset the version to 0 when we 00873 * switch buckets). 00874 */ 00875 for (; a->bucket < lim; a->bucket++, a->version = 0) { 00876 /* scan the current bucket */ 00877 AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) { 00878 if (p->version > a->version) 00879 goto found; 00880 } 00881 } 00882 00883 found: 00884 if (p) { 00885 ret = EXTERNAL_OBJ(p->astobj); 00886 if (a->flags & AO2_ITERATOR_UNLINK) { 00887 /* we are going to modify the container, so update version */ 00888 ast_atomic_fetchadd_int(&a->c->version, 1); 00889 AST_LIST_REMOVE(&a->c->buckets[a->bucket], p, entry); 00890 /* update number of elements */ 00891 ast_atomic_fetchadd_int(&a->c->elements, -1); 00892 a->version = 0; 00893 a->obj = NULL; 00894 a->c_version = a->c->version; 00895 ast_free(p); 00896 } else { 00897 a->version = p->version; 00898 a->obj = p; 00899 a->c_version = a->c->version; 00900 /* inc refcount of returned object */ 00901 *q = p; 00902 } 00903 } 00904 00905 return ret; 00906 }
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 485 of file astobj2.c.
References ao2_lock, ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, bucket_entry::astobj, INTERNAL_OBJ(), OBJ_POINTER, and bucket_entry::version.
Referenced by __ao2_link(), and __ao2_link_debug().
00486 { 00487 int i; 00488 /* create a new list entry */ 00489 struct bucket_entry *p; 00490 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00491 00492 if (obj == NULL) 00493 return NULL; 00494 00495 if (INTERNAL_OBJ(c) == NULL) 00496 return NULL; 00497 00498 p = ast_calloc(1, sizeof(*p)); 00499 if (!p) 00500 return NULL; 00501 00502 i = abs(c->hash_fn(user_data, OBJ_POINTER)); 00503 00504 ao2_lock(c); 00505 i %= c->n_buckets; 00506 p->astobj = obj; 00507 p->version = ast_atomic_fetchadd_int(&c->version, 1); 00508 AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry); 00509 ast_atomic_fetchadd_int(&c->elements, 1); 00510 00511 /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */ 00512 return p; 00513 }
static int internal_ao2_ref | ( | void * | user_data, | |
const int | delta | |||
) | [static] |
Definition at line 247 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_free, ast_log(), ast_mutex_destroy, __priv_data::data_size, __priv_data::destructor_fn, INTERNAL_OBJ(), __priv_data::lock, LOG_ERROR, astobj2::priv_data, and __priv_data::ref_counter.
Referenced by __ao2_ref(), and __ao2_ref_debug().
00248 { 00249 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00250 int current_value; 00251 int ret; 00252 00253 if (obj == NULL) 00254 return -1; 00255 00256 /* if delta is 0, just return the refcount */ 00257 if (delta == 0) 00258 return (obj->priv_data.ref_counter); 00259 00260 /* we modify with an atomic operation the reference counter */ 00261 ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta); 00262 current_value = ret + delta; 00263 00264 #ifdef AO2_DEBUG 00265 ast_atomic_fetchadd_int(&ao2.total_refs, delta); 00266 #endif 00267 00268 /* this case must never happen */ 00269 if (current_value < 0) 00270 ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data); 00271 00272 if (current_value <= 0) { /* last reference, destroy the object */ 00273 if (obj->priv_data.destructor_fn != NULL) { 00274 obj->priv_data.destructor_fn(user_data); 00275 } 00276 00277 ast_mutex_destroy(&obj->priv_data.lock); 00278 #ifdef AO2_DEBUG 00279 ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size); 00280 ast_atomic_fetchadd_int(&ao2.total_objects, -1); 00281 #endif 00282 /* for safety, zero-out the astobj2 header and also the 00283 * first word of the user-data, which we make sure is always 00284 * allocated. */ 00285 memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) ); 00286 ast_free(obj); 00287 } 00288 00289 return ret; 00290 }
static struct astobj2* INTERNAL_OBJ | ( | void * | user_data | ) | [static, read] |
convert from a pointer _p to a user-defined object
Definition at line 110 of file astobj2.c.
References AO2_MAGIC, ast_log(), LOG_ERROR, __priv_data::magic, and astobj2::priv_data.
Referenced by __ao2_lock(), __ao2_ref_debug(), __ao2_trylock(), __ao2_unlink(), __ao2_unlink_debug(), __ao2_unlock(), ao2_object_get_lockaddr(), internal_ao2_callback(), internal_ao2_iterator_next(), internal_ao2_link(), and internal_ao2_ref().
00111 { 00112 struct astobj2 *p; 00113 00114 if (!user_data) { 00115 ast_log(LOG_ERROR, "user_data is NULL\n"); 00116 return NULL; 00117 } 00118 00119 p = (struct astobj2 *) ((char *) user_data - sizeof(*p)); 00120 if (AO2_MAGIC != p->priv_data.magic) { 00121 if (p->priv_data.magic) { 00122 ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n", 00123 p->priv_data.magic, user_data); 00124 } else { 00125 ast_log(LOG_ERROR, 00126 "bad magic number for object %p. Object is likely destroyed.\n", 00127 user_data); 00128 } 00129 return NULL; 00130 } 00131 00132 return p; 00133 }