[Asterisk-code-review] astobj2: Support using a separate object for locking. (asterisk[master])

Corey Farrell asteriskteam at digium.com
Sat Aug 27 10:55:17 CDT 2016


Corey Farrell has uploaded a new change for review.

  https://gerrit.asterisk.org/3746

Change subject: astobj2: Support using a separate object for locking.
......................................................................

astobj2: Support using a separate object for locking.

Create ao2_alloc_with_lockobj function to support shared locking.

Change-Id: Iba687eb9843922be7e481e23a32c0700ecf88a80
---
M include/asterisk/astobj2.h
M main/astobj2.c
2 files changed, 79 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/46/3746/1

diff --git a/include/asterisk/astobj2.h b/include/asterisk/astobj2.h
index 0472c1b..2caa598 100644
--- a/include/asterisk/astobj2.h
+++ b/include/asterisk/astobj2.h
@@ -368,6 +368,8 @@
 	AO2_ALLOC_OPT_LOCK_NOLOCK = (2 << 0),
 	/*! The ao2 object locking option field mask. */
 	AO2_ALLOC_OPT_LOCK_MASK = (3 << 0),
+	/*! The ao2 object uses a separate object for locking. */
+	AO2_ALLOC_OPT_LOCK_OBJ = AO2_ALLOC_OPT_LOCK_MASK,
 };
 
 /*!
@@ -406,6 +408,12 @@
 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;
 
+#define ao2_alloc_with_lockobj(data_size, destructor_fn, lockobj, tag) \
+	__ao2_alloc_with_lockobj((data_size), (destructor_fn), (lockobj), (tag), __FILE__, __LINE__, __PRETTY_FUNCTION__)
+
+void *__ao2_alloc_with_lockobj(size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj,
+	const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result;
+
 /*! @} */
 
 /*! \brief
diff --git a/main/astobj2.c b/main/astobj2.c
index 5c92f26..8041210 100644
--- a/main/astobj2.c
+++ b/main/astobj2.c
@@ -108,6 +108,17 @@
 	void *user_data[0];
 };
 
+struct ao2_lockobj_priv {
+	void *lock;
+};
+
+/* AstObj2 with locking provided by a separate object. */
+struct astobj2_lockobj {
+	struct ao2_lockobj_priv lockobj;
+	struct __priv_data priv_data;
+	void *user_data[0];
+};
+
 #ifdef AO2_DEBUG
 struct ao2_stats ao2;
 #endif
@@ -117,6 +128,9 @@
 
 #define INTERNAL_OBJ_RWLOCK(user_data) \
 	((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
+
+#define INTERNAL_OBJ_LOCKOBJ(user_data) \
+	((struct astobj2_lockobj *) (((char *) (user_data)) - sizeof(struct astobj2_lockobj)))
 
 #define INTERNAL_OBJ(user_data) \
 	(struct astobj2 *) ((char *) user_data - sizeof(struct astobj2))
@@ -187,6 +201,7 @@
 	struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
 	struct astobj2_lock *obj_mutex;
 	struct astobj2_rwlock *obj_rwlock;
+	struct astobj2_lockobj *obj_lockobj;
 	int res = 0;
 
 	if (obj == NULL) {
@@ -231,6 +246,10 @@
 	case AO2_ALLOC_OPT_LOCK_NOLOCK:
 		/* The ao2 object has no lock. */
 		break;
+	case AO2_ALLOC_OPT_LOCK_OBJ:
+		obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+		res = __ao2_lock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
+		break;
 	default:
 		ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
 			user_data);
@@ -245,6 +264,7 @@
 	struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
 	struct astobj2_lock *obj_mutex;
 	struct astobj2_rwlock *obj_rwlock;
+	struct astobj2_lockobj *obj_lockobj;
 	int res = 0;
 	int current_value;
 
@@ -281,6 +301,10 @@
 	case AO2_ALLOC_OPT_LOCK_NOLOCK:
 		/* The ao2 object has no lock. */
 		break;
+	case AO2_ALLOC_OPT_LOCK_OBJ:
+		obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+		res = __ao2_unlock(obj_lockobj->lockobj.lock, file, func, line, var);
+		break;
 	default:
 		ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
 			user_data);
@@ -295,6 +319,7 @@
 	struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
 	struct astobj2_lock *obj_mutex;
 	struct astobj2_rwlock *obj_rwlock;
+	struct astobj2_lockobj *obj_lockobj;
 	int res = 0;
 
 	if (obj == NULL) {
@@ -339,6 +364,10 @@
 	case AO2_ALLOC_OPT_LOCK_NOLOCK:
 		/* The ao2 object has no lock. */
 		return 0;
+	case AO2_ALLOC_OPT_LOCK_OBJ:
+		obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+		res = __ao2_trylock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
+		break;
 	default:
 		ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
 			user_data);
@@ -370,6 +399,7 @@
 {
 	struct astobj2 *obj = INTERNAL_OBJ(user_data);
 	struct astobj2_rwlock *obj_rwlock;
+	struct astobj2_lockobj *obj_lockobj;
 	enum ao2_lock_req orig_lock;
 
 	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
@@ -399,6 +429,10 @@
 			}
 			break;
 		}
