[asterisk-commits] dvossel: branch dvossel/fixtheworld_phase1_step1 r299177 - /team/dvossel/fixt...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Dec 20 18:41:01 UTC 2010
Author: dvossel
Date: Mon Dec 20 12:40:58 2010
New Revision: 299177
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=299177
Log:
protect format interfaces with read/write lock
Modified:
team/dvossel/fixtheworld_phase1_step1/main/format.c
team/dvossel/fixtheworld_phase1_step1/main/format_cap.c
Modified: team/dvossel/fixtheworld_phase1_step1/main/format.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/fixtheworld_phase1_step1/main/format.c?view=diff&rev=299177&r1=299176&r2=299177
==============================================================================
--- team/dvossel/fixtheworld_phase1_step1/main/format.c (original)
+++ team/dvossel/fixtheworld_phase1_step1/main/format.c Mon Dec 20 12:40:58 2010
@@ -31,15 +31,24 @@
#include "asterisk/version.h"
#include "asterisk/format.h"
#include "asterisk/astobj2.h"
+#include "asterisk/lock.h"
/*! This is the container for all the format attribute interfaces.
* An ao2 container was chosen for fast lookup. */
static struct ao2_container *interfaces;
+
+/*! This is the lock used to protect the interfaces container. Yes, ao2_containers
+ * do have their own locking, but we need the capability of performing read/write
+ * locks on this specific container. */
+ast_rwlock_t ilock;
/*! a wrapper is used put interfaces into the ao2 container. */
struct interface_ao2_wrapper {
enum ast_format_id id;
struct ast_format_attr_interface *interface;
+ /*! a read write lock must be used to protect the wrapper instead
+ * of the ao2 lock. */
+ ast_rwlock_t wraplock;
};
static int interface_cmp_cb(void *obj, void *arg, int flags)
@@ -54,6 +63,12 @@
{
struct interface_ao2_wrapper *wrapper = (struct interface_ao2_wrapper *) obj;
return wrapper->id;
+}
+
+static void interface_destroy_cb(void *obj)
+{
+ struct interface_ao2_wrapper *wrapper = (struct interface_ao2_wrapper *) obj;
+ ast_rwlock_destroy(&wrapper->wraplock);
}
void ast_format_copy(struct ast_format *src, struct ast_format *dst)
@@ -75,15 +90,19 @@
va_end(ap);
return -1;
}
- if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, OBJ_POINTER))) {
+
+ ast_rwlock_rdlock(&ilock);
+ if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) {
va_end(ap);
ast_log(LOG_WARNING, "Could not find format interface to set\n");
- return -1;
- }
-
- ao2_lock(wrapper);
+ ast_rwlock_unlock(&ilock);
+ return -1;
+ }
+ ast_rwlock_unlock(&ilock);
+
+ ast_rwlock_rdlock(&wrapper->wraplock);
if (!wrapper->interface || !wrapper->interface->format_attr_set) {
- ao2_unlock(wrapper);
+ ast_rwlock_unlock(&wrapper->wraplock);
ao2_ref(wrapper, -1);
va_end(ap);
return -1;
@@ -92,7 +111,7 @@
/* The interface is responsible for calling va_end() now. */
wrapper->interface->format_attr_set(&format->fattr, ap);
- ao2_unlock(wrapper);
+ ast_rwlock_unlock(&wrapper->wraplock);
ao2_ref(wrapper, -1);
return 0;
@@ -133,17 +152,21 @@
va_end(ap);
return -1;
}
- if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, OBJ_POINTER))) {
+
+ ast_rwlock_rdlock(&ilock);
+ if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) {
va_end(ap);
- return -1;
- }
-
- ao2_lock(wrapper);
+ ast_rwlock_unlock(&ilock);
+ return -1;
+ }
+ ast_rwlock_unlock(&ilock);
+
+ ast_rwlock_rdlock(&wrapper->wraplock);
if (!wrapper->interface ||
!wrapper->interface->format_attr_set ||
!wrapper->interface->format_attr_cmp) {
- ao2_unlock(wrapper);
+ ast_rwlock_unlock(&wrapper->wraplock);
ao2_ref(wrapper, -1);
va_end(ap);
return -1;
@@ -155,7 +178,7 @@
/* use our tmp structure to tell if the attributes are set or not */
res = wrapper->interface->format_attr_cmp(&tmp.fattr, &format->fattr);
- ao2_unlock(wrapper);
+ ast_rwlock_unlock(&wrapper->wraplock);
ao2_ref(wrapper, -1);
return (res == AST_FORMAT_CMP_NOT_SUBSET) ? -1 : 0;
@@ -184,20 +207,24 @@
if (!interfaces) {
return res;
}
- if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, OBJ_POINTER))) {
+
+ ast_rwlock_rdlock(&ilock);
+ if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) {
+ ast_rwlock_unlock(&ilock);
return res;
}
-
- ao2_lock(wrapper);
+ ast_rwlock_unlock(&ilock);
+
+ ast_rwlock_rdlock(&wrapper->wraplock);
if (!wrapper->interface || !wrapper->interface->format_attr_cmp) {
- ao2_unlock(wrapper);
+ ast_rwlock_unlock(&wrapper->wraplock);
ao2_ref(wrapper, -1);
return res;
}
res = wrapper->interface->format_attr_cmp(&format1->fattr, &format2->fattr);
- ao2_unlock(wrapper);
+ ast_rwlock_unlock(&wrapper->wraplock);
ao2_ref(wrapper, -1);
return res;
@@ -226,21 +253,25 @@
if (!interfaces) {
return res;
}
- if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, OBJ_POINTER))) {
+
+ ast_rwlock_rdlock(&ilock);
+ if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) {
/* if no interface is present, we assume formats are joint by id alone */
+ ast_rwlock_unlock(&ilock);
return res;
}
-
- ao2_lock(wrapper);
+ ast_rwlock_unlock(&ilock);
+
+ ast_rwlock_rdlock(&wrapper->wraplock);
if (!wrapper->interface || !wrapper->interface->format_attr_get_joint) {
- ao2_unlock(wrapper);
+ ast_rwlock_unlock(&wrapper->wraplock);
ao2_ref(wrapper, -1);
return res;
}
res = wrapper->interface->format_attr_get_joint(&format1->fattr, &format2->fattr, &result->fattr);
- ao2_unlock(wrapper);
+ ast_rwlock_unlock(&wrapper->wraplock);
ao2_ref(wrapper, -1);
return res;
@@ -253,34 +284,6 @@
}
result->id = format1->id;
return format_joint_helper(format1, format2, result);
-}
-
-int ast_format_attr_reg_interface(struct ast_format_attr_interface *interface)
-{
- struct interface_ao2_wrapper *wrapper;
-
- /* check for duplicates first, remove if they exist */
- ast_format_attr_unreg_interface(interface);
-
- if (!interfaces &&
- !(interfaces = ao2_container_alloc(256,
- interface_hash_cb,
- interface_cmp_cb))) {
- ast_log(LOG_WARNING, "Failed to create format attribute interface container\n");
- return -1;
- }
-
- if (!(wrapper = ao2_alloc(sizeof(*wrapper), NULL))) {
- return -1;
- }
-
- wrapper->interface = interface;
- wrapper->id = interface->id;
-
- ao2_link(interfaces, wrapper);
- ao2_ref(wrapper, -1);
-
- return 0;
}
uint64_t ast_format_to_iax2(struct ast_format *format)
@@ -472,6 +475,47 @@
return NULL;
}
+/*! \internal
+ * \brief Initiate interface container and rw lock. */
+static int format_init(void)
+{
+ if (!(interfaces = ao2_container_alloc(256, interface_hash_cb, interface_cmp_cb))) {
+ return -1;
+ }
+ ast_rwlock_init(&ilock);
+ return 0;
+}
+
+int ast_format_attr_reg_interface(struct ast_format_attr_interface *interface)
+{
+ struct interface_ao2_wrapper *wrapper;
+
+ /* check for duplicates first, remove if they exist */
+ ast_format_attr_unreg_interface(interface);
+
+ if (!interfaces && (format_init())) {
+ ast_log(LOG_WARNING, "Failed to create format attribute interface container\n");
+ return -1;
+ }
+
+ if (!(wrapper = ao2_alloc(sizeof(*wrapper), interface_destroy_cb))) {
+ return -1;
+ }
+
+ wrapper->interface = interface;
+ wrapper->id = interface->id;
+ ast_rwlock_init(&wrapper->wraplock);
+
+ /* use the write lock whenever the interface container is modified */
+ ast_rwlock_wrlock(&ilock);
+ ao2_link(interfaces, wrapper);
+ ast_rwlock_unlock(&ilock);
+
+ ao2_ref(wrapper, -1);
+
+ return 0;
+}
+
int ast_format_attr_unreg_interface(struct ast_format_attr_interface *interface)
{
struct interface_ao2_wrapper *wrapper;
@@ -483,13 +527,17 @@
return -1;
}
- if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, OBJ_POINTER | OBJ_UNLINK))) {
- return -1;
- }
-
- ao2_lock(wrapper);
+ /* use the write lock whenever the interface container is modified */
+ ast_rwlock_wrlock(&ilock);
+ if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_UNLINK | OBJ_NOLOCK)))) {
+ ast_rwlock_unlock(&ilock);
+ return -1;
+ }
+ ast_rwlock_unlock(&ilock);
+
+ ast_rwlock_wrlock(&wrapper->wraplock);
wrapper->interface = NULL;
- ao2_unlock(wrapper);
+ ast_rwlock_unlock(&wrapper->wraplock);
ao2_ref(wrapper, -1);
Modified: team/dvossel/fixtheworld_phase1_step1/main/format_cap.c
URL: http://svnview.digium.com/svn/asterisk/team/dvossel/fixtheworld_phase1_step1/main/format_cap.c?view=diff&rev=299177&r1=299176&r2=299177
==============================================================================
--- team/dvossel/fixtheworld_phase1_step1/main/format_cap.c (original)
+++ team/dvossel/fixtheworld_phase1_step1/main/format_cap.c Mon Dec 20 12:40:58 2010
@@ -164,13 +164,14 @@
}
/*! \internal
- * \brief this struct is just used for the ast_cap_joint function so we
- * can provide both a format and a result ast_cap structure as arguments
- * to the make_joint ao2 callback function. */
+ * \brief this struct is just used for the ast_cap_joint function so we can provide
+ * both a format and a result ast_cap structure as arguments to the find_joint_cb
+ * ao2 callback function.
+ */
struct find_joint_data {
- /* format to compare to for joint capabilities */
+ /*! format to compare to for joint capabilities */
struct ast_format *format;
- /* if joint formmat exists with above format, add it to the result container */
+ /*! if joint formmat exists with above format, add it to the result container */
struct ast_cap *joint_cap;
};
More information about the asterisk-commits
mailing list