Thu Sep 7 01:03:12 2017

Asterisk developer's documentation


astobj2.c File Reference

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

Go to the source code of this file.

Data Structures

struct  __priv_data
struct  ao2_container
struct  astobj2
struct  bucket
struct  bucket_entry

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

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.
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 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_containerinternal_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_containerinternal_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_entryinternal_ao2_link (struct ao2_container *c, void *user_data, const char *file, int line, const char *func)
static int internal_ao2_ref (void *user_data, const int delta)
static struct astobj2INTERNAL_OBJ (void *user_data)
 convert from a pointer _p to a user-defined object

Variables

static FILE * ref_log

Define Documentation

#define AO2_MAGIC   0xa570b123

Definition at line 58 of file astobj2.c.

Referenced by internal_ao2_alloc(), and INTERNAL_OBJ().

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

convert from a pointer _p to an astobj2 object

Returns:
the pointer to the user-defined portion.

Definition at line 148 of file astobj2.c.

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

#define N1   20

Referenced by ao2_bt().


Enumeration Type Documentation

Enumerator:
DEFAULT 
WITH_DATA 

Definition at line 138 of file astobj2.c.

00138                        {
00139    DEFAULT,
00140    WITH_DATA,
00141 };


Function Documentation

void* __ao2_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn 
)

Definition at line 354 of file astobj2.c.

References internal_ao2_alloc().

Referenced by __ao2_container_alloc().

00355 {
00356    return internal_ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__);
00357 }

void* __ao2_alloc_debug ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
char *  tag,
const char *  file,
int  line,
const char *  funcname,
int  ref_debug 
)

Definition at line 335 of file astobj2.c.

References ast_get_tid(), and internal_ao2_alloc().

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

00337 {
00338    /* allocation */
00339    void *obj;
00340 
00341    if ((obj = internal_ao2_alloc(data_size, destructor_fn, file, line, funcname)) == NULL) {
00342       return NULL;
00343    }
00344 
00345    if (ref_log) {
00346       fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n", obj, ast_get_tid(), file, line, funcname, tag);
00347       fflush(ref_log);
00348    }
00349 
00350    /* return a pointer to the user data */
00351    return obj;
00352 }

void* __ao2_callback ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg 
)

Definition at line 782 of file astobj2.c.

References DEFAULT, and internal_ao2_callback().

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

00784 {
00785    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
00786 }

void* __ao2_callback_data ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_data_fn cb_fn,
void *  arg,
void *  data 
)

Definition at line 796 of file astobj2.c.

References internal_ao2_callback(), and WITH_DATA.

00798 {
00799    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
00800 }

void* __ao2_callback_data_debug ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_data_fn cb_fn,
void *  arg,
void *  data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 788 of file astobj2.c.

References internal_ao2_callback(), and WITH_DATA.

00792 {
00793    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname);
00794 }

void* __ao2_callback_debug ( struct ao2_container c,
const enum search_flags  flags,
ao2_callback_fn cb_fn,
void *  arg,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 774 of file astobj2.c.

References DEFAULT, and internal_ao2_callback().

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

00778 {
00779    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname);
00780 }

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 454 of file astobj2.c.

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

00456 {
00457    /* XXX maybe consistency check on arguments ? */
00458    /* compute the container size */
00459 
00460    const unsigned int num_buckets = hash_fn ? n_buckets : 1;
00461    size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
00462    struct ao2_container *c = __ao2_alloc(container_size, container_destruct);
00463 
00464    return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
00465 }

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 441 of file astobj2.c.

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

00444 {
00445    /* XXX maybe consistency check on arguments ? */
00446    /* compute the container size */
00447    const unsigned int num_buckets = hash_fn ? n_buckets : 1;
00448    size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
00449    struct ao2_container *c = __ao2_alloc_debug(container_size, ref_debug ? container_destruct_debug : container_destruct, tag, file, line, funcname, ref_debug);
00450 
00451    return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
00452 }

