summaryrefslogtreecommitdiff
path: root/main/format.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2012-02-28 18:15:34 +0000
committerRichard Mudgett <rmudgett@digium.com>2012-02-28 18:15:34 +0000
commit2e834f7d36be6b7fd2531f4e4ac3dcbb050a2bdc (patch)
tree7a9ebd0ea02ff83ef870b1fa9377e5d334a57aea /main/format.c
parentbd7e9dae6663ab7f53213916fc001105b7e8bd94 (diff)
Astobj2 locking enhancement.
Add the ability to specify what kind of locking an ao2 object has when it is allocated. The locking could be one of: MUTEX, RWLOCK, or none. New API: ao2_t_alloc_options() ao2_alloc_options() ao2_t_container_alloc_options() ao2_container_alloc_options() ao2_rdlock() ao2_wrlock() ao2_tryrdlock() ao2_trywrlock() The OBJ_NOLOCK and AO2_ITERATOR_DONTLOCK flags have a slight meaning change. They no longer mean that the object is protected by an external mechanism. They mean the lock associated with the object has already been manually obtained by one of the ao2_lock calls. This change is necessary for RWLOCK support since they are not reentrant. Also an operation on an ao2 container may require promoting a read lock to a write lock by releasing the already held read lock to re-acquire as a write lock. Replaced API calls: ao2_t_link_nolock() ao2_link_nolock() ao2_t_unlink_nolock() ao2_unlink_nolock() with the respective ao2_t_link_flags() ao2_link_flags() ao2_t_unlink_flags() ao2_unlink_flags() API calls to be more flexible and to allow an anticipated enhancement to control linking duplicate objects into a container. The changes to format.c and format_cap.c are taking advantange of the new ao2 locking options to simplify the use of the format capabilities containers. Review: https://reviewboard.asterisk.org/r/1554/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@357272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/format.c')
-rw-r--r--main/format.c97
1 files changed, 35 insertions, 62 deletions
diff --git a/main/format.c b/main/format.c
index 82e3d2628..3af0f15f8 100644
--- a/main/format.c
+++ b/main/format.c
@@ -41,22 +41,17 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
#define FORMAT_CONFIG "codecs.conf"
-/*! This is the container for all the format attribute interfaces.
- * An ao2 container was chosen for fast lookup. */
+/*!
+ * \brief Container for all the format attribute interfaces.
+ * \note This container uses RWLOCKs instead of MUTEX locks. .
+ * \note 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. */
-static ast_rwlock_t ilock;
-
/*! a wrapper is used put interfaces into the ao2 container. */
struct interface_ao2_wrapper {
enum ast_format_id id;
const 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;
};
/*! \brief Format List container, This container is never directly accessed outside
@@ -84,12 +79,6 @@ static int interface_hash_cb(const void *obj, const int flags)
return wrapper->id;
}
-static void interface_destroy_cb(void *obj)
-{
- struct interface_ao2_wrapper *wrapper = obj;
- ast_rwlock_destroy(&wrapper->wraplock);
-}
-
void ast_format_copy(struct ast_format *dst, const struct ast_format *src)
{
memcpy(dst, src, sizeof(struct ast_format));
@@ -107,16 +96,11 @@ int ast_format_get_video_mark(const struct ast_format *format)
static struct interface_ao2_wrapper *find_interface(const struct ast_format *format)
{
- struct interface_ao2_wrapper *wrapper;
struct interface_ao2_wrapper tmp_wrapper = {
.id = format->id,
};
- ast_rwlock_rdlock(&ilock);
- wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK));
- ast_rwlock_unlock(&ilock);
-
- return wrapper;
+ return ao2_find(interfaces, &tmp_wrapper, OBJ_POINTER);
}
static int has_interface(const struct ast_format *format)
@@ -143,16 +127,16 @@ static int format_set_helper(struct ast_format *format, va_list ap)
return -1;
}
- ast_rwlock_rdlock(&wrapper->wraplock);
+ ao2_rdlock(wrapper);
if (!wrapper->interface || !wrapper->interface->format_attr_set) {
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);
return -1;
}
wrapper->interface->format_attr_set(&format->fattr, ap);
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);
return 0;
@@ -207,12 +191,12 @@ static int format_isset_helper(const struct ast_format *format, va_list ap)
return -1;
}
- ast_rwlock_rdlock(&wrapper->wraplock);
+ ao2_rdlock(wrapper);
if (!wrapper->interface ||
!wrapper->interface->format_attr_set ||
!wrapper->interface->format_attr_cmp) {
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);
return -1;
}
@@ -228,7 +212,7 @@ static int format_isset_helper(const struct ast_format *format, va_list ap)
res = (res == AST_FORMAT_CMP_NOT_EQUAL) ? -1 : 0;
}
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);
return res;
@@ -249,21 +233,22 @@ int ast_format_get_value(const struct ast_format *format, int key, void *value)
{
int res = 0;
struct interface_ao2_wrapper *wrapper;
+
if (!(wrapper = find_interface(format))) {
return -1;
}
- ast_rwlock_rdlock(&wrapper->wraplock);
+ ao2_rdlock(wrapper);
if (!wrapper->interface ||
!wrapper->interface->format_attr_get_val) {
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);
return -1;
}
res = wrapper->interface->format_attr_get_val(&format->fattr, key, value);
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);
return res;
@@ -281,16 +266,16 @@ static enum ast_format_cmp_res format_cmp_helper(const struct ast_format *format
return res;
}
- ast_rwlock_rdlock(&wrapper->wraplock);
+ ao2_rdlock(wrapper);
if (!wrapper->interface || !wrapper->interface->format_attr_cmp) {
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);
return res;
}
res = wrapper->interface->format_attr_cmp(&format1->fattr, &format2->fattr);
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);
return res;
@@ -318,11 +303,11 @@ static int format_joint_helper(const struct ast_format *format1, const struct as
return res;
}
- ast_rwlock_rdlock(&wrapper->wraplock);
+ ao2_rdlock(wrapper);
if (wrapper->interface && wrapper->interface->format_attr_get_joint) {
res = wrapper->interface->format_attr_get_joint(&format1->fattr, &format2->fattr, &result->fattr);
}
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);
@@ -1066,21 +1051,13 @@ init_list_cleanup:
int ast_format_attr_init(void)
{
ast_cli_register_multiple(my_clis, ARRAY_LEN(my_clis));
- if (ast_rwlock_init(&ilock)) {
- return -1;
- }
- if (!(interfaces = ao2_container_alloc(283, interface_hash_cb, interface_cmp_cb))) {
- goto init_cleanup;
+ interfaces = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK,
+ 283, interface_hash_cb, interface_cmp_cb);
+ if (!interfaces) {
+ return -1;
}
return 0;
-
-init_cleanup:
- ast_rwlock_destroy(&ilock);
- if (interfaces) {
- ao2_ref(interfaces, -1);
- }
- return -1;
}
static int custom_celt_format(struct ast_format_list *entry, unsigned int maxbitrate, unsigned int framesize)
@@ -1310,28 +1287,28 @@ int ast_format_attr_reg_interface(const struct ast_format_attr_interface *interf
* anticipation of adding a new interface and to prevent a
* duplicate from sneaking in between the check and add.
*/
- ast_rwlock_wrlock(&ilock);
+ ao2_wrlock(interfaces);
/* check for duplicates first*/
if ((wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_NOLOCK)))) {
- ast_rwlock_unlock(&ilock);
+ ao2_unlock(interfaces);
ast_log(LOG_WARNING, "Can not register attribute interface for format id %d, interface already exists.\n", interface->id);
ao2_ref(wrapper, -1);
return -1;
}
- if (!(wrapper = ao2_alloc(sizeof(*wrapper), interface_destroy_cb))) {
- ast_rwlock_unlock(&ilock);
+ wrapper = ao2_alloc_options(sizeof(*wrapper), NULL, AO2_ALLOC_OPT_LOCK_RWLOCK);
+ if (!wrapper) {
+ ao2_unlock(interfaces);
return -1;
}
wrapper->interface = interface;
wrapper->id = interface->id;
- ast_rwlock_init(&wrapper->wraplock);
/* The write lock is already held. */
- ao2_link_nolock(interfaces, wrapper);
- ast_rwlock_unlock(&ilock);
+ ao2_link_flags(interfaces, wrapper, OBJ_NOLOCK);
+ ao2_unlock(interfaces);
ao2_ref(wrapper, -1);
@@ -1359,17 +1336,13 @@ int ast_format_attr_unreg_interface(const struct ast_format_attr_interface *inte
.id = interface->id,
};
- /* 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);
+ if (!(wrapper = ao2_find(interfaces, &tmp_wrapper, (OBJ_POINTER | OBJ_UNLINK)))) {
return -1;
}
- ast_rwlock_unlock(&ilock);
- ast_rwlock_wrlock(&wrapper->wraplock);
+ ao2_wrlock(wrapper);
wrapper->interface = NULL;
- ast_rwlock_unlock(&wrapper->wraplock);
+ ao2_unlock(wrapper);
ao2_ref(wrapper, -1);