summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/asterisk.c8
-rw-r--r--main/astobj2.c265
-rw-r--r--main/astobj2_container.c209
-rw-r--r--main/astobj2_container_private.h18
-rw-r--r--main/astobj2_hash.c93
-rw-r--r--main/astobj2_private.h19
-rw-r--r--main/astobj2_rbtree.c73
-rw-r--r--main/channel.c12
-rw-r--r--main/channel_internal_api.c12
-rw-r--r--main/format_cache.c14
-rw-r--r--main/format_cap.c43
-rw-r--r--main/loader.c44
12 files changed, 268 insertions, 542 deletions
diff --git a/main/asterisk.c b/main/asterisk.c
index 574451c65..86a190bc8 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -3424,6 +3424,12 @@ static void ast_readconfig(void)
ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
+#ifdef REF_DEBUG
+ /* The REF_DEBUG compiler flag is now only used to enable refdebug by default.
+ * Support for debugging reference counts is always compiled in. */
+ ast_set2_flag(&ast_options, 1, AST_OPT_FLAG_REF_DEBUG);
+#endif
+
ast_set_default_eid(&ast_eid_default);
/* no asterisk.conf? no problem, use buildtime config! */
@@ -3494,6 +3500,8 @@ static void ast_readconfig(void)
if (sscanf(v->value, "%30d", &option_debug) != 1) {
option_debug = ast_true(v->value);
}
+ } else if (!strcasecmp(v->name, "refdebug")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG);
#if HAVE_WORKING_FORK
/* Disable forking (-f at startup) */
} else if (!strcasecmp(v->name, "nofork")) {
diff --git a/main/astobj2.c b/main/astobj2.c
index edf1e95ab..c5b5cd957 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -118,52 +118,73 @@ struct ao2_stats ao2;
#define INTERNAL_OBJ_RWLOCK(user_data) \
((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
+#define INTERNAL_OBJ(user_data) \
+ (struct astobj2 *) ((char *) user_data - sizeof(struct astobj2))
+
/*!
* \brief convert from a pointer _p to a user-defined object
*
* \return the pointer to the astobj2 structure
*/
-static struct astobj2 *INTERNAL_OBJ(void *user_data)
+#define __INTERNAL_OBJ_CHECK(user_data, file, line, func) \
+ ({ \
+ struct astobj2 *p ## __LINE__; \
+ if (!user_data \
+ || !(p ## __LINE__ = INTERNAL_OBJ(user_data)) \
+ || IS_AO2_MAGIC_BAD(p ## __LINE__)) { \
+ log_bad_ao2(user_data, file, line, func); \
+ p ## __LINE__ = NULL; \
+ } \
+ (p ## __LINE__); \
+ })
+
+#define INTERNAL_OBJ_CHECK(user_data) \
+ __INTERNAL_OBJ_CHECK(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+/*!
+ * \brief convert from a pointer _p to an astobj2 object
+ *
+ * \return the pointer to the user-defined portion.
+ */
+#define EXTERNAL_OBJ(_p) ((_p) == NULL ? NULL : (_p)->user_data)
+
+int internal_is_ao2_object(void *user_data)
{
struct astobj2 *p;
if (!user_data) {
- ast_log(LOG_ERROR, "user_data is NULL\n");
- return NULL;
+ return 0;
}
- p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
- if (IS_AO2_MAGIC_BAD(p)) {
- if (p->priv_data.magic) {
- ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
- p->priv_data.magic, user_data);
- } else {
- ast_log(LOG_ERROR,
- "bad magic number for object %p. Object is likely destroyed.\n",
- user_data);
- }
- ast_assert(0);
- return NULL;
- }
+ p = INTERNAL_OBJ(user_data);
- return p;
+ return !p || IS_AO2_MAGIC_BAD(p) ? 0 : 1;
}
-/*!
- * \brief convert from a pointer _p to an astobj2 object
- *
- * \return the pointer to the user-defined portion.
- */
-#define EXTERNAL_OBJ(_p) ((_p) == NULL ? NULL : (_p)->user_data)
-
-int is_ao2_object(void *user_data)
+void log_bad_ao2(void *user_data, const char *file, int line, const char *func)
{
- return (INTERNAL_OBJ(user_data) != NULL);
+ struct astobj2 *p;
+
+ if (!user_data) {
+ ast_log(__LOG_ERROR, file, line, func, "user_data is NULL\n");
+ return;
+ }
+
+ p = INTERNAL_OBJ(user_data);
+ if (p->priv_data.magic) {
+ ast_log(__LOG_ERROR, file, line, func,
+ "bad magic number 0x%x for object %p\n",
+ p->priv_data.magic, user_data);
+ } else {
+ ast_log(__LOG_ERROR, file, line, func,
+ "bad magic number for object %p. Object is likely destroyed.\n",
+ user_data);
+ }
}
int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
{
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
+ struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
int res = 0;
@@ -221,7 +242,7 @@ int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, co
int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
{
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
+ struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
int res = 0;
@@ -271,7 +292,7 @@ int __ao2_unlock(void *user_data, const char *file, const char *func, int line,
int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
{
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
+ struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
int res = 0;
@@ -393,9 +414,11 @@ enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int
void *ao2_object_get_lockaddr(void *user_data)
{
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
+ struct astobj2 *obj;
struct astobj2_lock *obj_mutex;
+ obj = INTERNAL_OBJ_CHECK(user_data);
+
if (obj == NULL) {
ast_assert(0);
return NULL;
@@ -412,9 +435,10 @@ void *ao2_object_get_lockaddr(void *user_data)
return NULL;
}
-static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *func)
+int __ao2_ref(void *user_data, int delta,
+ const char *tag, const char *file, int line, const char *func)
{
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
+ struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
struct astobj2_lock *obj_mutex;
struct astobj2_rwlock *obj_rwlock;
int current_value;
@@ -422,6 +446,11 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
void *weakproxy = NULL;
if (obj == NULL) {
+ if (ref_log && user_data) {
+ fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
+ user_data, delta, ast_get_tid(), file, line, func, tag ?: "");
+ fflush(ref_log);
+ }
ast_assert(0);
return -1;
}
@@ -446,7 +475,9 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
if (weakproxy) {
if (current_value == 1) {
/* The only remaining reference is the one owned by the weak object */
- struct astobj2 *internal_weakproxy = INTERNAL_OBJ(weakproxy);
+ struct astobj2 *internal_weakproxy;
+
+ internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy);
/* Unlink the obj from the weak proxy */
internal_weakproxy->priv_data.weakptr = NULL;
@@ -468,6 +499,12 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
if (0 < current_value) {
/* The object still lives. */
+ if (ref_log && tag) {
+ fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data,
+ (delta < 0 ? "" : "+"), delta, ast_get_tid(),
+ file, line, func, ret, tag);
+ fflush(ref_log);
+ }
return ret;
}
@@ -475,6 +512,12 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
if (current_value < 0) {
ast_log(__LOG_ERROR, file, line, func,
"Invalid refcount %d on ao2 object %p\n", current_value, user_data);
+ if (ref_log) {
+ /* Log to ref_log invalid even if (tag == NULL) */
+ fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
+ user_data, delta, ast_get_tid(), file, line, func, tag ?: "");
+ fflush(ref_log);
+ }
ast_assert(0);
/* stop here even if assert doesn't DO_CRASH */
return -1;
@@ -515,51 +558,19 @@ static int internal_ao2_ref(void *user_data, int delta, const char *file, int li
break;
}
- return ret;
-}
-
-int __ao2_ref_debug(void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
-{
- struct astobj2 *obj = INTERNAL_OBJ(user_data);
- int old_refcount = -1;
-
- if (obj) {
- old_refcount = internal_ao2_ref(user_data, delta, file, line, func);
- }
-
- if (ref_log && user_data) {
- if (!obj) {
- /* Invalid object: Bad magic number. */
- fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
- user_data, delta, ast_get_tid(), file, line, func, tag);
- fflush(ref_log);
- } else if (old_refcount + delta == 0) {
- fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n",
- user_data, delta, ast_get_tid(), file, line, func, tag);
- fflush(ref_log);
- } else if (delta != 0) {
- fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data, (delta < 0 ? "" : "+"),
- delta, ast_get_tid(), file, line, func, old_refcount, tag);
- fflush(ref_log);
- }
- }
-
- if (obj == NULL) {
- ast_assert(0);
+ if (ref_log && tag) {
+ fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n",
+ user_data, delta, ast_get_tid(), file, line, func, tag);
+ fflush(ref_log);
}
- return old_refcount;
-}
-
-int __ao2_ref(void *user_data, int delta)
-{
- return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__);
+ return ret;
}
void __ao2_cleanup_debug(void *obj, const char *tag, const char *file, int line, const char *function)
{
if (obj) {
- __ao2_ref_debug(obj, -1, tag, file, line, function);
+ __ao2_ref(obj, -1, tag, file, line, function);
}
}
@@ -570,7 +581,8 @@ void __ao2_cleanup(void *obj)
}
}
-static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *file, int line, const char *func)
+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)
{
/* allocation */
struct astobj2 *obj;
@@ -633,43 +645,27 @@ static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_f
ast_atomic_fetchadd_int(&ao2.total_refs, 1);
#endif
+ if (ref_log && tag) {
+ fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n",
+ EXTERNAL_OBJ(obj), ast_get_tid(), file, line, func, tag);
+ fflush(ref_log);
+ }
+
/* return a pointer to the user data */
return EXTERNAL_OBJ(obj);
}
unsigned int ao2_options_get(void *obj)
{
- struct astobj2 *orig_obj = INTERNAL_OBJ(obj);
+ struct astobj2 *orig_obj;
+
+ orig_obj = INTERNAL_OBJ_CHECK(obj);
if (!orig_obj) {
return 0;
}
return orig_obj->priv_data.options;
}
-void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag,
- const char *file, int line, const char *func, int ref_debug)
-{
- /* allocation */
- void *obj;
-
- if ((obj = internal_ao2_alloc(data_size, destructor_fn, options, file, line, func)) == NULL) {
- return NULL;
- }
-
- if (ref_log) {
- fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n", obj, ast_get_tid(), file, line, func, tag);
- fflush(ref_log);
- }
-
- /* return a pointer to the user data */
- return obj;
-}
-
-void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options)
-{
- return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__);
-}
-
void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
{
@@ -687,11 +683,7 @@ void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, co
/* Release the held ao2 object. */
if (holder->obj) {
- if (tag) {
- __ao2_ref_debug(holder->obj, -1, tag, file, line, func);
- } else {
- __ao2_ref(holder->obj, -1);
- }
+ __ao2_ref(holder->obj, -1, tag, file, line, func);
holder->obj = NULL;
}
@@ -715,11 +707,7 @@ void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const c
}
if (obj) {
- if (tag) {
- __ao2_ref_debug(obj, +1, tag, file, line, func);
- } else {
- __ao2_ref(obj, +1);
- }
+ __ao2_ref(obj, +1, tag, file, line, func);
}
obj_old = holder->obj;
holder->obj = obj;
@@ -735,11 +723,7 @@ int __ao2_global_obj_replace_unref(struct ao2_global_obj *holder, void *obj, con
obj_old = __ao2_global_obj_replace(holder, obj, tag, file, line, func, name);
if (obj_old) {
- if (tag) {
- __ao2_ref_debug(obj_old, -1, tag, file, line, func);
- } else {
- __ao2_ref(obj_old, -1);
- }
+ __ao2_ref(obj_old, -1, tag, file, line, func);
return 1;
}
return 0;
@@ -764,11 +748,7 @@ void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const
obj = holder->obj;
if (obj) {
- if (tag) {
- __ao2_ref_debug(obj, +1, tag, file, line, func);
- } else {
- __ao2_ref(obj, +1);
- }
+ __ao2_ref(obj, +1, tag, file, line, func);
}
__ast_rwlock_unlock(file, line, func, &holder->lock, name);
@@ -798,12 +778,14 @@ void *__ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn,
return NULL;
}
- weakproxy = __ao2_alloc_debug(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_MUTEX,
- tag, file, line, func, 1);
+ weakproxy = __ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_MUTEX,
+ tag, file, line, func);
if (weakproxy) {
- struct astobj2 *weakproxy_internal = INTERNAL_OBJ(weakproxy);
+ struct astobj2 *weakproxy_internal;
+ /* Just created weakproxy, no need to check if it's valid. */
+ weakproxy_internal = INTERNAL_OBJ(weakproxy);
weakproxy_internal->priv_data.magic = AO2_WEAK;
}
@@ -813,8 +795,8 @@ void *__ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn,
int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
const char *tag, const char *file, int line, const char *func)
{
- struct astobj2 *weakproxy_internal = INTERNAL_OBJ(weakproxy);
- struct astobj2 *obj_internal = INTERNAL_OBJ(obj);
+ struct astobj2 *weakproxy_internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
+ struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func);
int ret = -1;
if (!weakproxy_internal
@@ -833,8 +815,8 @@ int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
}
if (!weakproxy_internal->priv_data.weakptr) {
- __ao2_ref_debug(obj, +1, tag, file, line, func);
- __ao2_ref_debug(weakproxy, +1, tag, file, line, func);
+ __ao2_ref(obj, +1, tag, file, line, func);
+ __ao2_ref(weakproxy, +1, tag, file, line, func);
weakproxy_internal->priv_data.weakptr = obj;
obj_internal->priv_data.weakptr = weakproxy;
@@ -857,7 +839,7 @@ int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
void *__ao2_weakproxy_get_object(void *weakproxy, int flags,
const char *tag, const char *file, int line, const char *func)
{
- struct astobj2 *internal = INTERNAL_OBJ(weakproxy);
+ struct astobj2 *internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
void *obj;
if (!internal || internal->priv_data.magic != AO2_WEAK) {
@@ -872,7 +854,7 @@ void *__ao2_weakproxy_get_object(void *weakproxy, int flags,
obj = internal->priv_data.weakptr;
if (obj) {
- __ao2_ref_debug(obj, +1, tag, file, line, func);
+ __ao2_ref(obj, +1, tag, file, line, func);
}
if (!(flags & OBJ_NOLOCK)) {
@@ -884,7 +866,7 @@ void *__ao2_weakproxy_get_object(void *weakproxy, int flags,
void *__ao2_get_weakproxy(void *obj, const char *tag, const char *file, int line, const char *func)
{
- struct astobj2 *obj_internal = INTERNAL_OBJ(obj);
+ struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func);
if (!obj_internal || obj_internal->priv_data.magic != AO2_MAGIC) {
/* This method is meant to be run on normal ao2 objects! */
@@ -895,13 +877,13 @@ void *__ao2_get_weakproxy(void *obj, const char *tag, const char *file, int line
return NULL;
}
- __ao2_ref_debug(obj_internal->priv_data.weakptr, +1, tag, file, line, func);
+ __ao2_ref(obj_internal->priv_data.weakptr, +1, tag, file, line, func);
return obj_internal->priv_data.weakptr;
}
int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags)
{
- struct astobj2 *weakproxy_internal = INTERNAL_OBJ(weakproxy);
+ struct astobj2 *weakproxy_internal = INTERNAL_OBJ_CHECK(weakproxy);
int ret = -1;
if (!weakproxy_internal || weakproxy_internal->priv_data.magic != AO2_WEAK) {
@@ -936,7 +918,7 @@ int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, v
int ao2_weakproxy_unsubscribe(void *weakproxy, ao2_weakproxy_notification_cb destroyed_cb, void *data, int flags)
{
- struct astobj2 *internal_weakproxy = INTERNAL_OBJ(weakproxy);
+ struct astobj2 *internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy);
struct ao2_weakproxy *weak;
struct ao2_weakproxy_notification *sub;
int ret = 0;
@@ -1123,29 +1105,28 @@ static void astobj2_cleanup(void)
#if defined(AO2_DEBUG)
ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
#endif
-#ifdef REF_DEBUG
- fclose(ref_log);
- ref_log = NULL;
-#endif
+
+ if (ast_opt_ref_debug) {
+ fclose(ref_log);
+ ref_log = NULL;
+ }
}
int astobj2_init(void)
{
-#ifdef REF_DEBUG
char ref_filename[1024];
-#endif
if (container_init() != 0) {
return -1;
}
-#ifdef REF_DEBUG
- snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
- ref_log = fopen(ref_filename, "w");
- if (!ref_log) {
- ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
+ if (ast_opt_ref_debug) {
+ snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
+ ref_log = fopen(ref_filename, "w");
+ if (!ref_log) {
+ ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
+ }
}
-#endif
#if defined(AO2_DEBUG)
ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
diff --git a/main/astobj2_container.c b/main/astobj2_container.c
index 07d10b9f9..c00da9fd4 100644
--- a/main/astobj2_container.c
+++ b/main/astobj2_container.c
@@ -49,11 +49,7 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag
if ((flags & AO2_UNLINK_NODE_UNLINK_OBJECT)
&& !(flags & AO2_UNLINK_NODE_NOUNREF_OBJECT)) {
- if (tag) {
- __ao2_ref_debug(node->obj, -1, tag, file, line, func);
- } else {
- ao2_t_ref(node->obj, -1, "Remove obj from container");
- }
+ __ao2_ref(node->obj, -1, tag ?: "Remove obj from container", file, line, func);
}
node->obj = NULL;
@@ -76,7 +72,7 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag
if (flags & AO2_UNLINK_NODE_UNREF_NODE) {
/* Remove node from container */
- __ao2_ref(node, -1);
+ ao2_t_ref(node, -1, NULL);
}
return 1;
@@ -97,13 +93,15 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag
* \retval 0 on errors.
* \retval 1 on success.
*/
-static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
+int __ao2_link(struct ao2_container *self, void *obj_new, int flags,
+ const char *tag, const char *file, int line, const char *func)
{
int res;
enum ao2_lock_req orig_lock;
struct ao2_container_node *node;
- if (!is_ao2_object(obj_new) || !is_ao2_object(self)
+ if (!__is_ao2_object(obj_new, file, line, func)
+ || !__is_ao2_object(self, file, line, func)
|| !self->v_table || !self->v_table->new_node || !self->v_table->insert) {
/* Sanity checks. */
ast_assert(0);
@@ -147,7 +145,7 @@ static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flag
res = 1;
break;
case AO2_CONTAINER_INSERT_NODE_REJECTED:
- __ao2_ref(node, -1);
+ ao2_t_ref(node, -1, NULL);
break;
}
}
@@ -161,16 +159,6 @@ static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flag
return res;
}
-int __ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
-{
- return internal_ao2_link(c, obj_new, flags, tag, file, line, func);
-}
-
-int __ao2_link(struct ao2_container *c, void *obj_new, int flags)
-{
- return internal_ao2_link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
-}
-
/*!
* \brief another convenience function is a callback that matches on address
*/
@@ -183,10 +171,10 @@ int ao2_match_by_addr(void *user_data, void *arg, int flags)
* Unlink an object from the container
* and destroy the associated * bucket_entry structure.
*/
-void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
+void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags,
const char *tag, const char *file, int line, const char *func)
{
- if (!is_ao2_object(user_data)) {
+ if (!__is_ao2_object(user_data, file, line, func)) {
/* Sanity checks. */
ast_assert(0);
return NULL;
@@ -194,22 +182,7 @@ void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
flags &= ~OBJ_SEARCH_MASK;
flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
- __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
-
- return NULL;
-}
-
-void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags)
-{
- if (!is_ao2_object(user_data)) {
- /* Sanity checks. */
- ast_assert(0);
- return NULL;
- }
-
- flags &= ~OBJ_SEARCH_MASK;
- flags |= (OBJ_UNLINK | OBJ_SEARCH_OBJECT | OBJ_NODATA);
- __ao2_callback(c, flags, ao2_match_by_addr, user_data);
+ __ao2_callback(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
return NULL;
}
@@ -268,8 +241,8 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
struct ao2_container *multi_container = NULL;
struct ao2_iterator *multi_iterator = NULL;
- if (!is_ao2_object(self) || !self->v_table || !self->v_table->traverse_first
- || !self->v_table->traverse_next) {
+ if (!__is_ao2_object(self, file, line, func) || !self->v_table
+ || !self->v_table->traverse_first || !self->v_table->traverse_next) {
/* Sanity checks. */
ast_assert(0);
return NULL;
@@ -376,12 +349,7 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
* Link the object into the container that will hold the
* results.
*/
- if (tag) {
- __ao2_link_debug(multi_container, node->obj, flags,
- tag, file, line, func);
- } else {
- __ao2_link(multi_container, node->obj, flags);
- }
+ __ao2_link(multi_container, node->obj, flags, tag, file, line, func);
} else {
ret = node->obj;
/* Returning a single object. */
@@ -390,11 +358,7 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
* Bump the ref count since we are not going to unlink and
* transfer the container's object ref to the returned object.
*/
- if (tag) {
- __ao2_ref_debug(ret, 1, tag, file, line, func);
- } else {
- ao2_t_ref(ret, 1, "Traversal found object");
- }
+ __ao2_ref(ret, 1, tag ?: "Traversal found object", file, line, func);
}
}
}
@@ -418,7 +382,7 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
}
if (node) {
/* Unref the node from self->v_table->traverse_first/traverse_next() */
- __ao2_ref(node, -1);
+ ao2_t_ref(node, -1, NULL);
}
if (flags & OBJ_NOLOCK) {
@@ -439,36 +403,24 @@ static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags
}
}
-void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
+void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
const char *func)
{
return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, tag, file, line, func);
}
-void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
- ao2_callback_fn *cb_fn, void *arg)
-{
- return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, NULL, NULL, 0, NULL);
-}
-
-void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
+void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
int line, const char *func)
{
return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, tag, file, line, func);
}
-void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
- ao2_callback_data_fn *cb_fn, void *arg, void *data)
-{
- return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, NULL, NULL, 0, NULL);
-}
-
/*!
* the find function just invokes the default callback with some reasonable flags.
*/
-void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
+void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags,
const char *tag, const char *file, int line, const char *func)
{
void *arged = (void *) arg;/* Done to avoid compiler const warning */
@@ -478,19 +430,7 @@ void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_fla
ast_assert(0);
return NULL;
}
- return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
-}
-
-void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
-{
- void *arged = (void *) arg;/* Done to avoid compiler const warning */
-
- if (!c) {
- /* Sanity checks. */
- ast_assert(0);
- return NULL;
- }
- return __ao2_callback(c, flags, c->cmp_fn, arged);
+ return __ao2_callback(c, flags, c->cmp_fn, arged, tag, file, line, func);
}
/*!
@@ -520,6 +460,12 @@ void ao2_iterator_restart(struct ao2_iterator *iter)
if (iter->last_node) {
enum ao2_lock_req orig_lock;
+ if (!is_ao2_object(iter->c)) {
+ /* Sanity check. */
+ ast_assert(0);
+ return;
+ }
+
/*
* Do a read lock in case the container node unref does not
* destroy the node. If the container node is destroyed then
@@ -532,7 +478,7 @@ void ao2_iterator_restart(struct ao2_iterator *iter)
ao2_rdlock(iter->c);
}
- __ao2_ref(iter->last_node, -1);
+ ao2_t_ref(iter->last_node, -1, NULL);
iter->last_node = NULL;
if (iter->flags & AO2_ITERATOR_DONTLOCK) {
@@ -568,16 +514,15 @@ void ao2_iterator_cleanup(struct ao2_iterator *iter)
}
}
-/*
- * move to the next element in the container.
- */
-static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
+void *__ao2_iterator_next(struct ao2_iterator *iter,
+ const char *tag, const char *file, int line, const char *func)
{
enum ao2_lock_req orig_lock;
struct ao2_container_node *node;
void *ret;
- if (!is_ao2_object(iter->c) || !iter->c->v_table || !iter->c->v_table->iterator_next) {
+ if (!__is_ao2_object(iter->c, file, line, func)
+ || !iter->c->v_table || !iter->c->v_table->iterator_next) {
/* Sanity checks. */
ast_assert(0);
return NULL;
@@ -614,14 +559,10 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *t
/* Transfer the container's node ref to the iterator. */
} else {
/* Bump ref of returned object */
- if (tag) {
- __ao2_ref_debug(ret, +1, tag, file, line, func);
- } else {
- ao2_t_ref(ret, +1, "Next iterator object.");
- }
+ __ao2_ref(ret, +1, tag ?: "Next iterator object.", file, line, func);
/* Bump the container's node ref for the iterator. */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
}
} else {
/* The iteration has completed. */
@@ -631,7 +572,7 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *t
/* Replace the iterator's node */
if (iter->last_node) {
- __ao2_ref(iter->last_node, -1);
+ ao2_t_ref(iter->last_node, -1, NULL);
}
iter->last_node = node;
@@ -644,16 +585,6 @@ static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *t
return ret;
}
-void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
-{
- return internal_ao2_iterator_next(iter, tag, file, line, func);
-}
-
-void *__ao2_iterator_next(struct ao2_iterator *iter)
-{
- return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
-}
-
int ao2_iterator_count(struct ao2_iterator *iter)
{
return ao2_container_count(iter->c);
@@ -665,26 +596,8 @@ void container_destruct(void *_c)
/* Unlink any stored objects in the container. */
c->destroying = 1;
- __ao2_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
-
- /* Perform any extra container cleanup. */
- if (c->v_table && c->v_table->destroy) {
- c->v_table->destroy(c);
- }
-
-#if defined(AO2_DEBUG)
- ast_atomic_fetchadd_int(&ao2.total_containers, -1);
-#endif
-}
-
-void container_destruct_debug(void *_c)
-{
- struct ao2_container *c = _c;
-
- /* Unlink any stored objects in the container. */
- c->destroying = 1;
- __ao2_callback_debug(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL,
- "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
+ ao2_t_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL,
+ "container_destruct called");
/* Perform any extra container cleanup. */
if (c->v_table && c->v_table->destroy) {
@@ -712,7 +625,7 @@ static int dup_obj_cb(void *obj, void *arg, int flags)
{
struct ao2_container *dest = arg;
- return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
+ return ao2_t_link_flags(dest, obj, OBJ_NOLOCK, NULL) ? 0 : (CMP_MATCH | CMP_STOP);
}
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
@@ -724,14 +637,14 @@ int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enu
ao2_rdlock(src);
ao2_wrlock(dest);
}
- obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
+ obj = ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
if (obj) {
/* Failed to put this obj into the dest container. */
ao2_t_ref(obj, -1, "Failed to put this object into the dest container.");
/* Remove all items from the dest container. */
- __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
- NULL);
+ ao2_t_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
+ NULL, NULL);
res = -1;
}
if (!(flags & OBJ_NOLOCK)) {
@@ -742,18 +655,19 @@ int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enu
return res;
}
-struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags)
+struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func)
{
struct ao2_container *clone;
int failed;
/* Create the clone container with the same properties as the original. */
- if (!is_ao2_object(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone) {
+ if (!__is_ao2_object(orig, file, line, func)
+ || !orig->v_table || !orig->v_table->alloc_empty_clone) {
/* Sanity checks. */
ast_assert(0);
return NULL;
}
- clone = orig->v_table->alloc_empty_clone(orig);
+ clone = orig->v_table->alloc_empty_clone(orig, tag, file, line, func);
if (!clone) {
return NULL;
}
@@ -767,42 +681,7 @@ struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum sea
}
if (failed) {
/* Object copy into the clone container failed. */
- ao2_t_ref(clone, -1, "Clone creation failed.");
- clone = NULL;
- }
- return clone;
-}
-
-struct ao2_container *__ao2_container_clone_debug(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug)
-{
- struct ao2_container *clone;
- int failed;
-
- /* Create the clone container with the same properties as the original. */
- if (!is_ao2_object(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone_debug) {
- /* Sanity checks. */
- ast_assert(0);
- return NULL;
- }
- clone = orig->v_table->alloc_empty_clone_debug(orig, tag, file, line, func, ref_debug);
- if (!clone) {
- return NULL;
- }
-
- if (flags & OBJ_NOLOCK) {
- ao2_wrlock(clone);
- }
- failed = ao2_container_dup(clone, orig, flags);
- if (flags & OBJ_NOLOCK) {
- ao2_unlock(clone);
- }
- if (failed) {
- /* Object copy into the clone container failed. */
- if (ref_debug) {
- __ao2_ref_debug(clone, -1, tag, file, line, func);
- } else {
- ao2_t_ref(clone, -1, "Clone creation failed.");
- }
+ __ao2_ref(clone, -1, tag ?: "Clone creation failed", file, line, func);
clone = NULL;
}
return clone;
diff --git a/main/astobj2_container_private.h b/main/astobj2_container_private.h
index 07779a5f9..3651ca41f 100644
--- a/main/astobj2_container_private.h
+++ b/main/astobj2_container_private.h
@@ -87,26 +87,15 @@ typedef void (*ao2_container_destroy_fn)(struct ao2_container *self);
* \brief Create an empty copy of this container.
*
* \param self Container to operate upon.
- *
- * \retval empty-container on success.
- * \retval NULL on error.
- */
-typedef struct ao2_container *(*ao2_container_alloc_empty_clone_fn)(struct ao2_container *self);
-
-/*!
- * \brief Create an empty copy of this container. (Debug version)
- *
- * \param self Container to operate upon.
* \param tag used for debugging.
* \param file Debug file name invoked from
* \param line Debug line invoked from
* \param func Debug function name invoked from
- * \param ref_debug TRUE if to output a debug reference message.
*
* \retval empty-container on success.
* \retval NULL on error.
*/
-typedef struct ao2_container *(*ao2_container_alloc_empty_clone_debug_fn)(struct ao2_container *self, const char *tag, const char *file, int line, const char *func, int ref_debug);
+typedef struct ao2_container *(*ao2_container_alloc_empty_clone_fn)(struct ao2_container *self, const char *tag, const char *file, int line, const char *func);
/*!
* \brief Create a new container node.
@@ -250,8 +239,6 @@ struct ao2_container_methods {
ao2_container_destroy_fn destroy;
/*! \brief Create an empty copy of this container. */
ao2_container_alloc_empty_clone_fn alloc_empty_clone;
- /*! \brief Create an empty copy of this container. (Debug version) */
- ao2_container_alloc_empty_clone_debug_fn alloc_empty_clone_debug;
/*! Create a new container node. */
ao2_container_new_node_fn new_node;
/*! Insert a node into this container. */
@@ -336,10 +323,9 @@ int __container_unlink_node_debug(struct ao2_container_node *node, uint32_t flag
const char *tag, const char *file, int line, const char *func);
#define __container_unlink_node(node, flags) \
- __container_unlink_node_debug(node, flags, NULL, NULL, 0, NULL)
+ __container_unlink_node_debug(node, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__)
void container_destruct(void *_c);
-void container_destruct_debug(void *_c);
int container_init(void);
#endif /* ASTOBJ2_CONTAINER_PRIVATE_H_ */
diff --git a/main/astobj2_hash.c b/main/astobj2_hash.c
index 110dd1602..91ad2d2d0 100644
--- a/main/astobj2_hash.c
+++ b/main/astobj2_hash.c
@@ -104,47 +104,27 @@ struct hash_traversal_state_check {
/*!
* \internal
* \brief Create an empty copy of this container.
- * \since 12.0.0
- *
- * \param self Container to operate upon.
- *
- * \retval empty-clone-container on success.
- * \retval NULL on error.
- */
-static struct ao2_container *hash_ao2_alloc_empty_clone(struct ao2_container_hash *self)
-{
- if (!is_ao2_object(self)) {
- return NULL;
- }
-
- return ao2_t_container_alloc_hash(ao2_options_get(self), self->common.options, self->n_buckets,
- self->hash_fn, self->common.sort_fn, self->common.cmp_fn, "Clone hash container");
-}
-
-/*!
- * \internal
- * \brief Create an empty copy of this container. (Debug version)
- * \since 12.0.0
+ * \since 14.0.0
*
* \param self Container to operate upon.
* \param tag used for debugging.
* \param file Debug file name invoked from
* \param line Debug line invoked from
* \param func Debug function name invoked from
- * \param ref_debug TRUE if to output a debug reference message.
*
* \retval empty-clone-container on success.
* \retval NULL on error.
*/
-static struct ao2_container *hash_ao2_alloc_empty_clone_debug(struct ao2_container_hash *self, const char *tag, const char *file, int line, const char *func, int ref_debug)
+static struct ao2_container *hash_ao2_alloc_empty_clone(struct ao2_container_hash *self,
+ const char *tag, const char *file, int line, const char *func)
{
- if (!is_ao2_object(self)) {
+ if (!__is_ao2_object(self, file, line, func)) {
return NULL;
}
- return __ao2_container_alloc_hash_debug(ao2_options_get(self), self->common.options,
+ return __ao2_container_alloc_hash(ao2_options_get(self), self->common.options,
self->n_buckets, self->hash_fn, self->common.sort_fn, self->common.cmp_fn,
- tag, file, line, func, ref_debug);
+ tag, file, line, func);
}
/*!
@@ -230,7 +210,7 @@ static struct hash_bucket_node *hash_ao2_new_node(struct ao2_container_hash *sel
struct hash_bucket_node *node;
int i;
- node = __ao2_alloc(sizeof(*node), hash_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ node = ao2_t_alloc_options(sizeof(*node), hash_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK, NULL);
if (!node) {
return NULL;
}
@@ -238,11 +218,7 @@ static struct hash_bucket_node *hash_ao2_new_node(struct ao2_container_hash *sel
i = abs(self->hash_fn(obj_new, OBJ_SEARCH_OBJECT));
i %= self->n_buckets;
- if (tag) {
- __ao2_ref_debug(obj_new, +1, tag, file, line, func);
- } else {
- ao2_t_ref(obj_new, +1, "Container node creation");
- }
+ __ao2_ref(obj_new, +1, tag ?: "Container node creation", file, line, func);
node->common.obj = obj_new;
node->common.my_container = (struct ao2_container *) self;
node->my_bucket = i;
@@ -440,7 +416,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s
}
/* We have the first traversal node */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
return node;
}
}
@@ -482,7 +458,7 @@ static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *s
}
/* We have the first traversal node */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
return node;
}
}
@@ -551,7 +527,7 @@ static struct hash_bucket_node *hash_ao2_find_next(struct ao2_container_hash *se
}
/* We have the next traversal node */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
/*
* Dereferencing the prev node may result in our next node
@@ -559,7 +535,7 @@ static struct hash_bucket_node *hash_ao2_find_next(struct ao2_container_hash *se
* the container uses RW locks and the container was read
* locked.
*/
- __ao2_ref(prev, -1);
+ ao2_t_ref(prev, -1, NULL);
if (node->common.obj) {
return node;
}
@@ -595,7 +571,7 @@ hash_descending_resume:;
}
/* We have the next traversal node */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
/*
* Dereferencing the prev node may result in our next node
@@ -603,7 +579,7 @@ hash_descending_resume:;
* the container uses RW locks and the container was read
* locked.
*/
- __ao2_ref(prev, -1);
+ ao2_t_ref(prev, -1, NULL);
if (node->common.obj) {
return node;
}
@@ -615,7 +591,7 @@ hash_ascending_resume:;
}
/* No more nodes in the container left to traverse. */
- __ao2_ref(prev, -1);
+ ao2_t_ref(prev, -1, NULL);
return NULL;
}
@@ -1037,8 +1013,6 @@ static int hash_ao2_integrity(struct ao2_container_hash *self)
/*! Hash container virtual method table. */
static const struct ao2_container_methods v_table_hash = {
.alloc_empty_clone = (ao2_container_alloc_empty_clone_fn) hash_ao2_alloc_empty_clone,
- .alloc_empty_clone_debug =
- (ao2_container_alloc_empty_clone_debug_fn) hash_ao2_alloc_empty_clone_debug,
.new_node = (ao2_container_new_node_fn) hash_ao2_new_node,
.insert = (ao2_container_insert_fn) hash_ao2_insert_node,
.traverse_first = (ao2_container_find_first_fn) hash_ao2_find_first,
@@ -1104,25 +1078,8 @@ static struct ao2_container *hash_ao2_container_init(
struct ao2_container *__ao2_container_alloc_hash(unsigned int ao2_options,
unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn,
- ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
-{
- unsigned int num_buckets;
- size_t container_size;
- struct ao2_container_hash *self;
-
- num_buckets = hash_fn ? n_buckets : 1;
- container_size = sizeof(struct ao2_container_hash) + num_buckets * sizeof(struct hash_bucket);
-
- self = ao2_t_alloc_options(container_size, container_destruct, ao2_options,
- "New hash container");
- return hash_ao2_container_init(self, container_options, num_buckets,
- hash_fn, sort_fn, cmp_fn);
-}
-
-struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options,
- unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn,
ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
- const char *tag, const char *file, int line, const char *func, int ref_debug)
+ const char *tag, const char *file, int line, const char *func)
{
unsigned int num_buckets;
size_t container_size;
@@ -1131,25 +1088,17 @@ struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options,
num_buckets = hash_fn ? n_buckets : 1;
container_size = sizeof(struct ao2_container_hash) + num_buckets * sizeof(struct hash_bucket);
- self = __ao2_alloc_debug(container_size,
- ref_debug ? container_destruct_debug : container_destruct, ao2_options,
- tag, file, line, func, ref_debug);
+ self = __ao2_alloc(container_size, container_destruct, ao2_options,
+ tag ?: __PRETTY_FUNCTION__, file, line, func);
return hash_ao2_container_init(self, container_options, num_buckets, hash_fn,
sort_fn, cmp_fn);
}
struct ao2_container *__ao2_container_alloc_list(unsigned int ao2_options,
- unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
-{
- return __ao2_container_alloc_hash(ao2_options, container_options, 1, NULL, sort_fn,
- cmp_fn);
-}
-
-struct ao2_container *__ao2_container_alloc_list_debug(unsigned int ao2_options,
unsigned int container_options, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
- const char *tag, const char *file, int line, const char *func, int ref_debug)
+ const char *tag, const char *file, int line, const char *func)
{
- return __ao2_container_alloc_hash_debug(ao2_options, container_options, 1, NULL,
- sort_fn, cmp_fn, tag, file, line, func, ref_debug);
+ return __ao2_container_alloc_hash(ao2_options, container_options, 1, NULL,
+ sort_fn, cmp_fn, tag, file, line, func);
}
diff --git a/main/astobj2_private.h b/main/astobj2_private.h
index 0583faf7f..ef47ed774 100644
--- a/main/astobj2_private.h
+++ b/main/astobj2_private.h
@@ -43,7 +43,24 @@ struct ao2_stats {
extern struct ao2_stats ao2;
#endif /* defined(AO2_DEBUG) */
-int is_ao2_object(void *user_data);
+void log_bad_ao2(void *user_data, const char *file, int line, const char *func);
+int internal_is_ao2_object(void *user_data);
+
+#define __is_ao2_object(user_data, file, line, func) \
+ ({ \
+ int ret ## __LINE__ = 0; \
+ if (user_data) { \
+ ret ## __LINE__ = internal_is_ao2_object(user_data); \
+ } \
+ if (!ret ## __LINE__) { \
+ log_bad_ao2(user_data, file, line, func); \
+ } \
+ (ret ## __LINE__); \
+ })
+
+#define is_ao2_object(user_data) \
+ __is_ao2_object(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger);
#endif /* ASTOBJ2_PRIVATE_H_ */
diff --git a/main/astobj2_rbtree.c b/main/astobj2_rbtree.c
index d3a902572..b06813d6f 100644
--- a/main/astobj2_rbtree.c
+++ b/main/astobj2_rbtree.c
@@ -545,47 +545,27 @@ static void rb_rotate_right(struct ao2_container_rbtree *self, struct rbtree_nod
/*!
* \internal
- * \brief Create an empty copy of this container.
- * \since 12.0.0
- *
- * \param self Container to operate upon.
- *
- * \retval empty-clone-container on success.
- * \retval NULL on error.
- */
-static struct ao2_container *rb_ao2_alloc_empty_clone(struct ao2_container_rbtree *self)
-{
- if (!is_ao2_object(self)) {
- return NULL;
- }
-
- return ao2_t_container_alloc_rbtree(ao2_options_get(self), self->common.options,
- self->common.sort_fn, self->common.cmp_fn, "Clone rbtree container");
-}
-
-/*!
- * \internal
* \brief Create an empty copy of this container. (Debug version)
- * \since 12.0.0
+ * \since 14.0.0
*
* \param self Container to operate upon.
* \param tag used for debugging.
* \param file Debug file name invoked from
* \param line Debug line invoked from
* \param func Debug function name invoked from
- * \param ref_debug TRUE if to output a debug reference message.
*
* \retval empty-clone-container on success.
* \retval NULL on error.
*/
-static struct ao2_container *rb_ao2_alloc_empty_clone_debug(struct ao2_container_rbtree *self, const char *tag, const char *file, int line, const char *func, int ref_debug)
+static struct ao2_container *rb_ao2_alloc_empty_clone(struct ao2_container_rbtree *self,
+ const char *tag, const char *file, int line, const char *func)
{
- if (!is_ao2_object(self)) {
+ if (!__is_ao2_object(self, file, line, func)) {
return NULL;
}
- return __ao2_container_alloc_rbtree_debug(ao2_options_get(self), self->common.options,
- self->common.sort_fn, self->common.cmp_fn, tag, file, line, func, ref_debug);
+ return __ao2_container_alloc_rbtree(ao2_options_get(self), self->common.options,
+ self->common.sort_fn, self->common.cmp_fn, tag, file, line, func);
}
/*!
@@ -925,16 +905,12 @@ static struct rbtree_node *rb_ao2_new_node(struct ao2_container_rbtree *self, vo
{
struct rbtree_node *node;
- node = __ao2_alloc(sizeof(*node), rb_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
+ node = ao2_t_alloc_options(sizeof(*node), rb_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK, NULL);
if (!node) {
return NULL;
}
- if (tag) {
- __ao2_ref_debug(obj_new, +1, tag, file, line, func);
- } else {
- ao2_t_ref(obj_new, +1, "Container node creation");
- }
+ __ao2_ref(obj_new, +1, tag ?: "Container node creation", file, line, func);
node->common.obj = obj_new;
node->common.my_container = (struct ao2_container *) self;
@@ -1337,7 +1313,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s
}
/* We have the next traversal node */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
/*
* Dereferencing the prev node may result in our next node
@@ -1345,7 +1321,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s
* the container uses RW locks and the container was read
* locked.
*/
- __ao2_ref(prev, -1);
+ ao2_t_ref(prev, -1, NULL);
if (node->common.obj) {
return node;
}
@@ -1353,7 +1329,7 @@ static struct rbtree_node *rb_ao2_find_next(struct ao2_container_rbtree *self, s
}
/* No more nodes in the container left to traverse. */
- __ao2_ref(prev, -1);
+ ao2_t_ref(prev, -1, NULL);
return NULL;
}
@@ -1636,7 +1612,7 @@ static struct rbtree_node *rb_ao2_find_first(struct ao2_container_rbtree *self,
}
/* We have the first traversal node */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
return node;
}
@@ -2018,8 +1994,6 @@ static int rb_ao2_integrity(struct ao2_container_rbtree *self)
/*! rbtree container virtual method table. */
static const struct ao2_container_methods v_table_rbtree = {
.alloc_empty_clone = (ao2_container_alloc_empty_clone_fn) rb_ao2_alloc_empty_clone,
- .alloc_empty_clone_debug =
- (ao2_container_alloc_empty_clone_debug_fn) rb_ao2_alloc_empty_clone_debug,
.new_node = (ao2_container_new_node_fn) rb_ao2_new_node,
.insert = (ao2_container_insert_fn) rb_ao2_insert_node,
.traverse_first = (ao2_container_find_first_fn) rb_ao2_find_first,
@@ -2063,24 +2037,8 @@ static struct ao2_container *rb_ao2_container_init(struct ao2_container_rbtree *
}
struct ao2_container *__ao2_container_alloc_rbtree(unsigned int ao2_options, unsigned int container_options,
- ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
-{
- struct ao2_container_rbtree *self;
-
- if (!sort_fn) {
- /* Sanity checks. */
- ast_log(LOG_ERROR, "Missing sort_fn()!\n");
- return NULL;
- }
-
- self = ao2_t_alloc_options(sizeof(*self), container_destruct, ao2_options,
- "New rbtree container");
- return rb_ao2_container_init(self, container_options, sort_fn, cmp_fn);
-}
-
-struct ao2_container *__ao2_container_alloc_rbtree_debug(unsigned int ao2_options, unsigned int container_options,
ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
- const char *tag, const char *file, int line, const char *func, int ref_debug)
+ const char *tag, const char *file, int line, const char *func)
{
struct ao2_container_rbtree *self;
@@ -2090,9 +2048,8 @@ struct ao2_container *__ao2_container_alloc_rbtree_debug(unsigned int ao2_option
return NULL;
}
- self = __ao2_alloc_debug(sizeof(*self),
- ref_debug ? container_destruct_debug : container_destruct, ao2_options,
- tag, file, line, func, ref_debug);
+ self = __ao2_alloc(sizeof(*self), container_destruct, ao2_options,
+ tag ?: __PRETTY_FUNCTION__, file, line, func);
return rb_ao2_container_init(self, container_options, sort_fn, cmp_fn);
}
diff --git a/main/channel.c b/main/channel.c
index db126db76..fee77630a 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -795,7 +795,9 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
return NULL;
}
- if (!(tmp = ast_channel_internal_alloc(ast_channel_destructor, assignedids, requestor))) {
+ tmp = __ast_channel_internal_alloc(ast_channel_destructor, assignedids, requestor,
+ file, line, function);
+ if (!tmp) {
/* Channel structure allocation failure. */
return NULL;
}
@@ -987,16 +989,14 @@ struct ast_channel *__ast_channel_alloc(int needqueue, int state, const char *ci
/* only do the minimum amount of work needed here to make a channel
* structure that can be used to expand channel vars */
-#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
struct ast_channel *__ast_dummy_channel_alloc(const char *file, int line, const char *function)
-#else
-struct ast_channel *ast_dummy_channel_alloc(void)
-#endif
{
struct ast_channel *tmp;
struct varshead *headp;
- if (!(tmp = ast_channel_internal_alloc(ast_dummy_channel_destructor, NULL, NULL))) {
+ tmp = __ast_channel_internal_alloc(ast_dummy_channel_destructor, NULL, NULL,
+ file, line, function);
+ if (!tmp) {
/* Dummy channel structure allocation failure. */
return NULL;
}
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c
index 4e8539889..0bb38499b 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -1439,15 +1439,9 @@ static int pvt_cause_cmp_fn(void *obj, void *vstr, int flags)
struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj), const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *file, int line, const char *function)
{
struct ast_channel *tmp;
-#if defined(REF_DEBUG)
- tmp = __ao2_alloc_debug(sizeof(*tmp), destructor,
- AO2_ALLOC_OPT_LOCK_MUTEX, "", file, line, function, 1);
-#elif defined(__AST_DEBUG_MALLOC)
- tmp = __ao2_alloc_debug(sizeof(*tmp), destructor,
- AO2_ALLOC_OPT_LOCK_MUTEX, "", file, line, function, 0);
-#else
- tmp = ao2_alloc(sizeof(*tmp), destructor);
-#endif
+
+ tmp = __ao2_alloc(sizeof(*tmp), destructor,
+ AO2_ALLOC_OPT_LOCK_MUTEX, "", file, line, function);
if (!tmp) {
return NULL;
diff --git a/main/format_cache.c b/main/format_cache.c
index 3e729769c..def795c9d 100644
--- a/main/format_cache.c
+++ b/main/format_cache.c
@@ -457,22 +457,14 @@ int ast_format_cache_set(struct ast_format *format)
return 0;
}
-struct ast_format *__ast_format_cache_get(const char *name)
+struct ast_format *__ast_format_cache_get(const char *name,
+ const char *tag, const char *file, int line, const char *func)
{
if (ast_strlen_zero(name)) {
return NULL;
}
- return ao2_find(formats, name, OBJ_SEARCH_KEY);
-}
-
-struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func)
-{
- if (ast_strlen_zero(name)) {
- return NULL;
- }
-
- return __ao2_find_debug(formats, name, OBJ_SEARCH_KEY, S_OR(tag, "ast_format_cache_get"), file, line, func);
+ return __ao2_find(formats, name, OBJ_SEARCH_KEY, tag, file, line, func);
}
struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate)
diff --git a/main/format_cap.c b/main/format_cap.c
index c9c6c3b30..7456a444b 100644
--- a/main/format_cap.c
+++ b/main/format_cap.c
@@ -103,25 +103,13 @@ static inline void format_cap_init(struct ast_format_cap *cap, enum ast_format_c
cap->framing = UINT_MAX;
}
-struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags)
+struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags,
+ const char *tag, const char *file, int line, const char *func)
{
struct ast_format_cap *cap;
- cap = ao2_alloc_options(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
- if (!cap) {
- return NULL;
- }
-
- format_cap_init(cap, flags);
-
- return cap;
-}
-
-struct ast_format_cap *__ast_format_cap_alloc_debug(enum ast_format_cap_flags flags, const char *tag, const char *file, int line, const char *func)
-{
- struct ast_format_cap *cap;
-
- cap = __ao2_alloc_debug(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(tag, "ast_format_cap_alloc"), file, line, func, 1);
+ cap = __ao2_alloc(sizeof(*cap), format_cap_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK,
+ tag, file, line, func);
if (!cap) {
return NULL;
}
@@ -187,26 +175,7 @@ static int format_in_format_cap(struct ast_format_cap *cap, struct ast_format *f
return 0;
}
-int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing)
-{
- struct format_cap_framed *framed;
-
- ast_assert(format != NULL);
-
- if (format_in_format_cap(cap, format)) {
- return 0;
- }
-
- framed = ao2_alloc_options(sizeof(*framed), format_cap_framed_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
- if (!framed) {
- return -1;
- }
- framed->format = ao2_bump(format);
-
- return format_cap_framed_init(framed, cap, format, framing);
-}
-
-int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func)
+int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int framing, const char *tag, const char *file, int line, const char *func)
{
struct format_cap_framed *framed;
@@ -221,7 +190,7 @@ int __ast_format_cap_append_debug(struct ast_format_cap *cap, struct ast_format
return -1;
}
- __ao2_ref_debug(format, +1, S_OR(tag, "ast_format_cap_append"), file, line, func);
+ __ao2_ref(format, +1, tag, file, line, func);
framed->format = format;
return format_cap_framed_init(framed, cap, format, framing);
diff --git a/main/loader.c b/main/loader.c
index 26d229fdb..eb959fa80 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -122,10 +122,8 @@ static int modules_loaded;
struct ast_module {
const struct ast_module_info *info;
-#ifdef REF_DEBUG
- /* Used to get module references into REF_DEBUG logs */
+ /* Used to get module references into refs log */
void *ref_debug;
-#endif
void *lib; /* the shared lib, or NULL if embedded */
int usecount; /* the number of 'users' currently in this module */
struct module_user_list users; /* the list of users in the module */
@@ -199,9 +197,9 @@ void ast_module_register(const struct ast_module_info *info)
ast_debug(5, "Registering module %s\n", info->name);
mod->info = info;
-#ifdef REF_DEBUG
- mod->ref_debug = ao2_t_alloc(0, NULL, info->name);
-#endif
+ if (ast_opt_ref_debug) {
+ mod->ref_debug = ao2_t_alloc(0, NULL, info->name);
+ }
AST_LIST_HEAD_INIT(&mod->users);
/* during startup, before the loader has been initialized,
@@ -248,9 +246,7 @@ void ast_module_unregister(const struct ast_module_info *info)
if (mod) {
ast_debug(5, "Unregistering module %s\n", info->name);
AST_LIST_HEAD_DESTROY(&mod->users);
-#ifdef REF_DEBUG
ao2_cleanup(mod->ref_debug);
-#endif
ast_free(mod);
}
}
@@ -270,9 +266,9 @@ struct ast_module_user *__ast_module_user_add(struct ast_module *mod, struct ast
AST_LIST_INSERT_HEAD(&mod->users, u, entry);
AST_LIST_UNLOCK(&mod->users);
-#ifdef REF_DEBUG
- ao2_ref(mod->ref_debug, +1);
-#endif
+ if (mod->ref_debug) {
+ ao2_ref(mod->ref_debug, +1);
+ }
ast_atomic_fetchadd_int(&mod->usecount, +1);
@@ -298,9 +294,9 @@ void __ast_module_user_remove(struct ast_module *mod, struct ast_module_user *u)
return;
}
-#ifdef REF_DEBUG
- ao2_ref(mod->ref_debug, -1);
-#endif
+ if (mod->ref_debug) {
+ ao2_ref(mod->ref_debug, -1);
+ }
ast_atomic_fetchadd_int(&mod->usecount, -1);
ast_free(u);
@@ -318,9 +314,9 @@ void __ast_module_user_hangup_all(struct ast_module *mod)
ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
}
-#ifdef REF_DEBUG
- ao2_ref(mod->ref_debug, -1);
-#endif
+ if (mod->ref_debug) {
+ ao2_ref(mod->ref_debug, -1);
+ }
ast_atomic_fetchadd_int(&mod->usecount, -1);
ast_free(u);
@@ -641,9 +637,7 @@ void ast_module_shutdown(void)
mod->info->unload();
}
AST_LIST_HEAD_DESTROY(&mod->users);
-#ifdef REF_DEBUG
ao2_cleanup(mod->ref_debug);
-#endif
ast_free(mod);
somethingchanged = 1;
}
@@ -1477,9 +1471,9 @@ struct ast_module *__ast_module_ref(struct ast_module *mod, const char *file, in
return NULL;
}
-#ifdef REF_DEBUG
- __ao2_ref_debug(mod->ref_debug, +1, "", file, line, func);
-#endif
+ if (mod->ref_debug) {
+ __ao2_ref(mod->ref_debug, +1, "", file, line, func);
+ }
ast_atomic_fetchadd_int(&mod->usecount, +1);
ast_update_use_count();
@@ -1503,9 +1497,9 @@ void __ast_module_unref(struct ast_module *mod, const char *file, int line, cons
return;
}
-#ifdef REF_DEBUG
- __ao2_ref_debug(mod->ref_debug, -1, "", file, line, func);
-#endif
+ if (mod->ref_debug) {
+ __ao2_ref(mod->ref_debug, -1, "", file, line, func);
+ }
ast_atomic_fetchadd_int(&mod->usecount, -1);
ast_update_use_count();