void* __ao2_find ( struct ao2_container c,
void *  arg,
enum search_flags  flags 
)

Definition at line 810 of file astobj2.c.

References __ao2_callback(), and ao2_container::cmp_fn.

Referenced by _get_mohbyname().

00811 {
00812    return __ao2_callback(c, flags, c->cmp_fn, arg);
00813 }

void* __ao2_find_debug ( struct ao2_container c,
void *  arg,
enum search_flags  flags,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

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

Definition at line 805 of file astobj2.c.

References __ao2_callback_debug(), and ao2_container::cmp_fn.

Referenced by _get_mohbyname().

00806 {
00807    return __ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname);
00808 }

void* __ao2_iterator_next ( struct ao2_iterator a  ) 

Definition at line 931 of file astobj2.c.

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

00932 {
00933    struct bucket_entry *p = NULL;
00934    void *ret = NULL;
00935 
00936    ret = internal_ao2_iterator_next(a, &p);
00937    
00938    if (p) {
00939       /* inc refcount of returned object */
00940       __ao2_ref(ret, 1);
00941    }
00942 
00943    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00944       ao2_unlock(a->c);
00945 
00946    return ret;
00947 }

void* __ao2_iterator_next_debug ( struct ao2_iterator a,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 913 of file astobj2.c.

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

00914 {
00915    struct bucket_entry *p;
00916    void *ret = NULL;
00917 
00918    ret = internal_ao2_iterator_next(a, &p);
00919    
00920    if (p) {
00921       /* inc refcount of returned object */
00922       __ao2_ref_debug(ret, 1, tag, file, line, funcname);
00923    }
00924 
00925    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00926       ao2_unlock(a->c);
00927 
00928    return ret;
00929 }

void* __ao2_link ( struct ao2_container c,
void *  user_data 
)

Definition at line 531 of file astobj2.c.

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

Referenced by internal_ao2_callback().

00532 {
00533    struct bucket_entry *p = internal_ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__);
00534 
00535    if (p) {
00536       __ao2_ref(user_data, +1);
00537       ao2_unlock(c);
00538    }
00539    return p;
00540 }

void* __ao2_link_debug ( struct ao2_container c,
void *  user_data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 520 of file astobj2.c.

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

Referenced by internal_ao2_callback().

00521 {
00522    struct bucket_entry *p = internal_ao2_link(c, user_data, file, line, funcname);
00523 
00524    if (p) {
00525       __ao2_ref_debug(user_data, +1, tag, file, line, funcname);
00526       ao2_unlock(c);
00527    }
00528    return p;
00529 }

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

Lock an object.

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

Definition at line 161 of file astobj2.c.

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

00162 {
00163    struct astobj2 *p = INTERNAL_OBJ(user_data);
00164 
00165    if (p == NULL)
00166       return -1;
00167 
00168 #ifdef AO2_DEBUG
00169    ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00170 #endif
00171 
00172    return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock);
00173 }

int __ao2_ref ( void *  user_data,
const int  delta 
)

Definition at line 248 of file astobj2.c.

References internal_ao2_ref().

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

00249 {
00250    return internal_ao2_ref(user_data, delta);
00251 }

int __ao2_ref_debug ( void *  user_data,
const int  delta,
const char *  tag,
const char *  file,
int  line,
const char *  funcname 
)

Definition at line 219 of file astobj2.c.

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

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

00220 {
00221    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00222    int old_refcount = -1;
00223 
00224    if (obj) {
00225       old_refcount = internal_ao2_ref(user_data, delta);
00226    }
00227 
00228    if (ref_log && user_data) {
00229       if (!obj) {
00230          /* Invalid object: Bad magic number. */
00231          fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
00232             user_data, delta, ast_get_tid(), file, line, funcname, tag);
00233          fflush(ref_log);
00234       } else if (old_refcount + delta == 0) {
00235          fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n",
00236             user_data, delta, ast_get_tid(), file, line, funcname, tag);
00237          fflush(ref_log);
00238       } else if (delta != 0) {
00239          fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data, (delta < 0 ? "" : "+"),
00240             delta, ast_get_tid(), file, line, funcname, old_refcount, tag);
00241          fflush(ref_log);
00242       }
00243    }
00244 
00245    return old_refcount;
00246 }

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

