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