[asterisk-commits] Astobj2: Allow reference debugging to be enabled/disabled by... (asterisk[master])
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Apr 28 06:42:30 CDT 2015
Matt Jordan has submitted this change and it was merged.
Change subject: Astobj2: Allow reference debugging to be enabled/disabled by config.
......................................................................
Astobj2: Allow reference debugging to be enabled/disabled by config.
* The REF_DEBUG compiler flag no longer has any effect on code that uses
Astobj2. It is used to determine if reference debugging is enabled by
default. Reference debugging can be enabled or disabled in asterisk.conf.
* Caller information is provided in logger errors for ao2 bad magic numbers.
* Optimizes AO2 by merging internal functions with the public counterpart.
This was possible now that we no longer require a dual ABI.
ASTERISK-24974 #close
Reported by: Corey Farrell
Change-Id: Icf3552721fe999365ba8a8cf00a965aa6b897cc1
---
M UPGRADE.txt
M apps/app_queue.c
M build_tools/cflags.xml
M build_tools/make_buildopts_h
M channels/chan_sip.c
M configs/samples/asterisk.conf.sample
M contrib/Makefile
M contrib/scripts/refcounter.py
M include/asterisk/astobj2.h
M include/asterisk/channel.h
M include/asterisk/format_cache.h
M include/asterisk/format_cap.h
M include/asterisk/options.h
M main/asterisk.c
M main/astobj2.c
M main/astobj2_container.c
M main/astobj2_container_private.h
M main/astobj2_hash.c
M main/astobj2_private.h
M main/astobj2_rbtree.c
M main/channel.c
M main/channel_internal_api.c
M main/format_cache.c
M main/format_cap.c
M main/loader.c
M res/res_musiconhold.c
26 files changed, 407 insertions(+), 993 deletions(-)
Approvals:
Richard Mudgett: Looks good to me, but someone else must approve
Matt Jordan: Looks good to me, approved; Verified
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 0696adb..d9d5cec 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -32,6 +32,9 @@
Caller-ID detection.
Core:
+ - The REF_DEBUG compiler flag is now used to enable refdebug by default.
+ The setting can be overridden in asterisk.conf by setting refdebug in
+ the options category. No recompile is required to enable/disable it.
AMI:
- The 'ModuleCheck' Action's Version key will no longer show the module
diff --git a/apps/app_queue.c b/apps/app_queue.c
index 0b8204c..d2c6406 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -1814,49 +1814,26 @@
ao2_callback(queue->members, OBJ_NODATA | OBJ_MULTIPLE, queue_member_decrement_followers, &pos);
}
-#ifdef REF_DEBUG
#define queue_ref(q) _queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define queue_unref(q) _queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define queue_t_ref(q, tag) _queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define queue_t_unref(q, tag) _queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define queues_t_link(c, q, tag) __ao2_link_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define queues_t_unlink(c, q, tag) __ao2_unlink_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define queues_t_link(c, q, tag) ao2_t_link(c, q, tag)
+#define queues_t_unlink(c, q, tag) ao2_t_unlink(c, q, tag)
static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
{
- __ao2_ref_debug(q, 1, tag, file, line, filename);
+ __ao2_ref(q, 1, tag, file, line, filename);
return q;
}
static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
{
if (q) {
- __ao2_ref_debug(q, -1, tag, file, line, filename);
+ __ao2_ref(q, -1, tag, file, line, filename);
}
return NULL;
}
-
-#else
-
-#define queue_t_ref(q, tag) queue_ref(q)
-#define queue_t_unref(q, tag) queue_unref(q)
-#define queues_t_link(c, q, tag) ao2_t_link(c, q, tag)
-#define queues_t_unlink(c, q, tag) ao2_t_unlink(c, q, tag)
-
-static inline struct call_queue *queue_ref(struct call_queue *q)
-{
- ao2_ref(q, 1);
- return q;
-}
-
-static inline struct call_queue *queue_unref(struct call_queue *q)
-{
- if (q) {
- ao2_ref(q, -1);
- }
- return NULL;
-}
-#endif
/*! \brief Set variables of queue */
static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
diff --git a/build_tools/cflags.xml b/build_tools/cflags.xml
index 1a2e78f..b91cf5a 100644
--- a/build_tools/cflags.xml
+++ b/build_tools/cflags.xml
@@ -5,7 +5,7 @@
<member name="DEBUG_THREADS" displayname="Enable Thread Debugging">
<support_level>core</support_level>
</member>
- <member name="REF_DEBUG" displayname="Enable reference count debugging">
+ <member name="REF_DEBUG" displayname="Enable reference count debugging by default">
<support_level>extended</support_level>
</member>
<member name="AO2_DEBUG" displayname="Enable internal Astobj2 debugging">
diff --git a/build_tools/make_buildopts_h b/build_tools/make_buildopts_h
index 55d08ba..df506ed 100755
--- a/build_tools/make_buildopts_h
+++ b/build_tools/make_buildopts_h
@@ -13,6 +13,20 @@
TMP=`${GREP} -e "^MENUSELECT_CFLAGS" menuselect.makeopts | sed 's/MENUSELECT_CFLAGS\=//g' | sed 's/-D//g'`
for x in ${TMP}; do
echo "#define ${x} 1"
+ if test "${x}" = "DONT_OPTIMIZE" \
+ -o "${x}" = "BETTER_BACKTRACES" \
+ -o "${x}" = "LOTS_OF_SPANS" \
+ -o "${x}" = "BUILD_NATIVE" \
+ -o "${x}" = "REF_DEBUG" \
+ -o "${x}" = "AO2_DEBUG" \
+ -o "${x}" = "REBUILD_PARSERS" \
+ -o "${x}" = "RADIO_RELAX" \
+ -o "${x}" = "DEBUG_SCHEDULER" \
+ -o "${x}" = "DETECT_DEADLOCKS" \
+ -o "${x}" = "DUMP_SCHEDULER" ; then
+ # These aren't ABI affecting options, keep them out of AST_BUILDOPTS
+ continue
+ fi
if test "x${BUILDOPTS}" != "x" ; then
BUILDOPTS="${BUILDOPTS}, ${x}"
else
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 3ee92da..aa616cd 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -8599,9 +8599,9 @@
{
struct sip_pvt *p;
- p = __ao2_alloc_debug(sizeof(*p), sip_destroy_fn,
+ p = __ao2_alloc(sizeof(*p), sip_destroy_fn,
AO2_ALLOC_OPT_LOCK_MUTEX, "allocate a dialog(pvt) struct",
- file, line, func, 1);
+ file, line, func);
if (!p) {
return NULL;
}
@@ -9178,7 +9178,7 @@
struct sip_pvt tmp_dialog = {
.callid = callid,
};
- sip_pvt_ptr = __ao2_find_debug(dialogs, &tmp_dialog, OBJ_POINTER,
+ sip_pvt_ptr = __ao2_find(dialogs, &tmp_dialog, OBJ_POINTER,
"find_call in dialogs", file, line, func);
if (sip_pvt_ptr) { /* well, if we don't find it-- what IS in there? */
/* Found the call */
@@ -9193,7 +9193,7 @@
struct sip_pvt *fork_pvt = NULL;
struct match_req_args args = { 0, };
int found;
- struct ao2_iterator *iterator = __ao2_callback_debug(dialogs,
+ struct ao2_iterator *iterator = __ao2_callback(dialogs,
OBJ_POINTER | OBJ_MULTIPLE,
dialog_find_multiple,
&tmp_dialog,
@@ -9243,7 +9243,7 @@
/* This is likely a forked Request that somehow resulted in us receiving multiple parts of the fork.
* RFC 3261 section 8.2.2.2, Indicate that we want to merge requests by sending a 482 response. */
transmit_response_using_temp(callid, addr, 1, intended_method, req, "482 (Loop Detected)");
- __ao2_ref_debug(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search.",
+ __ao2_ref(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search.",
file, line, func);
ao2_iterator_destroy(iterator);
dialog_unref(fork_pvt, "unref fork_pvt");
@@ -9255,7 +9255,7 @@
/* fall through */
case SIP_REQ_NOT_MATCH:
default:
- __ao2_ref_debug(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search",
+ __ao2_ref(sip_pvt_ptr, -1, "pvt did not match incoming SIP msg, unref from search",
file, line, func);
break;
}
diff --git a/configs/samples/asterisk.conf.sample b/configs/samples/asterisk.conf.sample
index e4883ec..818f5c2 100644
--- a/configs/samples/asterisk.conf.sample
+++ b/configs/samples/asterisk.conf.sample
@@ -14,6 +14,7 @@
[options]
;verbose = 3
;debug = 3
+;refdebug = yes ; Enable reference count debug logging.
;alwaysfork = yes ; Same as -F at startup.
;nofork = yes ; Same as -f at startup.
;quiet = yes ; Same as -q at startup.
diff --git a/contrib/Makefile b/contrib/Makefile
index 2c91b47..37f4df4 100644
--- a/contrib/Makefile
+++ b/contrib/Makefile
@@ -20,10 +20,8 @@
include $(ASTTOPDIR)/Makefile.rules
install:
- if [ -n "$(findstring REF_DEBUG,$(MENUSELECT_CFLAGS))" ]; then \
- $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/scripts"; \
- $(INSTALL) -m 755 scripts/refcounter.py "$(DESTDIR)$(ASTDATADIR)/scripts/refcounter.py"; \
- fi
+ $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/scripts"; \
+ $(INSTALL) -m 755 scripts/refcounter.py "$(DESTDIR)$(ASTDATADIR)/scripts/refcounter.py"; \
uninstall:
rm -f "$(DESTDIR)$(ASTDATADIR)/scripts/refcounter.py"
diff --git a/contrib/scripts/refcounter.py b/contrib/scripts/refcounter.py
index 1a97e90..1f4b375 100755
--- a/contrib/scripts/refcounter.py
+++ b/contrib/scripts/refcounter.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python
"""Process a ref debug log
- This file will process a log file created by the REF_DEBUG
- build option in Asterisk.
+ This file will process a log file created by enabling
+ the refdebug config option in asterisk.conf.
See http://www.asterisk.org for more information about
the Asterisk project. Please do not directly contact
diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index 1c3c2e8..de35bb3 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -141,31 +141,11 @@
/*
\note DEBUGGING REF COUNTS BIBLE:
An interface to help debug refcounting is provided
-in this package. It is dependent on the REF_DEBUG macro being
-defined via menuselect and in using variants of the normal ao2_xxxx
-function that are named ao2_t_xxxx instead, with an extra argument,
-a string that will be printed out into the refs log file when the
-refcount for an object is changed.
+in this package. It is dependent on the refdebug being enabled in
+asterisk.conf.
- these ao2_t_xxx variants are provided:
-
-ao2_t_alloc(arg1, arg2, arg3)
-ao2_t_ref(arg1,arg2,arg3)
-ao2_t_container_alloc(arg1,arg2,arg3,arg4)
-ao2_t_link(arg1, arg2, arg3)
-ao2_t_unlink(arg1, arg2, arg3)
-ao2_t_callback(arg1,arg2,arg3,arg4,arg5)
-ao2_t_find(arg1,arg2,arg3,arg4)
-ao2_t_iterator_next(arg1, arg2)
-
-If you study each argument list, you will see that these functions all have
-one extra argument than their ao2_xxx counterpart. The last argument in
-each case is supposed to be a string pointer, a "tag", that should contain
-enough of an explanation, that you can pair operations that increment the
-ref count, with operations that are meant to decrement the refcount.
-
-Each of these calls will generate at least one line of output in in the refs
-log files. These lines look like this:
+Each of the reference manipulations will generate one line of output in in the refs
+log file. These lines look like this:
...
0x8756f00,+1,1234,chan_sip.c,22240,load_module,**constructor**,allocate users
0x86e3408,+1,1234,chan_sip.c,22241,load_module,**constructor**,allocate peers
@@ -210,61 +190,29 @@
context for the ref change. Note that any subsequent columns are
considered to be part of this tag.
-Sometimes you have some helper functions to do object ref/unref
+Sometimes you have some helper functions to do object create/ref/unref
operations. Using these normally hides the place where these
functions were called. To get the location where these functions
-were called to appear in /refs, you can do this sort of thing:
+were called to appear in refs log, you can do this sort of thing:
-#ifdef REF_DEBUG
-#define dialog_ref(arg1,arg2) dialog_ref_debug((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define dialog_unref(arg1,arg2) dialog_unref_debug((arg1),(arg2), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-static struct sip_pvt *dialog_ref_debug(struct sip_pvt *p, const char *tag, const char *file, int line, const char *func)
+#define my_t_alloc(data,tag) my_alloc_debug((data), tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define my_alloc(data) my_t_alloc((data), "")
+
+static struct mydata *my_alloc_debug(void *data,
+ const char *tag, const char *file, int line, const char *func)
{
+ struct mydata *p;
+
+ p = __ao2_alloc(sizeof(*p), NULL, AO2_ALLOC_OPT_LOCK_MUTEX, tag, file, line, func);
if (p) {
- ao2_ref_debug(p, 1, tag, file, line, func);
- } else {
- ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n");
+ p->data = data;
}
return p;
}
-
-static struct sip_pvt *dialog_unref_debug(struct sip_pvt *p, const char *tag, const char *file, int line, const char *func)
-{
- if (p) {
- ao2_ref_debug(p, -1, tag, file, line, func);
- }
- return NULL;
-}
-#else
-static struct sip_pvt *dialog_ref(struct sip_pvt *p, const char *tag)
-{
- if (p) {
- ao2_ref(p, 1);
- } else {
- ast_log(LOG_ERROR, "Attempt to Ref a null pointer\n");
- }
- return p;
-}
-
-static struct sip_pvt *dialog_unref(struct sip_pvt *p, const char *tag)
-{
- if (p) {
- ao2_ref(p, -1);
- }
- return NULL;
-}
-#endif
-
-In the above code, note that the "normal" helper funcs call ao2_ref() as
-normal, and the "helper" functions call ao2_ref_debug directly with the
-file, function, and line number info provided. You might find this
-well worth the effort to help track these function calls in the code.
To find out why objects are not destroyed (a common bug), you can
-edit the source file to use the ao2_t_* variants, enable REF_DEBUG
-in menuselect, and add a descriptive tag to each call. Recompile,
-and run Asterisk, exit asterisk with "core stop gracefully", which should
-result in every object being destroyed.
+enable refdebug in asterisk.conf. Run asterisk, exit with "core stop gracefully".
+This should result in every object being destroyed.
Then, you can "sort -k 1 {AST_LOG_DIR}/refs > x1" to get a sorted list of
all the objects, or you can use "contrib/script/refcounter.py" to scan
@@ -439,50 +387,23 @@
* - the returned pointer cannot be free()'d or realloc()'ed;
* rather, we just call ao2_ref(o, -1);
*
+ * \note refdebug logging is skipped if debug_msg is NULL
+ *
* @{
*/
-#if defined(REF_DEBUG)
-
#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg) \
- __ao2_alloc_debug((data_size), (destructor_fn), (options), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+ __ao2_alloc((data_size), (destructor_fn), (options), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_alloc_options(data_size, destructor_fn, options) \
- __ao2_alloc_debug((data_size), (destructor_fn), (options), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+ __ao2_alloc((data_size), (destructor_fn), (options), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \
- __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+ __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_alloc(data_size, destructor_fn) \
- __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+ __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#elif defined(__AST_DEBUG_MALLOC)
-
-#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg) \
- __ao2_alloc_debug((data_size), (destructor_fn), (options), (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_alloc_options(data_size, destructor_fn, options) \
- __ao2_alloc_debug((data_size), (destructor_fn), (options), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \
- __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, (debug_msg), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_alloc(data_size, destructor_fn) \
- __ao2_alloc_debug((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
-#define ao2_t_alloc_options(data_size, destructor_fn, options, debug_msg) \
- __ao2_alloc((data_size), (destructor_fn), (options))
-#define ao2_alloc_options(data_size, destructor_fn, options) \
- __ao2_alloc((data_size), (destructor_fn), (options))
-
-#define ao2_t_alloc(data_size, destructor_fn, debug_msg) \
- __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX)
-#define ao2_alloc(data_size, destructor_fn) \
- __ao2_alloc((data_size), (destructor_fn), AO2_ALLOC_OPT_LOCK_MUTEX)
-
-#endif
-
-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) attribute_warn_unused_result;
-void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options) attribute_warn_unused_result;
+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) attribute_warn_unused_result;
/*! @} */
@@ -507,20 +428,12 @@
* can go away is when we release our reference, and it is
* the last one in existence.
*
+ * \note refdebug logging is skipped if tag is NULL
* @{
*/
-#ifdef REF_DEBUG
-
-#define ao2_t_ref(o,delta,tag) __ao2_ref_debug((o), (delta), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_ref(o,delta) __ao2_ref_debug((o), (delta), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#else
-
-#define ao2_t_ref(o,delta,tag) __ao2_ref((o), (delta))
-#define ao2_ref(o,delta) __ao2_ref((o), (delta))
-
-#endif
+#define ao2_t_ref(o,delta,tag) __ao2_ref((o), (delta), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_ref(o,delta) __ao2_ref((o), (delta), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief Retrieve the ao2 options used to create the object.
@@ -550,8 +463,7 @@
#define ao2_bump(obj) \
ao2_t_bump((obj), "")
-int __ao2_ref_debug(void *o, int delta, const char *tag, const char *file, int line, const char *func);
-int __ao2_ref(void *o, int delta);
+int __ao2_ref(void *o, int delta, const char *tag, const char *file, int line, const char *func);
/*!
* \since 12.4.0
@@ -848,19 +760,10 @@
*
* \return Nothing
*/
-#ifdef REF_DEBUG
#define ao2_t_global_obj_release(holder, tag) \
__ao2_global_obj_release(&holder, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
#define ao2_global_obj_release(holder) \
__ao2_global_obj_release(&holder, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-
-#else
-
-#define ao2_t_global_obj_release(holder, tag) \
- __ao2_global_obj_release(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#define ao2_global_obj_release(holder) \
- __ao2_global_obj_release(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#endif
void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name);
@@ -879,19 +782,10 @@
* \retval Reference to previous global ao2 object stored.
* \retval NULL if no object available.
*/
-#ifdef REF_DEBUG
#define ao2_t_global_obj_replace(holder, obj, tag) \
__ao2_global_obj_replace(&holder, (obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
#define ao2_global_obj_replace(holder, obj) \
__ao2_global_obj_replace(&holder, (obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-
-#else
-
-#define ao2_t_global_obj_replace(holder, obj, tag) \
- __ao2_global_obj_replace(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#define ao2_global_obj_replace(holder, obj) \
- __ao2_global_obj_replace(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#endif
void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name) attribute_warn_unused_result;
@@ -911,19 +805,10 @@
* \retval 0 The global object was previously empty
* \retval 1 The global object was not previously empty
*/
-#ifdef REF_DEBUG
#define ao2_t_global_obj_replace_unref(holder, obj, tag) \
__ao2_global_obj_replace_unref(&holder, (obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
#define ao2_global_obj_replace_unref(holder, obj) \
__ao2_global_obj_replace_unref(&holder, (obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-
-#else
-
-#define ao2_t_global_obj_replace_unref(holder, obj, tag) \
- __ao2_global_obj_replace_unref(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#define ao2_global_obj_replace_unref(holder, obj) \
- __ao2_global_obj_replace_unref(&holder, (obj), NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#endif
int __ao2_global_obj_replace_unref(struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name);
@@ -937,19 +822,10 @@
* \retval Reference to current ao2 object stored in the holder.
* \retval NULL if no object available.
*/
-#ifdef REF_DEBUG
#define ao2_t_global_obj_ref(holder, tag) \
__ao2_global_obj_ref(&holder, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
#define ao2_global_obj_ref(holder) \
__ao2_global_obj_ref(&holder, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-
-#else
-
-#define ao2_t_global_obj_ref(holder, tag) \
- __ao2_global_obj_ref(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#define ao2_global_obj_ref(holder) \
- __ao2_global_obj_ref(&holder, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__, #holder)
-#endif
void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name) attribute_warn_unused_result;
@@ -1372,36 +1248,15 @@
* \note Destructor is set implicitly.
*/
-#if defined(REF_DEBUG)
-
#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag) \
- __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+ __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn) \
- __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-
-#elif defined(__AST_DEBUG_MALLOC)
-
-#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag) \
- __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn) \
- __ao2_container_alloc_hash_debug((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
-#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag) \
- __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn))
-#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn) \
- __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn))
-
-#endif
+ __ao2_container_alloc_hash((ao2_options), (container_options), (n_buckets), (hash_fn), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
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) attribute_warn_unused_result;
-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) attribute_warn_unused_result;
+ const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
/*!
* \brief Allocate and initialize a list container.
@@ -1418,34 +1273,14 @@
* \note Implemented as a degenerate hash table.
*/
-#if defined(REF_DEBUG)
-
#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag) \
- __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+ __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn) \
- __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-
-#elif defined(__AST_DEBUG_MALLOC)
-
-#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag) \
- __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn) \
- __ao2_container_alloc_list_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
-#define ao2_t_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn, tag) \
- __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn))
-#define ao2_container_alloc_list(ao2_options, container_options, sort_fn, cmp_fn) \
- __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn))
-
-#endif
+ __ao2_container_alloc_list((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
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) attribute_warn_unused_result;
-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) attribute_warn_unused_result;
+ const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
/*!
* \brief Allocate and initialize a red-black tree container.
@@ -1461,34 +1296,14 @@
* \note Destructor is set implicitly.
*/
-#if defined(REF_DEBUG)
-
#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \
- __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
+ __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \
- __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-
-#elif defined(__AST_DEBUG_MALLOC)
-
-#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \
- __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \
- __ao2_container_alloc_rbtree_debug((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
-#define ao2_t_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn, tag) \
- __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn))
-#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn) \
- __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn))
-
-#endif
+ __ao2_container_alloc_rbtree((ao2_options), (container_options), (sort_fn), (cmp_fn), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
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) attribute_warn_unused_result;
-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) attribute_warn_unused_result;
+ const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
/*! \brief
* Returns the number of elements in a container.
@@ -1528,24 +1343,13 @@
* \retval Clone container on success.
* \retval NULL on error.
*/
-struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags) attribute_warn_unused_result;
-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) attribute_warn_unused_result;
-#if defined(REF_DEBUG)
+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) attribute_warn_unused_result;
-#define ao2_t_container_clone(orig, flags, tag) __ao2_container_clone_debug(orig, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-#define ao2_container_clone(orig, flags) __ao2_container_clone_debug(orig, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 1)
-
-#elif defined(__AST_DEBUG_MALLOC)
-
-#define ao2_t_container_clone(orig, flags, tag) __ao2_container_clone_debug(orig, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-#define ao2_container_clone(orig, flags) __ao2_container_clone_debug(orig, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__, 0)
-
-#else
-
-#define ao2_t_container_clone(orig, flags, tag) __ao2_container_clone(orig, flags)
-#define ao2_container_clone(orig, flags) __ao2_container_clone(orig, flags)
-
-#endif
+#define ao2_t_container_clone(orig, flags, tag) \
+ __ao2_container_clone(orig, flags, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_container_clone(orig, flags) \
+ __ao2_container_clone(orig, flags, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief Print output.
@@ -1661,10 +1465,10 @@
* \note This function automatically increases the reference count to account
* for the reference that the container now holds to the object.
*/
-#ifdef REF_DEBUG
-
-#define ao2_t_link(container, obj, tag) __ao2_link_debug((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_link(container, obj) __ao2_link_debug((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_t_link(container, obj, tag) \
+ __ao2_link((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_link(container, obj) \
+ __ao2_link((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief Add an object to a container.
@@ -1684,21 +1488,13 @@
* \note This function automatically increases the reference count to account
* for the reference that the container now holds to the object.
*/
-#define ao2_t_link_flags(container, obj, flags, tag) __ao2_link_debug((container), (obj), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_link_flags(container, obj, flags) __ao2_link_debug((container), (obj), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_t_link_flags(container, obj, flags, tag) \
+ __ao2_link((container), (obj), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_link_flags(container, obj, flags) \
+ __ao2_link((container), (obj), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-
-#define ao2_t_link(container, obj, tag) __ao2_link((container), (obj), 0)
-#define ao2_link(container, obj) __ao2_link((container), (obj), 0)
-
-#define ao2_t_link_flags(container, obj, flags, tag) __ao2_link((container), (obj), (flags))
-#define ao2_link_flags(container, obj, flags) __ao2_link((container), (obj), (flags))
-
-#endif
-
-int __ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func);
-int __ao2_link(struct ao2_container *c, void *obj_new, int flags);
+int __ao2_link(struct ao2_container *c, void *obj_new, int flags,
+ const char *tag, const char *file, int line, const char *func);
/*!
* \brief Remove an object from a container
@@ -1717,10 +1513,11 @@
* reference to the object will be automatically released. (The
* refcount will be decremented).
*/
-#ifdef REF_DEBUG
-#define ao2_t_unlink(container, obj, tag) __ao2_unlink_debug((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_unlink(container, obj) __ao2_unlink_debug((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_t_unlink(container, obj, tag) \
+ __ao2_unlink((container), (obj), 0, (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_unlink(container, obj) \
+ __ao2_unlink((container), (obj), 0, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief Remove an object from a container
@@ -1741,24 +1538,16 @@
* refcount will be decremented).
*/
-#define ao2_t_unlink_flags(container, obj, flags, tag) __ao2_unlink_debug((container), (obj), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_unlink_flags(container, obj, flags) __ao2_unlink_debug((container), (obj), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_t_unlink_flags(container, obj, flags, tag) \
+ __ao2_unlink((container), (obj), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_unlink_flags(container, obj, flags) \
+ __ao2_unlink((container), (obj), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-
-#define ao2_t_unlink(container, obj, tag) __ao2_unlink((container), (obj), 0)
-#define ao2_unlink(container, obj) __ao2_unlink((container), (obj), 0)
-
-#define ao2_t_unlink_flags(container, obj, flags, tag) __ao2_unlink((container), (obj), (flags))
-#define ao2_unlink_flags(container, obj, flags) __ao2_unlink((container), (obj), (flags))
-
-#endif
-
-void *__ao2_unlink_debug(struct ao2_container *c, void *obj, int flags, const char *tag, const char *file, int line, const char *func);
-void *__ao2_unlink(struct ao2_container *c, void *obj, int flags);
-
+void *__ao2_unlink(struct ao2_container *c, void *obj, int flags,
+ const char *tag, const char *file, int line, const char *func);
/*@} */
+
/*! \brief
* ao2_callback() is a generic function that applies cb_fn() to all objects
@@ -1842,26 +1631,15 @@
*
* @{
*/
-#ifdef REF_DEBUG
#define ao2_t_callback(c, flags, cb_fn, arg, tag) \
- __ao2_callback_debug((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ __ao2_callback((c), (flags), (cb_fn), (arg), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_callback(c, flags, cb_fn, arg) \
- __ao2_callback_debug((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ __ao2_callback((c), (flags), (cb_fn), (arg), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-
-#define ao2_t_callback(c, flags, cb_fn, arg, tag) \
- __ao2_callback((c), (flags), (cb_fn), (arg))
-#define ao2_callback(c, flags, cb_fn, arg) \
- __ao2_callback((c), (flags), (cb_fn), (arg))
-
-#endif
-
-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);
-void *__ao2_callback(struct ao2_container *c, enum search_flags flags, ao2_callback_fn *cb_fn, void *arg);
/*! @} */
@@ -1880,50 +1658,27 @@
*
* \see ao2_callback()
*/
-#ifdef REF_DEBUG
#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag) \
- __ao2_callback_data_debug((container), (flags), (cb_fn), (arg), (data), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ __ao2_callback_data((container), (flags), (cb_fn), (arg), (data), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_callback_data(container, flags, cb_fn, arg, data) \
- __ao2_callback_data_debug((container), (flags), (cb_fn), (arg), (data), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ __ao2_callback_data((container), (flags), (cb_fn), (arg), (data), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-
-#define ao2_t_callback_data(container, flags, cb_fn, arg, data, tag) \
- __ao2_callback_data((container), (flags), (cb_fn), (arg), (data))
-#define ao2_callback_data(container, flags, cb_fn, arg, data) \
- __ao2_callback_data((container), (flags), (cb_fn), (arg), (data))
-
-#endif
-
-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);
-void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
- ao2_callback_data_fn *cb_fn, void *arg, void *data);
/*! ao2_find() is a short hand for ao2_callback(c, flags, c->cmp_fn, arg)
* XXX possibly change order of arguments ?
*/
-#ifdef REF_DEBUG
#define ao2_t_find(container, arg, flags, tag) \
- __ao2_find_debug((container), (arg), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ __ao2_find((container), (arg), (flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_find(container, arg, flags) \
- __ao2_find_debug((container), (arg), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ __ao2_find((container), (arg), (flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-
-#define ao2_t_find(container, arg, flags, tag) \
- __ao2_find((container), (arg), (flags))
-#define ao2_find(container, arg, flags) \
- __ao2_find((container), (arg), (flags))
-
-#endif
-
-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 *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags);
/*! \brief
*
@@ -2083,20 +1838,13 @@
void ao2_iterator_destroy(struct ao2_iterator *iter);
#endif /* defined(TEST_FRAMEWORK) */
-#ifdef REF_DEBUG
+#define ao2_t_iterator_next(iter, tag) \
+ __ao2_iterator_next((iter), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+#define ao2_iterator_next(iter) \
+ __ao2_iterator_next((iter), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_t_iterator_next(iter, tag) __ao2_iterator_next_debug((iter), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#define ao2_iterator_next(iter) __ao2_iterator_next_debug((iter), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
-
-#else
-
-#define ao2_t_iterator_next(iter, tag) __ao2_iterator_next((iter))
-#define ao2_iterator_next(iter) __ao2_iterator_next((iter))
-
-#endif
-
-void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
-void *__ao2_iterator_next(struct ao2_iterator *iter) attribute_warn_unused_result;
+void *__ao2_iterator_next(struct ao2_iterator *iter,
+ const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
/*!
* \brief Restart an iteration.
@@ -2117,13 +1865,8 @@
* down a NULL */
void __ao2_cleanup(void *obj);
void __ao2_cleanup_debug(void *obj, const char *tag, const char *file, int line, const char *function);
-#ifdef REF_DEBUG
#define ao2_cleanup(obj) __ao2_cleanup_debug((obj), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ao2_t_cleanup(obj, tag) __ao2_cleanup_debug((obj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-#define ao2_cleanup(obj) __ao2_cleanup(obj)
-#define ao2_t_cleanup(obj, tag) __ao2_cleanup((obj))
-#endif
void ao2_iterator_cleanup(struct ao2_iterator *iter);
/*!
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 82abe99..aec7f75 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -1186,8 +1186,6 @@
__ast_channel_alloc((needqueue), (state), (cid_num), (cid_name), (acctcode), (exten), (context), (assignedids), (requestor), (amaflag), (endpoint), \
__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
-
-#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
/*!
* \brief Create a fake channel structure
*
@@ -1206,25 +1204,6 @@
*/
#define ast_dummy_channel_alloc() __ast_dummy_channel_alloc(__FILE__, __LINE__, __PRETTY_FUNCTION__)
struct ast_channel *__ast_dummy_channel_alloc(const char *file, int line, const char *function);
-#else
-/*!
- * \brief Create a fake channel structure
- *
- * \retval NULL failure
- * \retval non-NULL successfully allocated channel
- *
- * \note This function should ONLY be used to create a fake channel
- * that can then be populated with data for use in variable
- * substitution when a real channel does not exist.
- *
- * \note The created dummy channel should be destroyed by
- * ast_channel_unref(). Using ast_channel_release() needlessly
- * grabs the channel container lock and can cause a deadlock as
- * a result. Also grabbing the channel container lock reduces
- * system performance.
- */
-struct ast_channel *ast_dummy_channel_alloc(void);
-#endif
/*!
* \brief Queue one or more frames to a channel's frame queue
diff --git a/include/asterisk/format_cache.h b/include/asterisk/format_cache.h
index 9f4e06a..64e53b9 100644
--- a/include/asterisk/format_cache.h
+++ b/include/asterisk/format_cache.h
@@ -252,20 +252,13 @@
* \note The returned format has its reference count incremented. It must be
* dropped using ao2_ref or ao2_cleanup.
*/
-struct ast_format *__ast_format_cache_get(const char *name);
-struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func);
+struct ast_format *__ast_format_cache_get(const char *name,
+ const char *tag, const char *file, int line, const char *func);
-#ifdef REF_DEBUG
#define ast_format_cache_get(name) \
- __ast_format_cache_get_debug((name), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ __ast_format_cache_get((name), "ast_format_cache_get", __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ast_t_format_cache_get(name, tag) \
- __ast_format_cache_get_debug((name), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-#define ast_format_cache_get(name) \
- __ast_format_cache_get((name))
-#define ast_t_format_cache_get(name, tag) \
- __ast_format_cache_get((name))
-#endif
+ __ast_format_cache_get((name), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
diff --git a/include/asterisk/format_cap.h b/include/asterisk/format_cap.h
index 94e81f8..e422cc6 100644
--- a/include/asterisk/format_cap.h
+++ b/include/asterisk/format_cap.h
@@ -46,20 +46,14 @@
* \retval ast_format_cap object on success.
* \retval NULL on failure.
*/
-struct ast_format_cap *__ast_format_cap_alloc(enum ast_format_cap_flags flags);
-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 *__ast_format_cap_alloc(enum ast_format_cap_flags flags,
+ const char *tag, const char *file, int line, const char *func);
-#ifdef REF_DEBUG
#define ast_format_cap_alloc(flags) \
- __ast_format_cap_alloc_debug((flags), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ __ast_format_cap_alloc((flags), "ast_format_cap_alloc", \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ast_t_format_cap_alloc(flags, tag) \
- __ast_format_cap_alloc_debug((flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-#define ast_format_cap_alloc(flags) \
- __ast_format_cap_alloc((flags))
-#define ast_t_format_cap_alloc(flags, tag) \
- __ast_format_cap_alloc((flags))
-#endif
+ __ast_format_cap_alloc((flags), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief Set the global framing.
@@ -103,20 +97,15 @@
*
* \note If framing is specified here it overrides any global framing that has been set.
*/
-int __ast_format_cap_append(struct ast_format_cap *cap, struct ast_format *format, unsigned int 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);
-#ifdef REF_DEBUG
#define ast_format_cap_append(cap, format, framing) \
- __ast_format_cap_append_debug((cap), (format), (framing), "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
+ __ast_format_cap_append((cap), (format), (framing), "ast_format_cap_append", \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__)
#define ast_t_format_cap_append(cap, format, framing, tag) \
- __ast_format_cap_append_debug((cap), (format), (framing), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
-#else
-#define ast_format_cap_append(cap, format, framing) \
- __ast_format_cap_append((cap), (format), (framing))
-#define ast_t_format_cap_append(cap, format, framing, tag) \
- __ast_format_cap_append((cap), (format), (framing))
-#endif
+ __ast_format_cap_append((cap), (format), (framing), (tag), \
+ __FILE__, __LINE__, __PRETTY_FUNCTION__)
/*!
* \brief Add all codecs Asterisk knows about for a specific type to
diff --git a/include/asterisk/options.h b/include/asterisk/options.h
index 0da5799..a08b863 100644
--- a/include/asterisk/options.h
+++ b/include/asterisk/options.h
@@ -76,6 +76,8 @@
AST_OPT_FLAG_DONT_WARN = (1 << 18),
/*! End CDRs before the 'h' extension */
AST_OPT_FLAG_END_CDR_BEFORE_H_EXTEN = (1 << 19),
+ /*! Reference Debugging */
+ AST_OPT_FLAG_REF_DEBUG = (1 << 20),
/*! Always fork, even if verbose or debug settings are non-zero */
AST_OPT_FLAG_ALWAYS_FORK = (1 << 21),
/*! Disable log/verbose output to remote consoles */
@@ -131,6 +133,7 @@
#define ast_opt_hide_connect ast_test_flag(&ast_options, AST_OPT_FLAG_HIDE_CONSOLE_CONNECT)
#define ast_opt_lock_confdir ast_test_flag(&ast_options, AST_OPT_FLAG_LOCK_CONFIG_DIR)
#define ast_opt_generic_plc ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC)
+#define ast_opt_ref_debug ast_test_flag(&ast_options, AST_OPT_FLAG_REF_DEBUG)
extern struct ast_flags ast_options;
diff --git a/main/asterisk.c b/main/asterisk.c
index 574451c..86a190b 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -3424,6 +3424,12 @@
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 @@
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 edf1e95..c5b5cd9 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -118,36 +118,28 @@
#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)
-{
- struct astobj2 *p;
+#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__); \
+ })
- if (!user_data) {
- ast_log(LOG_ERROR, "user_data is NULL\n");
- return NULL;
- }
-
- 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;
- }
-
- return p;
-}
+#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
@@ -156,14 +148,43 @@
*/
#define EXTERNAL_OBJ(_p) ((_p) == NULL ? NULL : (_p)->user_data)
-int is_ao2_object(void *user_data)
+int internal_is_ao2_object(void *user_data)
{
- return (INTERNAL_OBJ(user_data) != NULL);
+ struct astobj2 *p;
+
+ if (!user_data) {
+ return 0;
+ }
+
+ p = INTERNAL_OBJ(user_data);
+
+ return !p || IS_AO2_MAGIC_BAD(p) ? 0 : 1;
+}
+
+void log_bad_ao2(void *user_data, const char *file, int line, const char *func)
+{
+ 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_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_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,8 +414,10 @@
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);
@@ -412,9 +435,10 @@
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 @@
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 @@
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 @@
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 @@
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 @@
break;
}
+ 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 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);
- }
-
- return old_refcount;
-}
-
-int __ao2_ref(void *user_data, int delta)
-{
- return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__);
}
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 @@
}
}
-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,41 +645,25 @@
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__);
}
@@ -687,11 +683,7 @@
/* 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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_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 @@
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_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 @@
#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 07d10b9..c00da9f 100644
--- a/main/astobj2_container.c
+++ b/main/astobj2_container.c
@@ -49,11 +49,7 @@
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 @@
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 @@
* \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 @@
res = 1;
break;
case AO2_CONTAINER_INSERT_NODE_REJECTED:
- __ao2_ref(node, -1);
+ ao2_t_ref(node, -1, NULL);
break;
}
}
@@ -159,16 +157,6 @@
}
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__);
}
/*!
@@ -183,10 +171,10 @@
* 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 @@
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 @@
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 @@
* 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 @@
* 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 @@
}
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 @@
}
}
-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 @@
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 @@
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 @@
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 @@
}
}
-/*
- * 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 @@
/* 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 @@
/* 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;
@@ -642,16 +583,6 @@
}
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)
@@ -665,26 +596,8 @@
/* 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 @@
{
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 @@
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 @@
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 @@
}
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 07779a5..3651ca4 100644
--- a/main/astobj2_container_private.h
+++ b/main/astobj2_container_private.h
@@ -87,26 +87,15 @@
* \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 @@
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 @@
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 110dd16..91ad2d2 100644
--- a/main/astobj2_hash.c
+++ b/main/astobj2_hash.c
@@ -104,47 +104,27 @@
/*!
* \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 @@
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 @@
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 @@
}
/* We have the first traversal node */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
return node;
}
}
@@ -482,7 +458,7 @@
}
/* We have the first traversal node */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
return node;
}
}
@@ -551,7 +527,7 @@
}
/* 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 @@
* 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 @@
}
/* 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 @@
* 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 @@
}
/* 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 @@
/*! 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 @@
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 @@
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 0583faf..ef47ed7 100644
--- a/main/astobj2_private.h
+++ b/main/astobj2_private.h
@@ -43,7 +43,24 @@
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 d3a9025..b06813d 100644
--- a/main/astobj2_rbtree.c
+++ b/main/astobj2_rbtree.c
@@ -545,47 +545,27 @@
/*!
* \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 @@
{
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 @@
}
/* 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 @@
* 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 @@
}
/* 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 @@
}
/* We have the first traversal node */
- __ao2_ref(node, +1);
+ ao2_t_ref(node, +1, NULL);
return node;
}
@@ -2018,8 +1994,6 @@
/*! 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 @@
}
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 @@
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 db126db..fee7763 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -795,7 +795,9 @@
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 @@
/* 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 4e85398..0bb3849 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -1439,15 +1439,9 @@
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 3e72976..def795c 100644
--- a/main/format_cache.c
+++ b/main/format_cache.c
@@ -457,22 +457,14 @@
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 c9c6c3b..7456a44 100644
--- a/main/format_cap.c
+++ b/main/format_cap.c
@@ -103,25 +103,13 @@
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 @@
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 @@
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 26d229f..eb959fa 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -122,10 +122,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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();
diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c
index 24a3a28..eaf1f4e 100644
--- a/res/res_musiconhold.c
+++ b/res/res_musiconhold.c
@@ -210,7 +210,7 @@
#define mohclass_ref(class,string) (ao2_t_ref((class), +1, (string)), class)
-#ifndef REF_DEBUG
+#ifndef AST_DEVMODE
#define mohclass_unref(class,string) ({ ao2_t_ref((class), -1, (string)); (struct mohclass *) NULL; })
#else
#define mohclass_unref(class,string) _mohclass_unref(class, string, __FILE__,__LINE__,__PRETTY_FUNCTION__)
@@ -219,14 +219,14 @@
struct mohclass *dup = ao2_callback(mohclasses, OBJ_POINTER, ao2_match_by_addr, class);
if (dup) {
- if (__ao2_ref_debug(dup, -1, (char *) tag, (char *) file, line, funcname) == 2) {
+ if (__ao2_ref(dup, -1, tag, file, line, funcname) == 2) {
ast_log(LOG_WARNING, "Attempt to unref mohclass %p (%s) when only 1 ref remained, and class is still in a container! (at %s:%d (%s))\n",
class, class->name, file, line, funcname);
} else {
ao2_ref(class, -1);
}
} else {
- __ao2_ref_debug(class, -1, (char *) tag, (char *) file, line, funcname);
+ __ao2_ref(class, -1, tag, file, line, funcname);
}
return NULL;
}
@@ -877,12 +877,8 @@
ast_copy_string(tmp_class.name, name, sizeof(tmp_class.name));
-#ifdef REF_DEBUG
- moh = __ao2_find_debug(mohclasses, &tmp_class, flags,
+ moh = __ao2_find(mohclasses, &tmp_class, flags,
"get_mohbyname", file, lineno, funcname);
-#else
- moh = __ao2_find(mohclasses, &tmp_class, flags);
-#endif
if (!moh && warn) {
ast_debug(1, "Music on Hold class '%s' not found in memory\n", name);
@@ -1373,17 +1369,9 @@
{
struct mohclass *class;
- if ((class =
-#ifdef REF_DEBUG
- __ao2_alloc_debug(sizeof(*class), moh_class_destructor,
- AO2_ALLOC_OPT_LOCK_MUTEX, "Allocating new moh class", file, line, funcname, 1)
-#elif defined(__AST_DEBUG_MALLOC)
- __ao2_alloc_debug(sizeof(*class), moh_class_destructor,
- AO2_ALLOC_OPT_LOCK_MUTEX, "Allocating new moh class", file, line, funcname, 0)
-#else
- ao2_alloc(sizeof(*class), moh_class_destructor)
-#endif
- )) {
+ class = __ao2_alloc(sizeof(*class), moh_class_destructor, AO2_ALLOC_OPT_LOCK_MUTEX,
+ "Allocating new moh class", file, line, funcname);
+ if (class) {
class->format = ao2_bump(ast_format_slin);
class->srcfd = -1;
}
--
To view, visit https://gerrit.asterisk.org/140
To unsubscribe, visit https://gerrit.asterisk.org/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Icf3552721fe999365ba8a8cf00a965aa6b897cc1
Gerrit-PatchSet: 8
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Corey Farrell <git at cfware.com>
Gerrit-Reviewer: Corey Farrell <git at cfware.com>
Gerrit-Reviewer: Mark Michelson <mmichelson at digium.com>
Gerrit-Reviewer: Matt Jordan <mjordan at digium.com>
Gerrit-Reviewer: Richard Mudgett <rmudgett at digium.com>
More information about the asterisk-commits
mailing list