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)
507 uint32_t privdataoptions;
509 const char *lock_state;
513 fprintf(
ref_log,
"%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
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",
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 ?:
"");
685 void *lockobj,
const char *tag,
const char *
file,
int line,
const char *func)
696 overhead =
sizeof(*obj_mutex);
698 if (obj_mutex ==
NULL) {
706 overhead =
sizeof(*obj_rwlock);
708 if (obj_rwlock ==
NULL) {
716 overhead =
sizeof(*obj);
729 overhead =
sizeof(*obj_lockobj);
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
863 const char *tag,
const char *
file,
int line,
const char *func)
890 const char *tag,
const char *
file,
int line,
const char *func)
990 if (
sub->cb == destroyed_cb &&
sub->data ==
data) {
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,.
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.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
void ast_verbose(const char *fmt,...)
#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
struct stasis_forward * sub
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::@299 list
This struct should be opaque, but it's size is needed.
struct ao2_weakproxy::@186 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)