[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