Try locking-- (don't block if fail).

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

Definition at line 189 of file astobj2.c.

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

00190 {
00191    struct astobj2 *p = INTERNAL_OBJ(user_data);
00192    int ret;
00193    
00194    if (p == NULL)
00195       return -1;
00196    ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock);
00197 
00198 #ifdef AO2_DEBUG
00199    if (!ret)
00200       ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00201 #endif
00202    return ret;
00203 }

void* __ao2_unlink ( struct ao2_container c,
void *  user_data 
)

Definition at line 565 of file astobj2.c.

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

00566 {
00567    if (INTERNAL_OBJ(user_data) == NULL)   /* safety check on the argument */
00568       return NULL;
00569 
00570    __ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data);
00571 
00572    return NULL;
00573 }

void* __ao2_unlink_debug ( struct ao2_container c,
void *  user_data,
char *  tag,
char *  file,
int  line,
const char *  funcname 
)

Definition at line 554 of file astobj2.c.

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

00556 {
00557    if (INTERNAL_OBJ(user_data) == NULL)   /* safety check on the argument */
00558       return NULL;
00559 
00560    __ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname);
00561 
00562    return NULL;
00563 }

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

Unlock an object.

Parameters:
a A pointer to the object we want unlock.
Returns:
0 on success, other values on error.

Definition at line 175 of file astobj2.c.

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

00176 {
00177    struct astobj2 *p = INTERNAL_OBJ(user_data);
00178 
00179    if (p == NULL)
00180       return -1;
00181 
00182 #ifdef AO2_DEBUG
00183    ast_atomic_fetchadd_int(&ao2.total_locked, -1);
00184 #endif
00185 
00186    return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock);
00187 }

void ao2_bt ( void   ) 

Definition at line 90 of file astobj2.c.

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

00091 {
00092    int c, i;
00093 #define N1  20
00094    void *addresses[N1];
00095    char **strings;
00096 
00097    c = backtrace(addresses, N1);
00098    strings = ast_bt_get_symbols(addresses,c);
00099    ast_verbose("backtrace returned: %d\n", c);
00100    for(i = 0; i < c; i++) {
00101       ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
00102    }
00103    ast_std_free(strings);
00104 }

int ao2_container_count ( struct ao2_container c  ) 
void ao2_iterator_destroy ( struct ao2_iterator i  ) 

Destroy a container iterator.

destroy an iterator

