[asterisk-commits] russell: branch russell/chan_refcount r82328 - in /team/russell/chan_refcount...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Sep 13 11:30:50 CDT 2007
Author: russell
Date: Thu Sep 13 11:30:50 2007
New Revision: 82328
URL: http://svn.digium.com/view/asterisk?view=rev&rev=82328
Log:
* constify some args to manager functions
* add two new functions ao2_lock_both() and ao2_unlock_both()
- These functions are intended to be used when two objects must be locked
at the same time, and thus deadlocks must be avoided. However, instead of
using an expensive trylock/unlock/lock/sleep/trylock loop, it just locks
the object with a lower pointer address first to ensure that the locking
is always done in the same order.
Modified:
team/russell/chan_refcount/include/asterisk/astobj2.h
team/russell/chan_refcount/include/asterisk/channel.h
team/russell/chan_refcount/include/asterisk/manager.h
team/russell/chan_refcount/main/astobj2.c
team/russell/chan_refcount/main/manager.c
Modified: team/russell/chan_refcount/include/asterisk/astobj2.h
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/include/asterisk/astobj2.h?view=diff&rev=82328&r1=82327&r2=82328
==============================================================================
--- team/russell/chan_refcount/include/asterisk/astobj2.h (original)
+++ team/russell/chan_refcount/include/asterisk/astobj2.h Thu Sep 13 11:30:50 2007
@@ -193,6 +193,21 @@
int ao2_lock(void *a);
/*!
+ * \brief Lock two objects.
+ *
+ * \param obj1 a pointer to the first object to lock
+ * \param obj2 a pointer to the second object to lock
+ *
+ * This function should be used in all cases where two objects need to be
+ * locked at the same time. It avoids deadlocks by ensuring the same locking
+ * order is always used, by locking the object with a lower pointer address
+ * first.
+ *
+ * \return 0 on success, other values on error
+ */
+int ao2_lock_both(void *obj1, void *obj2);
+
+/*!
* \brief Try to lock an object.
*
* \param a A pointer to the object we want lock.
@@ -208,6 +223,20 @@
* \return 0 on success, other values on error.
*/
int ao2_unlock(void *a);
+
+/*!
+ * \brief Unlock two objects.
+ *
+ * \param obj1 a pointer to the first object to lock
+ * \param obj2 a pointer to the second object to lock
+ *
+ * This function can be used with ao2_lock_both, but isn't necessarily
+ * required, as the order in which objects are unlocked is not as important
+ * as the order in which they are locked.
+ *
+ * \return 0 on success, other values on error
+ */
+int ao2_unlock_both(void *obj1, void *obj2);
/*!
*
Modified: team/russell/chan_refcount/include/asterisk/channel.h
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/include/asterisk/channel.h?view=diff&rev=82328&r1=82327&r2=82328
==============================================================================
--- team/russell/chan_refcount/include/asterisk/channel.h (original)
+++ team/russell/chan_refcount/include/asterisk/channel.h Thu Sep 13 11:30:50 2007
@@ -1487,6 +1487,9 @@
#define ast_channel_unlock(c) ao2_unlock(c)
#define ast_channel_trylock(c) ao2_trylock(c)
+#define ast_channel_lock_both(c1, c2) ao2_lock_both(c1, c2)
+#define ast_channel_unlock_both(c1, c2) ao2_unlock_both(c1, c2)
+
static force_inline struct ast_channel *ast_channel_ref(struct ast_channel *chan)
{
ao2_ref(chan, +1);
Modified: team/russell/chan_refcount/include/asterisk/manager.h
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/include/asterisk/manager.h?view=diff&rev=82328&r1=82327&r2=82328
==============================================================================
--- team/russell/chan_refcount/include/asterisk/manager.h (original)
+++ team/russell/chan_refcount/include/asterisk/manager.h Thu Sep 13 11:30:50 2007
@@ -180,7 +180,7 @@
struct ast_variable *astman_get_variables(const struct message *m);
/*! Send error in manager transaction */
-void astman_send_error(struct mansession *s, const struct message *m, char *error);
+void astman_send_error(struct mansession *s, const struct message *m, const char *error);
void astman_send_response(struct mansession *s, const struct message *m, char *resp, char *msg);
void astman_send_ack(struct mansession *s, const struct message *m, char *msg);
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag);
Modified: team/russell/chan_refcount/main/astobj2.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/main/astobj2.c?view=diff&rev=82328&r1=82327&r2=82328
==============================================================================
--- team/russell/chan_refcount/main/astobj2.c (original)
+++ team/russell/chan_refcount/main/astobj2.c Thu Sep 13 11:30:50 2007
@@ -25,6 +25,13 @@
#include "asterisk/utils.h"
#include "asterisk/cli.h"
+#ifndef MIN
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
/*!
* astobj2 objects are always preceded by this data structure,
* which contains a lock, a reference counter,
@@ -131,6 +138,29 @@
return ast_mutex_lock(&p->priv_data.lock);
}
+int ao2_lock_both(void *user_data1, void *user_data2)
+{
+ struct astobj2 *p1, *p2;
+ int res;
+
+ p1 = INTERNAL_OBJ(MIN(user_data1, user_data2));
+ p2 = INTERNAL_OBJ(MAX(user_data1, user_data2));
+
+ res = ast_mutex_lock(&p1->priv_data.lock);
+ if (!res) {
+#ifdef AO2_DEBUG
+ ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+#endif
+ res = ast_mutex_lock(&p2->priv_data.lock);
+#ifdef AO2_DEBUG
+ if (!res)
+ ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+#endif
+ }
+
+ return res;
+}
+
int ao2_trylock(void *user_data)
{
struct astobj2 *p = INTERNAL_OBJ(user_data);
@@ -157,6 +187,29 @@
ast_atomic_fetchadd_int(&ao2.total_locked, -1);
return ast_mutex_unlock(&p->priv_data.lock);
+}
+
+int ao2_unlock_both(void *user_data1, void *user_data2)
+{
+ struct astobj2 *p1, *p2;
+ int res;
+
+ p1 = INTERNAL_OBJ(user_data1);
+ p2 = INTERNAL_OBJ(user_data2);
+
+ res = ast_mutex_unlock(&p1->priv_data.lock);
+ if (!res) {
+#ifdef AO2_DEBUG
+ ast_atomic_fetchadd_int(&ao2.total_locked, -1);
+#endif
+ res = ast_mutex_unlock(&p2->priv_data.lock);
+#ifdef AO2_DEBUG
+ if (!res)
+ ast_atomic_fetchadd_int(&ao2.total_locked, -1);
+#endif
+ }
+
+ return res;
}
/*
Modified: team/russell/chan_refcount/main/manager.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/main/manager.c?view=diff&rev=82328&r1=82327&r2=82328
==============================================================================
--- team/russell/chan_refcount/main/manager.c (original)
+++ team/russell/chan_refcount/main/manager.c Thu Sep 13 11:30:50 2007
@@ -886,7 +886,7 @@
* XXX MSG_MOREDATA should go to a header file.
*/
#define MSG_MOREDATA ((char *)astman_send_response)
-static void astman_send_response_full(struct mansession *s, const struct message *m, char *resp, char *msg, char *listflag)
+static void astman_send_response_full(struct mansession *s, const struct message *m, char *resp, const char *msg, char *listflag)
{
const char *id = astman_get_header(m,"ActionID");
@@ -908,7 +908,7 @@
astman_send_response_full(s, m, resp, msg, NULL);
}
-void astman_send_error(struct mansession *s, const struct message *m, char *error)
+void astman_send_error(struct mansession *s, const struct message *m, const char *error)
{
astman_send_response_full(s, m, "Error", error, NULL);
}
More information about the asterisk-commits
mailing list