[asterisk-commits] mjordan: branch mjordan/12-memorypool r423231 - /team/mjordan/12-memorypool/m...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Sep 16 16:49:05 CDT 2014


Author: mjordan
Date: Tue Sep 16 16:49:01 2014
New Revision: 423231

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=423231
Log:
Update branch with latest whatevers

No idea where this branch is at, but it'd be nice to not lose this work.

Modified:
    team/mjordan/12-memorypool/main/astobj2.c

Modified: team/mjordan/12-memorypool/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/12-memorypool/main/astobj2.c?view=diff&rev=423231&r1=423230&r2=423231
==============================================================================
--- team/mjordan/12-memorypool/main/astobj2.c (original)
+++ team/mjordan/12-memorypool/main/astobj2.c Tue Sep 16 16:49:01 2014
@@ -98,344 +98,6 @@
 	struct __priv_data priv_data;
 	void *user_data[0];
 };
-
-#if defined(AST_DEVMODE)
-#define AO2_DEVMODE_STAT(stat)	stat
-#else
-#define AO2_DEVMODE_STAT(stat)
-#endif	/* defined(AST_DEVMODE) */
-
-#ifdef AO2_DEBUG
-struct ao2_stats {
-	volatile int total_objects;
-	volatile int total_mem;
-	volatile int total_containers;
-	volatile int total_refs;
-	volatile int total_locked;
-};
-
-static struct ao2_stats ao2;
-#endif
-
-#ifdef HAVE_BKTR
-#include <execinfo.h>    /* for backtrace */
-#endif
-
-void ao2_bt(void)
-{
-#ifdef HAVE_BKTR
-	int depth;
-	int idx;
-#define N1	20
-	void *addresses[N1];
-	char **strings;
-
-	depth = backtrace(addresses, N1);
-	strings = ast_bt_get_symbols(addresses, depth);
-	ast_verbose("backtrace returned: %d\n", depth);
-	for (idx = 0; idx < depth; ++idx) {
-		ast_verbose("%d: %p %s\n", idx, addresses[idx], strings[idx]);
-	}
-	ast_std_free(strings);
-#endif
-}
-
-#define INTERNAL_OBJ_MUTEX(user_data) \
-	((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
-
-#define INTERNAL_OBJ_RWLOCK(user_data) \
-	((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
-
-#define INTERNAL_OBJ_MEMORY_POOL(user_data) \
-	(struct ao2_memory_pool_item *) (((char *) (user_data)) - sizeof(struct ao2_memory_pool_item))
-
-/*!
- * \brief convert from a pointer _p to a user-defined object
- *
- * \return the pointer to the astobj2 structure
- */
-static inline struct astobj2 *INTERNAL_OBJ(void *user_data)
-{
-	struct astobj2 *p;
-
-	if (!user_data) {
-		ast_log(LOG_ERROR, "user_data is NULL\n");
-		return NULL;
-	}
-
-	p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
-	if (AO2_MAGIC != p->priv_data.magic) {
-		if (p->priv_data.magic) {
-			ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
-				p->priv_data.magic, user_data);
-		} else {
-			ast_log(LOG_ERROR,
-				"bad magic number for object %p. Object is likely destroyed.\n",
-				user_data);
-		}
-		return NULL;
-	}
-
-	return p;
-}
-
-/*!
- * \brief convert from a pointer _p to an astobj2 object
- *
- * \return the pointer to the user-defined portion.
- */
-#define EXTERNAL_OBJ(_p)	((_p) == NULL ? NULL : (_p)->user_data)
-
-int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
-{
-	struct astobj2 *obj = INTERNAL_OBJ(user_data);
-	struct astobj2_lock *obj_mutex;
-	struct astobj2_rwlock *obj_rwlock;
-	int res = 0;
-
-	if (obj == NULL) {
-		ast_assert(0);
-		return -1;
-	}
-
-	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
-	case AO2_ALLOC_OPT_LOCK_MUTEX:
-		obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
-		res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
-#ifdef AO2_DEBUG
-		if (!res) {
-			ast_atomic_fetchadd_int(&ao2.total_locked, 1);
-		}
-#endif
-		break;
-	case AO2_ALLOC_OPT_LOCK_RWLOCK:
-		obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
-		switch (lock_how) {
-		case AO2_LOCK_REQ_MUTEX:
-		case AO2_LOCK_REQ_WRLOCK:
-			res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
-			if (!res) {
-				ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
-#ifdef AO2_DEBUG
-				ast_atomic_fetchadd_int(&ao2.total_locked, 1);
-#endif
-			}
-			break;
-		case AO2_LOCK_REQ_RDLOCK:
-			res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
-			if (!res) {
-				ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
-#ifdef AO2_DEBUG
-				ast_atomic_fetchadd_int(&ao2.total_locked, 1);
-#endif
-			}
-			break;
-		}
-		break;
-	case AO2_ALLOC_OPT_LOCK_NOLOCK:
-		/* The ao2 object has no lock. */
-		break;
-	default:
-		ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
-			user_data);
-		return -1;
-	}
-
-	return res;
-}
-
-int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
-{
-	struct astobj2 *obj = INTERNAL_OBJ(user_data);
-	struct astobj2_lock *obj_mutex;
-	struct astobj2_rwlock *obj_rwlock;
-	int res = 0;
-	int current_value;
-
-	if (obj == NULL) {
-		ast_assert(0);
-		return -1;
-	}
-
-	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
-	case AO2_ALLOC_OPT_LOCK_MUTEX:
-		obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
-		res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
-#ifdef AO2_DEBUG
-		if (!res) {
-			ast_atomic_fetchadd_int(&ao2.total_locked, -1);
-		}
-#endif
-		break;
-	case AO2_ALLOC_OPT_LOCK_RWLOCK:
-		obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
-
-		current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
-		if (current_value < 0) {
-			/* It was a WRLOCK that we are unlocking.  Fix the count. */
-			ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
-		}
-		res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
-#ifdef AO2_DEBUG
-		if (!res) {
-			ast_atomic_fetchadd_int(&ao2.total_locked, -1);
-		}
-#endif
-		break;
-	case AO2_ALLOC_OPT_LOCK_NOLOCK:
-		/* The ao2 object has no lock. */
-		break;
-	default:
-		ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
-			user_data);
-		res = -1;
-		break;
-	}
-	return res;
-}
-
-int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
-{
-	struct astobj2 *obj = INTERNAL_OBJ(user_data);
-	struct astobj2_lock *obj_mutex;
-	struct astobj2_rwlock *obj_rwlock;
-	int res = 0;
-
-	if (obj == NULL) {
-		ast_assert(0);
-		return -1;
-	}
-
-	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
-	case AO2_ALLOC_OPT_LOCK_MUTEX:
-		obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
-		res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
-#ifdef AO2_DEBUG
-		if (!res) {
-			ast_atomic_fetchadd_int(&ao2.total_locked, 1);
-		}
-#endif
-		break;
-	case AO2_ALLOC_OPT_LOCK_RWLOCK:
-		obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
-		switch (lock_how) {
-		case AO2_LOCK_REQ_MUTEX:
-		case AO2_LOCK_REQ_WRLOCK:
-			res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
-			if (!res) {
-				ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
-#ifdef AO2_DEBUG
-				ast_atomic_fetchadd_int(&ao2.total_locked, 1);
-#endif
-			}
-			break;
-		case AO2_LOCK_REQ_RDLOCK:
-			res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
-			if (!res) {
-				ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
-#ifdef AO2_DEBUG
-				ast_atomic_fetchadd_int(&ao2.total_locked, 1);
-#endif
-			}
-			break;
-		}
-		break;
-	case AO2_ALLOC_OPT_LOCK_NOLOCK:
-		/* The ao2 object has no lock. */
-		return 0;
-	default:
-		ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
-			user_data);
-		return -1;
-	}
-
-
-	return res;
-}
-
-/*!
- * \internal
- * \brief Adjust an object's lock to the requested level.
- *
- * \param user_data An ao2 object to adjust lock level.
- * \param lock_how What level to adjust lock.
- * \param keep_stronger TRUE if keep original lock level if it is stronger.
- *
- * \pre The ao2 object is already locked.
- *
- * \details
- * An ao2 object with a RWLOCK will have its lock level adjusted
- * to the specified level if it is not already there.  An ao2
- * object with a different type of lock is not affected.
- *
- * \return Original lock level.
- */
-static enum ao2_lock_req adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
-{
-	struct astobj2 *obj = INTERNAL_OBJ(user_data);
-	struct astobj2_rwlock *obj_rwlock;
-	enum ao2_lock_req orig_lock;
-
-	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
-	case AO2_ALLOC_OPT_LOCK_RWLOCK:
-		obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
-		if (obj_rwlock->rwlock.num_lockers < 0) {
-			orig_lock = AO2_LOCK_REQ_WRLOCK;
-		} else {
-			orig_lock = AO2_LOCK_REQ_RDLOCK;
-		}
-		switch (lock_how) {
-		case AO2_LOCK_REQ_MUTEX:
-			lock_how = AO2_LOCK_REQ_WRLOCK;
-			/* Fall through */
-		case AO2_LOCK_REQ_WRLOCK:
-			if (lock_how != orig_lock) {
-				/* Switch from read lock to write lock. */
-				ao2_unlock(user_data);
-				ao2_wrlock(user_data);
-			}
-			break;
-		case AO2_LOCK_REQ_RDLOCK:
-			if (!keep_stronger && lock_how != orig_lock) {
-				/* Switch from write lock to read lock. */
-				ao2_unlock(user_data);
-				ao2_rdlock(user_data);
-			}
-			break;
-		}
-		break;
-	default:
-		ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
-		/* Fall through */
-	case AO2_ALLOC_OPT_LOCK_NOLOCK:
-	case AO2_ALLOC_OPT_LOCK_MUTEX:
-		orig_lock = AO2_LOCK_REQ_MUTEX;
-		break;
-	}
-
-	return orig_lock;
-}
-
-void *ao2_object_get_lockaddr(void *user_data)
-{
-	struct astobj2 *obj = INTERNAL_OBJ(user_data);
-	struct astobj2_lock *obj_mutex;
-
-	if (obj == NULL) {
-		ast_assert(0);
-		return NULL;
-	}
-
-	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
-	case AO2_ALLOC_OPT_LOCK_MUTEX:
-		obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
-		return &obj_mutex->mutex.lock;
-	default:
-		break;
-	}
-
-	return NULL;
-}
 
 /*! \brief An item in a memory pool */
 struct ao2_memory_pool_item {
@@ -477,6 +139,365 @@
 	struct ao2_memory_pool_item *items[0];
 };
 