Definition at line 833 of file astobj2.c.

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

Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __iax2_show_peers(), __queues_show(), _sip_show_peers(), action_meetmelist(), alias_show(), ast_channel_iterator_destroy(), ast_data_iterator_end(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_srtp_unprotect(), ast_var_indications(), ast_var_indications_table(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), complete_userno(), conf_queue_dtmf(), data_filter_find(), data_get_xml_add_child(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), 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_cli_status(), 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(), queue_function_queuememberpaused(), queue_function_queuememberstatus(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), sla_calc_station_delays(), sla_change_trunk_state(), sla_queue_event_conf(), sla_show_stations(), sla_show_trunks(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().

00834 {
00835    ao2_ref(i->c, -1);
00836    if (i->flags & AO2_ITERATOR_MALLOCD) {
00837       ast_free(i);
00838    } else {
00839       i->c = NULL;
00840    }
00841 }

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 818 of file astobj2.c.

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

Referenced by __ast_data_search_cmp_structure(), __ast_manager_event_multichan(), __data_result_print_cli(), __iax2_show_peers(), __queues_show(), action_meetmelist(), alias_show(), ast_channel_iterator_all_new(), ast_data_iterator_init(), ast_data_search_match(), ast_merge_contexts_and_delete(), ast_srtp_unprotect(), ast_tone_zone_iterator_init(), astman_verify_session_readpermissions(), astman_verify_session_writepermissions(), authenticate(), authenticate_reply(), build_dialplan_useage_map(), calendar_query_exec(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_fax_show_sessions(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_core_id(), complete_core_show_hint(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), complete_userno(), conf_queue_dtmf(), data_filter_find(), data_get_xml_add_child(), data_odbc_provider_handler(), data_provider_print_cli(), data_provider_release_all(), data_result_generate_node(), data_result_manager_output(), 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_cli_status(), 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(), queue_function_queuememberpaused(), queue_function_queuememberstatus(), queues_data_provider_get(), queues_data_provider_get_helper(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), sla_calc_station_delays(), sla_change_trunk_state(), sla_queue_event_conf(), sla_show_stations(), sla_show_trunks(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), update_realtime_members(), and users_data_provider_get().

00819 {
00820    struct ao2_iterator a = {
00821       .c = c,
00822       .flags = flags
00823    };
00824 
00825    ao2_ref(c, +1);
00826    
00827    return a;
00828 }

int ao2_match_by_addr ( void *  user_data,
void *  arg,
int  flags 
)

another convenience function is a callback that matches on address

Definition at line 545 of file astobj2.c.

References CMP_MATCH, and CMP_STOP.

00546 {
00547    return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
00548 }

void* ao2_object_get_lockaddr ( void *  obj  ) 

Return the lock address of an object.

Parameters:
[in] obj A pointer to the object we want.
Returns:
the address of the lock, else NULL.

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

Since:
1.6.1

Definition at line 205 of file astobj2.c.

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

00206 {
00207    struct astobj2 *p = INTERNAL_OBJ(obj);
00208    
00209    if (p == NULL)
00210       return NULL;
00211 
00212    return &p->priv_data.lock;
00213 }

static void astobj2_cleanup ( void   )  [static]

Definition at line 1137 of file astobj2.c.

References ARRAY_LEN, and ast_cli_unregister_multiple().

Referenced by astobj2_init().

01138 {
01139 #ifdef AO2_DEBUG
01140    ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
01141 #endif
01142 
01143 #ifdef REF_DEBUG
01144    fclose(ref_log);
01145    ref_log = NULL;
01146 #endif
01147 }

int astobj2_init ( void   ) 

Provided by astobj2.c

Definition at line 1150 of file astobj2.c.

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

Referenced by main().

01151 {
01152 #ifdef REF_DEBUG
01153    char ref_filename[1024];
01154 #endif
01155 
01156 #ifdef REF_DEBUG
01157    snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
01158    ref_log = fopen(ref_filename, "w");
01159    if (!ref_log) {
01160       ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
01161    }
01162 #endif
01163 
01164 #ifdef AO2_DEBUG
01165    ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
01166 #endif
01167 
01168    ast_register_atexit(astobj2_cleanup);
01169    return 0;
01170 }

static int cb_true ( void *  user_data,
void *  arg,
int  flags 
) [static]

special callback that matches all

Definition at line 578 of file astobj2.c.

References CMP_MATCH.

Referenced by internal_ao2_callback().

00579 {
00580    return CMP_MATCH;
00581 }

static int cb_true_data ( void *  user_data,
void *  arg,
void *  data,
int  flags 
) [static]

similar to cb_true, but is an ao2_callback_data_fn instead

Definition at line 586 of file astobj2.c.

References CMP_MATCH.

Referenced by internal_ao2_callback().

00587 {
00588    return CMP_MATCH;
00589 }

static int cd_cb ( void *  obj,
void *  arg,
int  flag 
) [static]

Definition at line 952 of file astobj2.c.

References __ao2_ref().

Referenced by container_destruct().

00953 {
00954    __ao2_ref(obj, -1);
00955    return 0;
00956 }

static int cd_cb_debug ( void *  obj,
void *  arg,
int  flag 
) [static]

Definition at line 958 of file astobj2.c.

References __ao2_ref_debug().

Referenced by container_destruct_debug().

00959 {
00960    __ao2_ref_debug(obj, -1, "deref object via container destroy",  __FILE__, __LINE__, __PRETTY_FUNCTION__);
00961    return 0;
00962 }

static void container_destruct ( void *  c  )  [static]

Definition at line 964 of file astobj2.c.

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

Referenced by __ao2_container_alloc(), and __ao2_container_alloc_debug().

00965 {
00966    struct ao2_container *c = _c;
00967    int i;
00968 
00969    __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
00970 
00971    for (i = 0; i < c->n_buckets; i++) {
00972       struct bucket_entry *current;
00973 
00974       while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
00975          ast_free(current);
00976       }
00977    }
00978 
00979 #ifdef AO2_DEBUG
00980    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
00981 #endif
00982 }

static void container_destruct_debug ( void *  c  )  [static]

Definition at line 984 of file astobj2.c.

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

Referenced by __ao2_container_alloc_debug().

00985 {
00986    struct ao2_container *c = _c;
00987    int i;
00988 
00989    __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
00990 
00991    for (i = 0; i < c->n_buckets; i++) {
00992       struct bucket_entry *current;
00993 
00994       while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
00995          ast_free(current);
00996       }
00997    }
00998 
00999 #ifdef AO2_DEBUG
01000    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
01001 #endif
01002 }

static int hash_zero ( const void *  user_obj,
const int  flags 
) [static]

always zero hash function

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

Returns:
0

Definition at line 412 of file astobj2.c.

Referenced by internal_ao2_container_alloc().

00413 {
00414    return 0;
00415 }

static void* internal_ao2_alloc ( size_t  data_size,
ao2_destructor_fn  destructor_fn,
const char *  file,
int  line,
const char *  funcname 
) [static]

Definition at line 302 of file astobj2.c.

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

Referenced by __ao2_alloc(), and __ao2_alloc_debug().

00303 {
00304    /* allocation */
00305    struct astobj2 *obj;
00306 
00307    if (data_size < sizeof(void *))
00308       data_size = sizeof(void *);
00309 
00310 #if defined(__AST_DEBUG_MALLOC)
00311    obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname);
00312 #else
00313    obj = ast_calloc(1, sizeof(*obj) + data_size);
00314 #endif
00315 
00316    if (obj == NULL)
00317       return NULL;
00318 
00319    ast_mutex_init(&obj->priv_data.lock);
00320    obj->priv_data.magic = AO2_MAGIC;
00321    obj->priv_data.data_size = data_size;
00322    obj->priv_data.ref_counter = 1;
00323    obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */
00324 
00325 #ifdef AO2_DEBUG
00326    ast_atomic_fetchadd_int(&ao2.total_objects, 1);
00327    ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
00328    ast_atomic_fetchadd_int(&ao2.total_refs, 1);
00329 #endif
00330 
00331    /* return a pointer to the user data */
00332    return EXTERNAL_OBJ(obj);
00333 }

static void * internal_ao2_callback ( struct ao2_container c,
const enum search_flags  flags,
void *  cb_fn,
void *  arg,
void *  data,
enum ao2_callback_type  type,
char *  tag,
char *  file,
int  line,
const char *  funcname 
) [static]

Browse the container using different stategies accoding the flags.

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

Definition at line 599 of file astobj2.c.

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

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

00602 {
00603    int i, start, last;  /* search boundaries */
00604    void *ret = NULL;
00605    ao2_callback_fn *cb_default = NULL;
00606    ao2_callback_data_fn *cb_withdata = NULL;
00607    struct ao2_container *multi_container = NULL;
00608    struct ao2_iterator *multi_iterator = NULL;
00609 
00610    if (INTERNAL_OBJ(c) == NULL)  /* safety check on the argument */
00611       return NULL;
00612 
00613    /*
00614     * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
00615     * turned off.  This if statement checks for the special condition
00616     * where multiple items may need to be returned.
00617     */
00618    if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
00619       /* we need to return an ao2_iterator with the results,
00620        * as there could be more than one. the iterator will
00621        * hold the only reference to a container that has all the
00622        * matching objects linked into it, so when the iterator
00623        * is destroyed, the container will be automatically
00624        * destroyed as well.
00625        */
00626       if (!(multi_container = ao2_container_alloc(1, NULL, NULL))) {
00627          return NULL;
00628       }
00629       if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
00630          ao2_ref(multi_container, -1);
00631          return NULL;
00632       }
00633    }
00634 
00635    /* override the match function if necessary */
00636    if (cb_fn == NULL) { /* if NULL, match everything */
00637       if (type == WITH_DATA) {
00638          cb_withdata = cb_true_data;
00639       } else {
00640          cb_default = cb_true;
00641       }
00642    } else {
00643       /* We do this here to avoid the per object casting penalty (even though
00644          that is probably optimized away anyway). */
00645       if (type == WITH_DATA) {
00646          cb_withdata = cb_fn;
00647       } else {
00648          cb_default = cb_fn;
00649       }
00650    }
00651 
00652    /*
00653     * XXX this can be optimized.
00654     * If we have a hash function and lookup by pointer,
00655     * run the hash function. Otherwise, scan the whole container
00656     * (this only for the time being. We need to optimize this.)
00657     */
00658    if ((flags & OBJ_POINTER)) /* we know hash can handle this case */
00659       start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets;
00660    else        /* don't know, let's scan all buckets */
00661       start = i = -1;      /* XXX this must be fixed later. */
00662 
00663    /* determine the search boundaries: i..last-1 */
00664    if (i < 0) {
00665       start = i = 0;
00666       last = c->n_buckets;
00667    } else if ((flags & OBJ_CONTINUE)) {
00668       last = c->n_buckets;
00669    } else {
00670       last = i + 1;
00671    }
00672 
00673    ao2_lock(c);   /* avoid modifications to the content */
00674 
00675    for (; i < last ; i++) {
00676       /* scan the list with prev-cur pointers */
00677       struct bucket_entry *cur;
00678 
00679       AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
00680          int match = (CMP_MATCH | CMP_STOP);
00681 
00682          if (type == WITH_DATA) {
00683             match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
00684          } else {
00685             match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
00686          }
00687 
00688          /* we found the object, performing operations according flags */
00689          if (match == 0) { /* no match, no stop, continue */
00690             continue;
00691          } else if (match == CMP_STOP) {  /* no match but stop, we are done */
00692             i = last;
00693             break;
00694          }
00695 
00696          /* we have a match (CMP_MATCH) here */
00697          if (!(flags & OBJ_NODATA)) {  /* if must return the object, record the value */
00698             /* it is important to handle this case before the unlink */
00699             ret = EXTERNAL_OBJ(cur->astobj);
00700             if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
00701                if (tag)
00702                   __ao2_ref_debug(ret, 1, tag, file, line, funcname);
00703                else
00704                   __ao2_ref(ret, 1);
00705             }
00706          }
00707 
00708          /* If we are in OBJ_MULTIPLE mode and OBJ_NODATE is off, 
00709           * link the object into the container that will hold the results.
00710           */
00711          if (ret && (multi_container != NULL)) {
00712             if (tag) {
00713                __ao2_link_debug(multi_container, ret, tag, file, line, funcname);
00714             } else {
00715                __ao2_link(multi_container, ret);
00716             }
00717             ret = NULL;
00718          }
00719 
00720          if (flags & OBJ_UNLINK) {  /* must unlink */
00721             /* we are going to modify the container, so update version */
00722             ast_atomic_fetchadd_int(&c->version, 1);
00723             AST_LIST_REMOVE_CURRENT(entry);
00724             /* update number of elements */
00725             ast_atomic_fetchadd_int(&c->elements, -1);
00726 
00727             /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container
00728              * must be decremented.
00729              * - When unlinking with OBJ_MULTIPLE the ref from the original container
00730              * must be decremented regardless if OBJ_NODATA is used. This is because the result is
00731              * returned in a new container that already holds its own ref for the object. If the ref
00732              * from the original container is not accounted for here a memory leak occurs. */
00733             if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) {
00734                if (tag)
00735                   __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, funcname);
00736                else
00737                   __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
00738             }
00739             ast_free(cur); /* free the link record */
00740          }
00741 
00742          if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
00743             /* We found our only (or last) match, so force an exit from
00744                the outside loop. */
00745             i = last;
00746             break;
00747          }
00748       }
00749       AST_LIST_TRAVERSE_SAFE_END;
00750 
00751       if (ret) {
00752          break;
00753       }
00754 
00755       if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
00756          /* Move to the beginning to ensure we check every bucket */
00757          i = -1;
00758          last = start;
00759       }
00760    }
00761    ao2_unlock(c);
00762 
00763    /* if multi_container was created, we are returning multiple objects */
00764    if (multi_container != NULL) {
00765       *multi_iterator = ao2_iterator_init(multi_container,
00766                       AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
00767       ao2_ref(multi_container, -1);
00768       return multi_iterator;
00769    } else {
00770       return ret;
00771    }
00772 }

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 420 of file astobj2.c.

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

