[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