30 #define DEBUG_THREADS_LOOSE_ABI 42 #define ast_log ast_log_safe 58 #if defined(AO2_DEBUG) 96 #define AO2_MAGIC 0xa70b123 97 #define AO2_WEAK 0xa70b122 98 #define IS_AO2_MAGIC_BAD(p) (AO2_MAGIC != (p->priv_data.magic | 1)) 151 struct ao2_stats ao2;
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)
508 const char *lock_state;
512 fprintf(
ref_log,
"%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
513 user_data, delta,
ast_get_tid(), file, line, func, tag ?:
"");
530 current_value = ret + delta;
539 if (current_value == 1) {
541 struct astobj2 *internal_weakproxy;
559 if (current_value == 1) {
564 destroyed_cb->
cb(weakproxy, destroyed_cb->
data);
572 if (0 < current_value) {
574 #define EXCESSIVE_REF_COUNT 100000 577 char excessive_ref_buf[100];
580 snprintf(excessive_ref_buf,
sizeof(excessive_ref_buf),
581 "Excessive refcount %d reached on ao2 object %p",
582 (
int)current_value, user_data);
589 fprintf(
ref_log,
"%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data,
591 file, line, func, (
int)ret, tag ?:
"");
598 if (current_value < 0) {
600 "Invalid refcount %d on ao2 object %p\n", (
int)current_value, user_data);
603 fprintf(
ref_log,
"%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
604 user_data, delta,
ast_get_tid(), file, line, func, tag ?:
"");
653 "Invalid lock option on ao2 object %p\n", user_data);
654 lock_state =
"invalid";
659 fprintf(
ref_log,
"%p,%d,%d,%s,%d,%s,**destructor**lock-state:%s**,%s\n",
660 user_data, delta,
ast_get_tid(), file, line, func, lock_state, tag ?:
"");
670 __ao2_ref(obj, -1, tag, file, line,
function);
682 void *lockobj,
const char *tag,
const char *
file,
int line,
const char *func)
693 overhead =
sizeof(*obj_mutex);
694 obj_mutex =
__ast_calloc(1, overhead + data_size, file, line, func);
695 if (obj_mutex ==
NULL) {
703 overhead =
sizeof(*obj_rwlock);
704 obj_rwlock =
__ast_calloc(1, overhead + data_size, file, line, func);
705 if (obj_rwlock ==
NULL) {
713 overhead =
sizeof(*obj);
714 obj =
__ast_calloc(1, overhead + data_size, file, line, func);
722 ast_log(
__LOG_ERROR, file, line, func,
"AO2_ALLOC_OPT_LOCK_OBJ requires a non-NULL lockobj.\n");
726 overhead =
sizeof(*obj_lockobj);
727 obj_lockobj =
__ast_calloc(1, overhead + data_size, file, line, func);
728 if (obj_lockobj ==
NULL) {
729 ao2_t_ref(lockobj, -1,
"release lockobj for failed alloc");
756 fprintf(
ref_log,
"%p,+1,%d,%s,%d,%s,**constructor**%zu**%zu**,%s\n",
766 const char *tag,
const char *
file,
int line,
const char *func)
772 const char *tag,
const char *
file,
int line,
const char *func)
775 tag, file, line, func);
791 const char *tag,
const char *
file,
int line,
const char *func)
795 if (data_size <
sizeof(*weakproxy)) {
802 tag, file, line, func);
805 struct astobj2 *weakproxy_internal;
816 const char *tag,
const char *
file,
int line,
const char *func)
822 if (!weakproxy_internal
838 __ao2_ref(obj, +1, tag, file, line, func);
839 __ao2_ref(weakproxy, +1, tag, file, line, func);
847 if (!(flags & OBJ_NOLOCK)) {
860 const char *tag,
const char *
file,
int line,
const char *func)
865 if (!
internal || internal->priv_data.magic !=
AO2_WEAK) {
875 if (internal->priv_data.weakptr) {
876 ret =
__ao2_ref(internal->priv_data.weakptr, delta, tag, file, line, func);
879 if (!(flags & OBJ_NOLOCK)) {
887 const char *tag,
const char *
file,
int line,
const char *func)
892 if (!
internal || internal->priv_data.magic !=
AO2_WEAK) {
902 obj =
internal->priv_data.weakptr;
904 __ao2_ref(obj, +1, tag, file, line, func);
907 if (!(flags & OBJ_NOLOCK)) {
958 if (!(flags & OBJ_NOLOCK)) {
987 if (sub->
cb == destroyed_cb && sub->
data == data) {
998 if (!(flags & OBJ_NOLOCK)) {
1007 static int print_cb(
void *obj,
void *arg,
int flag)
1010 char *s = (
char *)obj;
1023 e->
command =
"astobj2 show stats";
1024 e->
usage =
"Usage: astobj2 show stats\n" 1025 " Show astobj2 show stats\n";
1030 ast_cli(a->
fd,
"Objects : %d\n", ao2.total_objects);
1031 ast_cli(a->
fd,
"Containers : %d\n", ao2.total_containers);
1032 ast_cli(a->
fd,
"Memory : %d\n", ao2.total_mem);
1033 ast_cli(a->
fd,
"Locked : %d\n", ao2.total_locked);
1034 ast_cli(a->
fd,
"Refs : %d\n", ao2.total_refs);
1047 static int prof_id = -1;
1053 e->
usage =
"Usage: astobj2 test <num>\n" 1054 " Runs astobj2 test. Creates 'num' objects,\n" 1055 " and test iterators, callbacks and maybe other stuff\n";
1065 if (prof_id == -1) {
1070 lim = atoi(a->
argv[2]);
1079 ast_cli(a->
fd,
"container allocated as %p\n", c1);
1086 for (i = 0; i < lim; i++) {
1090 ast_cli(a->
fd,
"object %d allocated as %p\n", i, obj);
1091 sprintf(obj,
"-- this is obj %d --", i);
1104 ast_cli(a->
fd,
"testing container cloning\n");
1107 ast_cli(a->
fd,
"Cloned container does not have the same number of objects!\n");
1111 ast_cli(a->
fd,
"testing iterators, remove every second object\n");
1118 ast_cli(a->
fd,
"iterator on <%s>\n", obj);
1124 ast_cli(a->
fd,
"testing iterators again\n");
1127 ast_cli(a->
fd,
"iterator on <%s>\n", obj);
1133 ast_cli(a->
fd,
"testing callbacks again\n");
1136 ast_verbose(
"now you should see an error and possible assertion failure messages:\n");
1147 #if defined(AO2_DEBUG) 1149 AST_CLI_DEFINE(handle_astobj2_stats,
"Print astobj2 statistics"),
1156 #if defined(AO2_DEBUG) 1168 char ref_filename[1024];
1172 ref_log = fopen(ref_filename,
"w");
1174 ast_log(
LOG_ERROR,
"Could not open ref debug log file: %s\n", ref_filename);
1186 #if defined(AO2_DEBUG) #define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
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)
int __ao2_weakproxy_ref_object(void *weakproxy, int delta, int flags, const char *tag, const char *file, int line, const char *func)
Run ao2_t_ref on the object associated with weakproxy.
unsigned int ao2_options_get(void *obj)
Retrieve the ao2 options used to create the object.
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_CLI_DEFINE(fn, txt,...)
Asterisk main include file. File version handling, generic pbx functions.
int __ast_rwlock_trywrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
uint32_t options
The ao2 object option flags.
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_weakproxy_notification_cb)(void *weakproxy, void *data)
ao2_lock_req
Which lock to request.
static void astobj2_cleanup(void)
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
struct ao2_lock_priv mutex
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define ast_rwlock_destroy(rwlock)
Common, private definitions for astobj2.
#define ao2_container_clone(orig, flags)
descriptor for a cli entry.
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.
int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags)
Request notification when weakproxy points to NULL.
Assume that the ao2_container is already locked.
#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag)
Allocate and initialize a list container.
void * __ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn, const char *tag, const char *file, int line, const char *func)
Allocate an ao2_weakproxy object.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define ao2_t_unlink(container, obj, tag)
Remove an object from a container.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
void ast_verbose(const char *fmt,...)
#define __INTERNAL_OBJ_CHECK(user_data, file, line, func)
convert from a pointer _p to a user-defined object
int __ast_rwlock_unlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
void ast_cli(int fd, const char *fmt,...)
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
Unlock an object.
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
#define EXCESSIVE_REF_COUNT
#define INTERNAL_OBJ_LOCKOBJ(user_data)
struct ao2_rwlock_priv rwlock
void __ao2_cleanup(void *obj)
struct __priv_data priv_data
void * ao2_object_get_lockaddr(void *user_data)
Return the mutex lock address of an object.
#define INTERNAL_OBJ_CHECK(user_data)
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Asterisk file paths, configured in asterisk.conf.
int ast_get_tid(void)
Get current thread ID.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define ao2_ref(o, delta)
ao2_destructor_fn destructor_fn
uint32_t lockused
Set to 1 when the lock is used if refdebug is enabled.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
int __ao2_ref(void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
void DO_CRASH_NORETURN __ast_assert_failed(int condition, const char *condition_str, const char *file, int line, const char *function)
#define EXTERNAL_OBJ(_p)
convert from a pointer _p to an astobj2 object
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
struct ao2_weakproxy::@224 destroyed_cb
struct ao2_weakproxy_notification::@339 list
int internal_is_ao2_object(void *user_data)
int __ast_pthread_mutex_unlock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
#define ao2_t_iterator_next(iter, tag)
#define INTERNAL_OBJ(user_data)
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
void(* ao2_destructor_fn)(void *vdoomed)
Typedef for an object destructor.
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
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 log_bad_ao2(void *user_data, const char *file, int line, const char *func)
const char * ast_config_AST_LOG_DIR
#define INTERNAL_OBJ_RWLOCK(user_data)
#define INTERNAL_OBJ_MUTEX(user_data)
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define ast_calloc(num, len)
A wrapper for calloc()
struct __priv_data priv_data
Prototypes for public functions only of internal interest,.
int ao2_weakproxy_unsubscribe(void *weakproxy, ao2_weakproxy_notification_cb destroyed_cb, void *data, int flags)
Remove notification of real object destruction.
#define IS_AO2_MAGIC_BAD(p)
int __ast_rwlock_wrlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
#define ao2_t_bump(obj, tag)
Bump refcount on an AO2 object by one, returning the object.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
void * __ao2_weakproxy_get_object(void *weakproxy, int flags, const char *tag, const char *file, int line, const char *func)
Get the object associated with weakproxy.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags, const char *tag, const char *file, int line, const char *func)
Associate weakproxy with obj.
Structure for rwlock and tracking information.
Standard Command Line Interface.
This struct should be opaque, but it's size is needed.
int __ast_pthread_mutex_lock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
Common, private definitions for astobj2 containers.
enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
struct __priv_data priv_data
struct stasis_forward * sub
ao2_weakproxy_notification_cb cb
int __ast_pthread_mutex_trylock(const char *filename, int lineno, const char *func, const char *mutex_name, ast_mutex_t *t)
void __ao2_cleanup_debug(void *obj, const char *tag, const char *file, int line, const char *function)
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
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 ast_mutex_init(pmutex)
#define ast_mutex_destroy(a)
int __ast_rwlock_tryrdlock(const char *filename, int lineno, const char *func, ast_rwlock_t *t, const char *name)
struct __priv_data priv_data
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
struct ao2_lockobj_priv lockobj
Structure for mutex and tracking information.
#define ast_opt_ref_debug
#define ao2_link(container, obj)
void * __ao2_get_weakproxy(void *obj, const char *tag, const char *file, int line, const char *func)
Get the weakproxy attached to obj.
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)