00422 {
00423    /* XXX maybe consistency check on arguments ? */
00424    /* compute the container size */
00425 
00426    if (!c)
00427       return NULL;
00428    
00429    c->version = 1;   /* 0 is a reserved value here */
00430    c->n_buckets = hash_fn ? n_buckets : 1;
00431    c->hash_fn = hash_fn ? hash_fn : hash_zero;
00432    c->cmp_fn = cmp_fn;
00433 
00434 #ifdef AO2_DEBUG
00435    ast_atomic_fetchadd_int(&ao2.total_containers, 1);
00436 #endif
00437 
00438    return c;
00439 }

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]
static void * internal_ao2_iterator_next ( struct ao2_iterator a,
struct bucket_entry **  q 
) [static]

Definition at line 846 of file astobj2.c.

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

Referenced by __ao2_iterator_next(), and __ao2_iterator_next_debug().

00847 {
00848    int lim;
00849    struct bucket_entry *p = NULL;
00850    void *ret = NULL;
00851 
00852    *q = NULL;
00853    
00854    if (INTERNAL_OBJ(a->c) == NULL)
00855       return NULL;
00856 
00857    if (!(a->flags & AO2_ITERATOR_DONTLOCK))
00858       ao2_lock(a->c);
00859 
00860    /* optimization. If the container is unchanged and
00861     * we have a pointer, try follow it
00862     */
00863    if (a->c->version == a->c_version && (p = a->obj)) {
00864       if ((p = AST_LIST_NEXT(p, entry)))
00865          goto found;
00866       /* nope, start from the next bucket */
00867       a->bucket++;
00868       a->version = 0;
00869       a->obj = NULL;
00870    }
00871 
00872    lim = a->c->n_buckets;
00873 
00874    /* Browse the buckets array, moving to the next
00875     * buckets if we don't find the entry in the current one.
00876     * Stop when we find an element with version number greater
00877     * than the current one (we reset the version to 0 when we
00878     * switch buckets).
00879     */
00880    for (; a->bucket < lim; a->bucket++, a->version = 0) {
00881       /* scan the current bucket */
00882       AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) {
00883          if (p->version > a->version)
00884             goto found;
00885       }
00886    }
00887 
00888 found:
00889    if (p) {
00890       ret = EXTERNAL_OBJ(p->astobj);
00891       if (a->flags & AO2_ITERATOR_UNLINK) {
00892          /* we are going to modify the container, so update version */
00893          ast_atomic_fetchadd_int(&a->c->version, 1);
00894          AST_LIST_REMOVE(&a->c->buckets[a->bucket], p, entry);
00895          /* update number of elements */
00896          ast_atomic_fetchadd_int(&a->c->elements, -1);
00897          a->version = 0;
00898          a->obj = NULL;
00899          a->c_version = a->c->version;
00900          ast_free(p);
00901       } else {
00902          a->version = p->version;
00903          a->obj = p;
00904          a->c_version = a->c->version;
00905          /* inc refcount of returned object */
00906          *q = p;
00907       }
00908    }
00909 
00910    return ret;
00911 }

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 490 of file astobj2.c.

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