+#if defined(AST_DEVMODE)
+#define AO2_DEVMODE_STAT(stat)	stat
+#else
+#define AO2_DEVMODE_STAT(stat)
+#endif	/* defined(AST_DEVMODE) */
+
+#ifdef AO2_DEBUG
+struct ao2_stats {
+	volatile int total_objects;
+	volatile int total_mem;
+	volatile int total_containers;
+	volatile int total_refs;
+	volatile int total_locked;
+};
+
+static struct ao2_stats ao2;
+#endif
+
+#ifdef HAVE_BKTR
+#include <execinfo.h>    /* for backtrace */
+#endif
+
+void ao2_bt(void)
+{
+#ifdef HAVE_BKTR
+	int depth;
+	int idx;
+#define N1	20
+	void *addresses[N1];
+	char **strings;
+
+	depth = backtrace(addresses, N1);
+	strings = ast_bt_get_symbols(addresses, depth);
+	ast_verbose("backtrace returned: %d\n", depth);
+	for (idx = 0; idx < depth; ++idx) {
+		ast_verbose("%d: %p %s\n", idx, addresses[idx], strings[idx]);
+	}
+	ast_std_free(strings);
+#endif
+}
+
+#define INTERNAL_OBJ_MUTEX(user_data) \
+	((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
+
+#define INTERNAL_OBJ_RWLOCK(user_data) \
+	((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
+
+static inline struct ao2_memory_pool_item *INTERNAL_OBJ_MEMORY_POOL(void *user_data)
+{
+	struct ao2_memory_pool_item *p;
+
+	if (!user_data) {
+		ast_log(AST_LOG_ERROR, "user_data is NULL\n");
+		ast_do_crash();
+		return NULL;
+	}
+	p = (struct ao2_memory_pool_item *) (((char *) (user_data)) - sizeof(struct ao2_memory_pool_item));
+	if (AO2_MAGIC != p->ao2_obj.priv_data.magic) {
+		if (!p->ao2_obj.priv_data.magic) {
+			ast_log(AST_LOG_ERROR, "Bad magic number for object %p; object is likely destroyed\n", user_data);
+		} else {
+			ast_log(AST_LOG_ERROR, "Bad magic number 0x%x for object %p\n",
+				p->ao2_obj.priv_data.magic, user_data);
+		}
+		ast_do_crash();
+		return NULL;
+	}
+
+	return p;
+}	
+
+/*!
+ * \brief convert from a pointer _p to a user-defined object
+ *
+ * \return the pointer to the astobj2 structure
+ */
+static inline struct astobj2 *INTERNAL_OBJ(void *user_data)
+{
+	struct astobj2 *p;
+
+	if (!user_data) {
+		ast_log(LOG_ERROR, "user_data is NULL\n");
+		return NULL;
+	}
+
+	p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
+	if (AO2_MAGIC != p->priv_data.magic) {
+		if (p->priv_data.magic) {
+			ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
+				p->priv_data.magic, user_data);
+		} else {
+			ast_log(LOG_ERROR,
+				"bad magic number for object %p. Object is likely destroyed.\n",
+				user_data);
+		}
+		return NULL;
+	}
+
+	return p;
+}
+
+/*!
+ * \brief convert from a pointer _p to an astobj2 object
+ *
+ * \return the pointer to the user-defined portion.
+ */
+#define EXTERNAL_OBJ(_p)	((_p) == NULL ? NULL : (_p)->user_data)
+
+int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
+{
+	struct astobj2 *obj = INTERNAL_OBJ(user_data);
+	struct astobj2_lock *obj_mutex;
+	struct astobj2_rwlock *obj_rwlock;
+	int res = 0;
+
+	if (obj == NULL) {
+		ast_assert(0);
+		return -1;
+	}
+
+	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
+	case AO2_ALLOC_OPT_LOCK_MUTEX:
+		obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
+		res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
+#ifdef AO2_DEBUG
+		if (!res) {
+			ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+		}
+#endif
+		break;
+	case AO2_ALLOC_OPT_LOCK_RWLOCK:
+		obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
+		switch (lock_how) {
+		case AO2_LOCK_REQ_MUTEX:
+		case AO2_LOCK_REQ_WRLOCK:
+			res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
+			if (!res) {
+				ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
+#ifdef AO2_DEBUG
+				ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+#endif
+			}
+			break;
+		case AO2_LOCK_REQ_RDLOCK:
+			res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
+			if (!res) {
+				ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
+#ifdef AO2_DEBUG
+				ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+#endif
+			}
+			break;
+		}
+		break;
+	case AO2_ALLOC_OPT_LOCK_NOLOCK:
+		/* The ao2 object has no lock. */
+		break;
+	default:
+		ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
+			user_data);
+		return -1;
+	}
+
+	return res;
+}
+
+int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
+{
+	struct astobj2 *obj = INTERNAL_OBJ(user_data);
+	struct astobj2_lock *obj_mutex;
+	struct astobj2_rwlock *obj_rwlock;
+	int res = 0;
+	int current_value;
+
+	if (obj == NULL) {
+		ast_assert(0);
+		return -1;
+	}
+
+	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
+	case AO2_ALLOC_OPT_LOCK_MUTEX:
+		obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
+		res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
+#ifdef AO2_DEBUG
+		if (!res) {
+			ast_atomic_fetchadd_int(&ao2.total_locked, -1);
+		}
+#endif
+		break;
+	case AO2_ALLOC_OPT_LOCK_RWLOCK:
+		obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
+
+		current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
+		if (current_value < 0) {
+			/* It was a WRLOCK that we are unlocking.  Fix the count. */
+			ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
+		}
+		res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
+#ifdef AO2_DEBUG
+		if (!res) {
+			ast_atomic_fetchadd_int(&ao2.total_locked, -1);
+		}
+#endif
+		break;
+	case AO2_ALLOC_OPT_LOCK_NOLOCK:
+		/* The ao2 object has no lock. */
+		break;
+	default:
+		ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
+			user_data);
+		res = -1;
+		break;
+	}
+	return res;
+}
+
+int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
+{
+	struct astobj2 *obj = INTERNAL_OBJ(user_data);
+	struct astobj2_lock *obj_mutex;
+	struct astobj2_rwlock *obj_rwlock;
+	int res = 0;
+
+	if (obj == NULL) {
+		ast_assert(0);
+		return -1;
+	}
+
+	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
+	case AO2_ALLOC_OPT_LOCK_MUTEX:
+		obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
+		res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
+#ifdef AO2_DEBUG
+		if (!res) {
+			ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+		}
+#endif
+		break;
+	case AO2_ALLOC_OPT_LOCK_RWLOCK:
+		obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
+		switch (lock_how) {
+		case AO2_LOCK_REQ_MUTEX:
+		case AO2_LOCK_REQ_WRLOCK:
+			res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
+			if (!res) {
+				ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
+#ifdef AO2_DEBUG
+				ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+#endif
+			}
+			break;
+		case AO2_LOCK_REQ_RDLOCK:
+			res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
+			if (!res) {
+				ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
+#ifdef AO2_DEBUG
+				ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+#endif
+			}
+			break;
+		}
+		break;
+	case AO2_ALLOC_OPT_LOCK_NOLOCK:
+		/* The ao2 object has no lock. */
+		return 0;
+	default:
+		ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
+			user_data);
+		return -1;
+	}
+
+
+	return res;
+}
+
+/*!
+ * \internal
+ * \brief Adjust an object's lock to the requested level.
+ *
+ * \param user_data An ao2 object to adjust lock level.
+ * \param lock_how What level to adjust lock.
+ * \param keep_stronger TRUE if keep original lock level if it is stronger.
+ *
+ * \pre The ao2 object is already locked.
+ *
+ * \details
+ * An ao2 object with a RWLOCK will have its lock level adjusted
+ * to the specified level if it is not already there.  An ao2
+ * object with a different type of lock is not affected.
+ *
+ * \return Original lock level.
+ */
+static enum ao2_lock_req adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
+{
+	struct astobj2 *obj = INTERNAL_OBJ(user_data);
+	struct astobj2_rwlock *obj_rwlock;
+	enum ao2_lock_req orig_lock;
+
+	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
+	case AO2_ALLOC_OPT_LOCK_RWLOCK:
+		obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
+		if (obj_rwlock->rwlock.num_lockers < 0) {
+			orig_lock = AO2_LOCK_REQ_WRLOCK;
+		} else {
+			orig_lock = AO2_LOCK_REQ_RDLOCK;
+		}
+		switch (lock_how) {
+		case AO2_LOCK_REQ_MUTEX:
+			lock_how = AO2_LOCK_REQ_WRLOCK;
+			/* Fall through */
+		case AO2_LOCK_REQ_WRLOCK:
+			if (lock_how != orig_lock) {
+				/* Switch from read lock to write lock. */
+				ao2_unlock(user_data);
+				ao2_wrlock(user_data);
+			}
+			break;
+		case AO2_LOCK_REQ_RDLOCK:
+			if (!keep_stronger && lock_how != orig_lock) {
+				/* Switch from write lock to read lock. */
+				ao2_unlock(user_data);
+				ao2_rdlock(user_data);
+			}
+			break;
+		}
+		break;
+	default:
+		ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
+		/* Fall through */
+	case AO2_ALLOC_OPT_LOCK_NOLOCK:
+	case AO2_ALLOC_OPT_LOCK_MUTEX:
+		orig_lock = AO2_LOCK_REQ_MUTEX;
+		break;
+	}
+
+	return orig_lock;
+}
+
+void *ao2_object_get_lockaddr(void *user_data)
+{
+	struct astobj2 *obj = INTERNAL_OBJ(user_data);
+	struct astobj2_lock *obj_mutex;
+
+	if (obj == NULL) {
+		ast_assert(0);
+		return NULL;
+	}
+
+	switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
+	case AO2_ALLOC_OPT_LOCK_MUTEX:
+		obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
+		return &obj_mutex->mutex.lock;
+	default:
+		break;
+	}
+
+	return NULL;
+}
+
 static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *func)
 {
 	struct astobj2 *obj = INTERNAL_OBJ(user_data);
@@ -721,8 +742,38 @@
 }
 
 /*! \brief Compute where in a memory pool an item exists, based on its index */