+		break;
+	case AO2_ALLOC_OPT_LOCK_OBJ:
+		obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+		orig_lock = __adjust_lock(obj_lockobj->lockobj.lock, lock_how, keep_stronger);
 		break;
 	default:
 		ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
@@ -441,6 +475,7 @@
 	struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
 	struct astobj2_lock *obj_mutex;
 	struct astobj2_rwlock *obj_rwlock;
+	struct astobj2_lockobj *obj_lockobj;
 	int current_value;
 	int ret;
 	void *weakproxy = NULL;
@@ -552,6 +587,12 @@
 	case AO2_ALLOC_OPT_LOCK_NOLOCK:
 		ast_free(obj);
 		break;
+	case AO2_ALLOC_OPT_LOCK_OBJ:
+		obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
+		ao2_t_ref(obj_lockobj->lockobj.lock, -1, "release lockobj");
+
+		ast_free(obj_lockobj);
+		break;
 	default:
 		ast_log(__LOG_ERROR, file, line, func,
 			"Invalid lock option on ao2 object %p\n", user_data);
@@ -581,13 +622,14 @@
 	}
 }
 
-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)
+static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options,
+	void *lockobj, const char *tag, const char *file, int line, const char *func)
 {
 	/* allocation */
 	struct astobj2 *obj;
 	struct astobj2_lock *obj_mutex;
 	struct astobj2_rwlock *obj_rwlock;
+	struct astobj2_lockobj *obj_lockobj;
 
 	switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
 	case AO2_ALLOC_OPT_LOCK_MUTEX:
@@ -613,6 +655,20 @@
 		if (obj == NULL) {
 			return NULL;
 		}
+		break;
+	case AO2_ALLOC_OPT_LOCK_OBJ:
+		lockobj = ao2_t_bump(lockobj, "set lockobj");
+		if (!lockobj) {
+			ast_log(__LOG_ERROR, file, line, func, "AO2_ALLOC_OPT_LOCK_OBJ requires a non-NULL lockobj.\n");
+		}
+
+		obj_lockobj = __ast_calloc(1, sizeof(*obj_lockobj) + data_size, file, line, func);
+		if (obj_lockobj == NULL) {
+			return NULL;
+		}
+
+		obj_lockobj->lockobj.lock = lockobj;
+		obj = (struct astobj2 *) &obj_lockobj->priv_data;
 		break;
 	default:
 		/* Invalid option value. */
@@ -643,6 +699,19 @@
 	return EXTERNAL_OBJ(obj);
 }
 
+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)
+{
+	return internal_ao2_alloc(data_size, destructor_fn, options, NULL, tag, file, line, func);
+}
+
+void *__ao2_alloc_with_lockobj(size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj,
+	const char *tag, const char *file, int line, const char *func)
+{
+	return internal_ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_OBJ, lockobj,
+		tag, file, line, func);
+}
+
 unsigned int ao2_options_get(void *obj)
 {
 	struct astobj2 *orig_obj;

-- 
To view, visit https://gerrit.asterisk.org/3746
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iba687eb9843922be7e481e23a32c0700ecf88a80
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Corey Farrell <git at cfware.com>



More information about the asterisk-code-review mailing list