Referenced by __ao2_link(), and __ao2_link_debug().

00491 {
00492    int i;
00493    /* create a new list entry */
00494    struct bucket_entry *p;
00495    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00496 
00497    if (obj == NULL)
00498       return NULL;
00499 
00500    if (INTERNAL_OBJ(c) == NULL)
00501       return NULL;
00502 
00503    p = ast_calloc(1, sizeof(*p));
00504    if (!p)
00505       return NULL;
00506 
00507    i = abs(c->hash_fn(user_data, OBJ_POINTER));
00508 
00509    ao2_lock(c);
00510    i %= c->n_buckets;
00511    p->astobj = obj;
00512    p->version = ast_atomic_fetchadd_int(&c->version, 1);
00513    AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
00514    ast_atomic_fetchadd_int(&c->elements, 1);
00515 
00516    /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */
00517    return p;
00518 }

static int internal_ao2_ref ( void *  user_data,
const int  delta 
) [static]

Definition at line 253 of file astobj2.c.

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

Referenced by __ao2_ref(), and __ao2_ref_debug().

00254 {
00255    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00256    int current_value;
00257    int ret;
00258 
00259    if (obj == NULL)
00260       return -1;
00261 
00262    /* if delta is 0, just return the refcount */
00263    if (delta == 0)
00264       return (obj->priv_data.ref_counter);
00265 
00266    /* we modify with an atomic operation the reference counter */
00267    ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
00268    current_value = ret + delta;
00269 
00270 #ifdef AO2_DEBUG  
00271    ast_atomic_fetchadd_int(&ao2.total_refs, delta);
00272 #endif
00273 
00274    /* this case must never happen */
00275    if (current_value < 0)
00276       ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data);
00277 
00278    if (current_value <= 0) { /* last reference, destroy the object */
00279       if (obj->priv_data.destructor_fn != NULL) {
00280          obj->priv_data.destructor_fn(user_data);
00281       }
00282 
00283       ast_mutex_destroy(&obj->priv_data.lock);
00284 #ifdef AO2_DEBUG
00285       ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
00286       ast_atomic_fetchadd_int(&ao2.total_objects, -1);
00287 #endif
00288       /* for safety, zero-out the astobj2 header and also the
00289        * first word of the user-data, which we make sure is always
00290        * allocated. */
00291       memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) );
00292       ast_free(obj);
00293    }
00294 
00295    return ret;
00296 }

static struct astobj2* INTERNAL_OBJ ( void *  user_data  )  [static, read]

convert from a pointer _p to a user-defined object

Returns:
the pointer to the astobj2 structure

Definition at line 112 of file astobj2.c.

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

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

00113 {
00114    struct astobj2 *p;
00115 
00116    if (!user_data) {
00117       ast_log(LOG_ERROR, "user_data is NULL\n");
00118       return NULL;
00119    }
00120 
00121    p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
00122    if (AO2_MAGIC != p->priv_data.magic) {
00123       if (p->priv_data.magic) {
00124          ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
00125             p->priv_data.magic, user_data);
00126       } else {
00127          ast_log(LOG_ERROR,
00128             "bad magic number for object %p. Object is likely destroyed.\n",
00129             user_data);
00130       }
00131       ast_assert(0);
00132       return NULL;
00133    }
00134 
00135    return p;
00136 }


Variable Documentation

FILE* ref_log [static]

Definition at line 35 of file astobj2.c.


Generated on 7 Sep 2017 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1