-#define MEMORY_POOL_ITEM(pool, index) \
-	((struct ao2_memory_pool_item *)((char *)((pool)->items) + (index) * ((pool)->obj_size + sizeof(struct ao2_memory_pool_item))))
+static inline struct ao2_memory_pool_item *MEMORY_POOL_ITEM(struct ao2_memory_pool *pool, size_t index)
+{
+	struct ao2_memory_pool_item *item;
+
+	if (!pool) {
+		ast_log(AST_LOG_ERROR, "memory pool is NULL\n");
+		ast_do_crash();
+		return NULL;		
+	}
+	item = ((struct ao2_memory_pool_item *)((char *)((pool)->items) + (index) * ((pool)->obj_size + sizeof(struct ao2_memory_pool_item))));
+	if (!item) {
+		ast_log(AST_LOG_ERROR, "item in pool %p is NULL\n", pool);
+		ast_do_crash();
+		return NULL;
+	}
+	/* If pool is not yet set, we haven't been initialized. Pass on the magic
+	 * checks in that one case.
+	 */
+	if (item->pool && AO2_MAGIC != item->ao2_obj.priv_data.magic) {
+		if (!item->ao2_obj.priv_data.magic) {
+			ast_log(AST_LOG_ERROR, "Bad magic number for object %p in pool %p; object is likely destroyed\n", item, pool);
+		} else {
+			ast_log(AST_LOG_ERROR, "Bad magic number 0x%x for object %p in pool %p\n",
+				item->ao2_obj.priv_data.magic, item, pool);
+		}
+		ast_do_crash();
+		return NULL;
+	}
+
+	return item;
+}
+
 
 /*!
  * \brief Destructor for a memory pool




More information about the asterisk-commits mailing list