30#define DEBUG_THREADS_LOOSE_ABI 
   42#define ast_log ast_log_safe 
   96#define AO2_MAGIC   0xa70b123 
   97#define AO2_WEAK    0xa70b122 
   98#define IS_AO2_MAGIC_BAD(p) (AO2_MAGIC != (p->priv_data.magic | 1)) 
  154#define INTERNAL_OBJ_MUTEX(user_data) \ 
  155    ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock))) 
 
  157#define INTERNAL_OBJ_RWLOCK(user_data) \ 
  158    ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock))) 
 
  160#define INTERNAL_OBJ_LOCKOBJ(user_data) \ 
  161    ((struct astobj2_lockobj *) (((char *) (user_data)) - sizeof(struct astobj2_lockobj))) 
 
  163#define INTERNAL_OBJ(user_data) \ 
  164    (struct astobj2 *) ((char *) user_data - sizeof(struct astobj2)) 
 
  171#define __INTERNAL_OBJ_CHECK(user_data, file, line, func) \ 
  173        struct astobj2 *p ## __LINE__; \ 
  175            || !(p ## __LINE__ = INTERNAL_OBJ(user_data)) \ 
  176            || IS_AO2_MAGIC_BAD(p ## __LINE__)) { \ 
  177            log_bad_ao2(user_data, file, line, func); \ 
  178            p ## __LINE__ = NULL; \ 
 
  183#define INTERNAL_OBJ_CHECK(user_data) \ 
  184    __INTERNAL_OBJ_CHECK(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__) 
 
  191#define EXTERNAL_OBJ(_p)    ((_p) == NULL ? NULL : (_p)->user_data) 
  217    snprintf(bad_magic, 
sizeof(bad_magic), 
"bad magic number 0x%x for object %p",
 
 
  315        if (current_value < 0) {
 
 
  445            if (lock_how != orig_lock) {
 
  452            if (!keep_stronger && lock_how != orig_lock) {
 
 
  499    const char *tag, 
const char *file, 
int line, 
const char *func)
 
  505    int32_t current_value;
 
  507    uint32_t privdataoptions;
 
  509    const char *lock_state;
 
  513            fprintf(
ref_log, 
"%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
 
  514                user_data, delta, 
ast_get_tid(), file, line, func, tag ?: 
"");
 
  531    current_value = ret + delta;
 
  540        if (current_value == 1) {
 
  542            struct astobj2 *internal_weakproxy;
 
  560        if (current_value == 1) {
 
  565                destroyed_cb->
cb(weakproxy, destroyed_cb->
data);
 
  573    if (0 < current_value) {
 
  575#define EXCESSIVE_REF_COUNT     100000 
  578            char excessive_ref_buf[100];
 
  581            snprintf(excessive_ref_buf, 
sizeof(excessive_ref_buf),
 
  582                "Excessive refcount %d reached on ao2 object %p",
 
  583                (
int)current_value, user_data);
 
  590            fprintf(
ref_log, 
"%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data,
 
  592                file, line, func, (int)ret, tag ?: 
"");
 
  599    if (current_value < 0) {
 
  601            "Invalid refcount %d on ao2 object %p\n", (
int)current_value, user_data);
 
  604            fprintf(
ref_log, 
"%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
 
  605                user_data, delta, 
ast_get_tid(), file, line, func, tag ?: 
"");
 
  656            "Invalid lock option on ao2 object %p\n", user_data);
 
  657        lock_state = 
"invalid";
 
  662        fprintf(
ref_log, 
"%p,%d,%d,%s,%d,%s,**destructor**lock-state:%s**,%s\n",
 
  663            user_data, delta, 
ast_get_tid(), file, line, func, lock_state, tag ?: 
"");
 
 
  673        __ao2_ref(obj, -1, tag, file, line, function);
 
 
  685    void *lockobj, 
const char *tag, 
const char *file, 
int line, 
const char *func)
 
  696        overhead = 
sizeof(*obj_mutex);
 
  697        obj_mutex = 
__ast_calloc(1, overhead + data_size, file, line, func);
 
  698        if (obj_mutex == 
NULL) {
 
  706        overhead = 
sizeof(*obj_rwlock);
 
  707        obj_rwlock = 
__ast_calloc(1, overhead + data_size, file, line, func);
 
  708        if (obj_rwlock == 
NULL) {
 
  716        overhead = 
sizeof(*obj);
 
  717        obj = 
__ast_calloc(1, overhead + data_size, file, line, func);
 
  725            ast_log(
__LOG_ERROR, file, line, func, 
"AO2_ALLOC_OPT_LOCK_OBJ requires a non-NULL lockobj.\n");
 
  729        overhead = 
sizeof(*obj_lockobj);
 
  730        obj_lockobj = 
__ast_calloc(1, overhead + data_size, file, line, func);
 
  731        if (obj_lockobj == 
NULL) {
 
  732            ao2_t_ref(lockobj, -1, 
"release lockobj for failed alloc");
 
  759        fprintf(
ref_log, 
"%p,+1,%d,%s,%d,%s,**constructor**%zu**%zu**,%s\n",
 
 
  769    const char *tag, 
const char *file, 
int line, 
const char *func)
 
 
  775    const char *tag, 
const char *file, 
int line, 
const char *func)
 
  778        tag, file, line, func);
 
 
  794    const char *tag, 
const char *file, 
int line, 
const char *func)
 
  798    if (data_size < 
sizeof(*weakproxy)) {
 
  805        tag, file, line, func);
 
  808        struct astobj2 *weakproxy_internal;
 
 
  819    const char *tag, 
const char *file, 
int line, 
const char *func)
 
  825    if (!weakproxy_internal
 
  841        __ao2_ref(obj, +1, tag, file, line, func);
 
  842        __ao2_ref(weakproxy, +1, tag, file, line, func);
 
 
  863    const char *tag, 
const char *file, 
int line, 
const char *func)
 
 
  890    const char *tag, 
const char *file, 
int line, 
const char *func)
 
  907        __ao2_ref(obj, +1, tag, file, line, func);
 
 
 1010static int print_cb(
void *obj, 
void *arg, 
int flag)
 
 1013    char *s = (
char *)obj;
 
 1015    ast_cli(
a->fd, 
"string <%s>\n", s);
 
 1026        e->
command = 
"astobj2 show stats";
 
 1027        e->
usage = 
"Usage: astobj2 show stats\n" 
 1028               "       Show astobj2 show stats\n";
 
 1033    ast_cli(
a->fd, 
"Objects    : %d\n", ao2.total_objects);
 
 1034    ast_cli(
a->fd, 
"Containers : %d\n", ao2.total_containers);
 
 1035    ast_cli(
a->fd, 
"Memory     : %d\n", ao2.total_mem);
 
 1036    ast_cli(
a->fd, 
"Locked     : %d\n", ao2.total_locked);
 
 1037    ast_cli(
a->fd, 
"Refs       : %d\n", ao2.total_refs);
 
 1050    static int prof_id = -1;
 
 1056        e->
usage = 
"Usage: astobj2 test <num>\n" 
 1057               "       Runs astobj2 test. Creates 'num' objects,\n" 
 1058               "       and test iterators, callbacks and maybe other stuff\n";
 
 1068    if (prof_id == -1) {
 
 1072    ast_cli(
a->fd, 
"argc %d argv %s %s %s\n", 
a->argc, 
a->argv[0], 
a->argv[1], 
a->argv[2]);
 
 1073    lim = atoi(
a->argv[2]);
 
 1074    ast_cli(
a->fd, 
"called astobj_test\n");
 
 1082    ast_cli(
a->fd, 
"container allocated as %p\n", c1);
 
 1089    for (i = 0; i < lim; i++) {
 
 1093        ast_cli(
a->fd, 
"object %d allocated as %p\n", i, obj);
 
 1094        sprintf(obj, 
"-- this is obj %d --", i);
 
 1104    ast_cli(
a->fd, 
"testing callbacks\n");
 
 1107    ast_cli(
a->fd, 
"testing container cloning\n");
 
 1110        ast_cli(
a->fd, 
"Cloned container does not have the same number of objects!\n");
 
 1114    ast_cli(
a->fd, 
"testing iterators, remove every second object\n");
 
 1121            ast_cli(
a->fd, 
"iterator on <%s>\n", obj);
 
 1127        ast_cli(
a->fd, 
"testing iterators again\n");
 
 1130            ast_cli(
a->fd, 
"iterator on <%s>\n", obj);
 
 1136    ast_cli(
a->fd, 
"testing callbacks again\n");
 
 1139    ast_verbose(
"now you should see an error and possible assertion failure messages:\n");
 
 1142    ast_cli(
a->fd, 
"destroy container\n");
 
 1150#if defined(AO2_DEBUG) 
 1152    AST_CLI_DEFINE(handle_astobj2_stats, 
"Print astobj2 statistics"),
 
 1159#if defined(AO2_DEBUG) 
 
 1171    char ref_filename[1024];
 
 1175        ref_log = fopen(ref_filename, 
"w");
 
 1177            ast_log(
LOG_ERROR, 
"Could not open ref debug log file: %s\n", ref_filename);
 
 1189#if defined(AO2_DEBUG) 
 
Prototypes for public functions only of internal interest,.
void ast_cli_unregister_multiple(void)
Asterisk main include file. File version handling, generic pbx functions.
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
int64_t ast_mark(int, int start1_stop0)
void * __ast_calloc(size_t nmemb, size_t size, const char *file, int lineno, const char *func) attribute_malloc
#define ast_calloc(num, len)
A wrapper for calloc()
enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
#define EXTERNAL_OBJ(_p)
convert from a pointer _p to an astobj2 object
int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags)
Request notification when weakproxy points to NULL.
unsigned int ao2_options_get(void *obj)
Retrieve the ao2 options used to create the object.
void * __ao2_alloc_with_lockobj(size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj, const char *tag, const char *file, int line, const char *func)
#define EXCESSIVE_REF_COUNT
#define INTERNAL_OBJ_LOCKOBJ(user_data)
void * __ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn, const char *tag, const char *file, int line, const char *func)
static void * internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, void *lockobj, const char *tag, const char *file, int line, const char *func)
int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
Try locking– (don't block if fail)
static void astobj2_cleanup(void)
#define __INTERNAL_OBJ_CHECK(user_data, file, line, func)
convert from a pointer _p to a user-defined object
#define IS_AO2_MAGIC_BAD(p)
int __ao2_weakproxy_ref_object(void *weakproxy, int delta, int flags, const char *tag, const char *file, int line, const char *func)
void log_bad_ao2(void *user_data, const char *file, int line, const char *func)
int internal_is_ao2_object(void *user_data)
void * __ao2_weakproxy_get_object(void *weakproxy, int flags, const char *tag, const char *file, int line, const char *func)
int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags, const char *tag, const char *file, int line, const char *func)
void * ao2_object_get_lockaddr(void *user_data)
Return the mutex lock address of an object.
#define INTERNAL_OBJ_CHECK(user_data)
int __ao2_ref(void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
#define INTERNAL_OBJ_MUTEX(user_data)
void __ao2_cleanup(void *obj)
int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
Lock an object.
void __ao2_cleanup_debug(void *obj, const char *tag, const char *file, int line, const char *function)
#define INTERNAL_OBJ_RWLOCK(user_data)
#define INTERNAL_OBJ(user_data)
int ao2_weakproxy_unsubscribe(void *weakproxy, ao2_weakproxy_notification_cb destroyed_cb, void *data, int flags)
Remove notification of real object destruction.
int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
Unlock an object.
void * __ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, const char *file, int line, const char *func)
void * __ao2_get_weakproxy(void *obj, const char *tag, const char *file, int line, const char *func)
#define ao2_t_ref(o, delta, tag)
#define ao2_link(container, obj)
Add an object to a container.
@ AO2_ALLOC_OPT_LOCK_NOLOCK
@ AO2_ALLOC_OPT_LOCK_RWLOCK
@ AO2_ALLOC_OPT_LOCK_MUTEX
@ AO2_ALLOC_OPT_LOCK_MASK
@ AO2_ALLOC_OPT_NO_REF_DEBUG
#define ao2_t_iterator_next(iter, tag)
ao2_lock_req
Which lock to request.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
void(* ao2_weakproxy_notification_cb)(void *weakproxy, void *data)
void(* ao2_destructor_fn)(void *vdoomed)
Typedef for an object destructor.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag)
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_t_bump(obj, tag)
#define ao2_t_unlink(container, obj, tag)
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
#define ao2_container_clone(orig, flags)
Create a clone/copy of the given container.
Common, private definitions for astobj2 containers.
Common, private definitions for astobj2.
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
int __ast_rwlock_wrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
int __ast_rwlock_trywrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
int __ast_rwlock_unlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
#define ast_mutex_init(pmutex)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
#define ast_rwlock_destroy(rwlock)
int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
#define ast_mutex_destroy(a)
int __ast_rwlock_tryrdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
int __ast_rwlock_rdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
#define ast_atomic_fetch_add(ptr, val, memorder)
Support for atomic instructions.
#define ast_opt_ref_debug
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_LOG_DIR
static struct stasis_subscription * sub
Statsd channel stats. Exmaple of how to subscribe to Stasis events.
uint32_t options
The ao2 object option flags.
ao2_destructor_fn destructor_fn
uint32_t lockused
Set to 1 when the lock is used if refdebug is enabled.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
ao2_weakproxy_notification_cb cb
struct ao2_weakproxy_notification::@321 list
This struct should be opaque, but it's size is needed.
struct ao2_weakproxy::@199 destroyed_cb
descriptor for a cli entry.
Structure for mutex and tracking information.
Structure for rwlock and tracking information.
struct ao2_lock_priv mutex
struct __priv_data priv_data
struct __priv_data priv_data
struct ao2_lockobj_priv lockobj
struct ao2_rwlock_priv rwlock
struct __priv_data priv_data
struct __priv_data priv_data
int ast_get_tid(void)
Get current thread ID.
void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)