* #36737: switch back to svn repo, remove assert in sip_transaction.c
diff --git a/jni/pjproject-android/.svn/pristine/e3/e3718ecd95ea7d21895fc82f20b1558b4e4ec8f6.svn-base b/jni/pjproject-android/.svn/pristine/e3/e3718ecd95ea7d21895fc82f20b1558b4e4ec8f6.svn-base
new file mode 100644
index 0000000..d7f4ffa
--- /dev/null
+++ b/jni/pjproject-android/.svn/pristine/e3/e3718ecd95ea7d21895fc82f20b1558b4e4ec8f6.svn-base
@@ -0,0 +1,715 @@
+/* $Id$ */
+/*
+ * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
+ * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <pj/lock.h>
+#include <pj/os.h>
+#include <pj/assert.h>
+#include <pj/log.h>
+#include <pj/pool.h>
+#include <pj/string.h>
+#include <pj/errno.h>
+
+#define THIS_FILE "lock.c"
+
+typedef void LOCK_OBJ;
+
+/*
+ * Lock structure.
+ */
+struct pj_lock_t
+{
+ LOCK_OBJ *lock_object;
+
+ pj_status_t (*acquire) (LOCK_OBJ*);
+ pj_status_t (*tryacquire) (LOCK_OBJ*);
+ pj_status_t (*release) (LOCK_OBJ*);
+ pj_status_t (*destroy) (LOCK_OBJ*);
+};
+
+typedef pj_status_t (*FPTR)(LOCK_OBJ*);
+
+/******************************************************************************
+ * Implementation of lock object with mutex.
+ */
+static pj_lock_t mutex_lock_template =
+{
+ NULL,
+ (FPTR) &pj_mutex_lock,
+ (FPTR) &pj_mutex_trylock,
+ (FPTR) &pj_mutex_unlock,
+ (FPTR) &pj_mutex_destroy
+};
+
+static pj_status_t create_mutex_lock( pj_pool_t *pool,
+ const char *name,
+ int type,
+ pj_lock_t **lock )
+{
+ pj_lock_t *p_lock;
+ pj_mutex_t *mutex;
+ pj_status_t rc;
+
+ PJ_ASSERT_RETURN(pool && lock, PJ_EINVAL);
+
+ p_lock = PJ_POOL_ALLOC_T(pool, pj_lock_t);
+ if (!p_lock)
+ return PJ_ENOMEM;
+
+ pj_memcpy(p_lock, &mutex_lock_template, sizeof(pj_lock_t));
+ rc = pj_mutex_create(pool, name, type, &mutex);
+ if (rc != PJ_SUCCESS)
+ return rc;
+
+ p_lock->lock_object = mutex;
+ *lock = p_lock;
+ return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pj_lock_create_simple_mutex( pj_pool_t *pool,
+ const char *name,
+ pj_lock_t **lock )
+{
+ return create_mutex_lock(pool, name, PJ_MUTEX_SIMPLE, lock);
+}
+
+PJ_DEF(pj_status_t) pj_lock_create_recursive_mutex( pj_pool_t *pool,
+ const char *name,
+ pj_lock_t **lock )
+{
+ return create_mutex_lock(pool, name, PJ_MUTEX_RECURSE, lock);
+}
+
+
+/******************************************************************************
+ * Implementation of NULL lock object.
+ */
+static pj_status_t null_op(void *arg)
+{
+ PJ_UNUSED_ARG(arg);
+ return PJ_SUCCESS;
+}
+
+static pj_lock_t null_lock_template =
+{
+ NULL,
+ &null_op,
+ &null_op,
+ &null_op,
+ &null_op
+};
+
+PJ_DEF(pj_status_t) pj_lock_create_null_mutex( pj_pool_t *pool,
+ const char *name,
+ pj_lock_t **lock )
+{
+ PJ_UNUSED_ARG(name);
+ PJ_UNUSED_ARG(pool);
+
+ PJ_ASSERT_RETURN(lock, PJ_EINVAL);
+
+ *lock = &null_lock_template;
+ return PJ_SUCCESS;
+}
+
+
+/******************************************************************************
+ * Implementation of semaphore lock object.
+ */
+#if defined(PJ_HAS_SEMAPHORE) && PJ_HAS_SEMAPHORE != 0
+
+static pj_lock_t sem_lock_template =
+{
+ NULL,
+ (FPTR) &pj_sem_wait,
+ (FPTR) &pj_sem_trywait,
+ (FPTR) &pj_sem_post,
+ (FPTR) &pj_sem_destroy
+};
+
+PJ_DEF(pj_status_t) pj_lock_create_semaphore( pj_pool_t *pool,
+ const char *name,
+ unsigned initial,
+ unsigned max,
+ pj_lock_t **lock )
+{
+ pj_lock_t *p_lock;
+ pj_sem_t *sem;
+ pj_status_t rc;
+
+ PJ_ASSERT_RETURN(pool && lock, PJ_EINVAL);
+
+ p_lock = PJ_POOL_ALLOC_T(pool, pj_lock_t);
+ if (!p_lock)
+ return PJ_ENOMEM;
+
+ pj_memcpy(p_lock, &sem_lock_template, sizeof(pj_lock_t));
+ rc = pj_sem_create( pool, name, initial, max, &sem);
+ if (rc != PJ_SUCCESS)
+ return rc;
+
+ p_lock->lock_object = sem;
+ *lock = p_lock;
+
+ return PJ_SUCCESS;
+}
+
+
+#endif /* PJ_HAS_SEMAPHORE */
+
+
+PJ_DEF(pj_status_t) pj_lock_acquire( pj_lock_t *lock )
+{
+ PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
+ return (*lock->acquire)(lock->lock_object);
+}
+
+PJ_DEF(pj_status_t) pj_lock_tryacquire( pj_lock_t *lock )
+{
+ PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
+ return (*lock->tryacquire)(lock->lock_object);
+}
+
+PJ_DEF(pj_status_t) pj_lock_release( pj_lock_t *lock )
+{
+ PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
+ return (*lock->release)(lock->lock_object);
+}
+
+PJ_DEF(pj_status_t) pj_lock_destroy( pj_lock_t *lock )
+{
+ PJ_ASSERT_RETURN(lock != NULL, PJ_EINVAL);
+ return (*lock->destroy)(lock->lock_object);
+}
+
+
+/******************************************************************************
+ * Group lock
+ */
+
+/* Individual lock in the group lock */
+typedef struct grp_lock_item
+{
+ PJ_DECL_LIST_MEMBER(struct grp_lock_item);
+ int prio;
+ pj_lock_t *lock;
+
+} grp_lock_item;
+
+/* Destroy callbacks */
+typedef struct grp_destroy_callback
+{
+ PJ_DECL_LIST_MEMBER(struct grp_destroy_callback);
+ void *comp;
+ void (*handler)(void*);
+} grp_destroy_callback;
+
+#if PJ_GRP_LOCK_DEBUG
+/* Store each add_ref caller */
+typedef struct grp_lock_ref
+{
+ PJ_DECL_LIST_MEMBER(struct grp_lock_ref);
+ const char *file;
+ int line;
+} grp_lock_ref;
+#endif
+
+/* The group lock */
+struct pj_grp_lock_t
+{
+ pj_lock_t base;
+
+ pj_pool_t *pool;
+ pj_atomic_t *ref_cnt;
+ pj_lock_t *own_lock;
+
+ pj_thread_t *owner;
+ int owner_cnt;
+
+ grp_lock_item lock_list;
+ grp_destroy_callback destroy_list;
+
+#if PJ_GRP_LOCK_DEBUG
+ grp_lock_ref ref_list;
+ grp_lock_ref ref_free_list;
+#endif
+};
+
+
+PJ_DEF(void) pj_grp_lock_config_default(pj_grp_lock_config *cfg)
+{
+ pj_bzero(cfg, sizeof(*cfg));
+}
+
+static void grp_lock_set_owner_thread(pj_grp_lock_t *glock)
+{
+ if (!glock->owner) {
+ glock->owner = pj_thread_this();
+ glock->owner_cnt = 1;
+ } else {
+ pj_assert(glock->owner == pj_thread_this());
+ glock->owner_cnt++;
+ }
+}
+
+static void grp_lock_unset_owner_thread(pj_grp_lock_t *glock)
+{
+ pj_assert(glock->owner == pj_thread_this());
+ pj_assert(glock->owner_cnt > 0);
+ if (--glock->owner_cnt <= 0) {
+ glock->owner = NULL;
+ glock->owner_cnt = 0;
+ }
+}
+
+static pj_status_t grp_lock_acquire(LOCK_OBJ *p)
+{
+ pj_grp_lock_t *glock = (pj_grp_lock_t*)p;
+ grp_lock_item *lck;
+
+ pj_assert(pj_atomic_get(glock->ref_cnt) > 0);
+
+ lck = glock->lock_list.next;
+ while (lck != &glock->lock_list) {
+ pj_lock_acquire(lck->lock);
+ lck = lck->next;
+ }
+ grp_lock_set_owner_thread(glock);
+ pj_grp_lock_add_ref(glock);
+ return PJ_SUCCESS;
+}
+
+static pj_status_t grp_lock_tryacquire(LOCK_OBJ *p)
+{
+ pj_grp_lock_t *glock = (pj_grp_lock_t*)p;
+ grp_lock_item *lck;
+
+ pj_assert(pj_atomic_get(glock->ref_cnt) > 0);
+
+ lck = glock->lock_list.next;
+ while (lck != &glock->lock_list) {
+ pj_status_t status = pj_lock_tryacquire(lck->lock);
+ if (status != PJ_SUCCESS) {
+ lck = lck->prev;
+ while (lck != &glock->lock_list) {
+ pj_lock_release(lck->lock);
+ lck = lck->prev;
+ }
+ return status;
+ }
+ lck = lck->next;
+ }
+ grp_lock_set_owner_thread(glock);
+ pj_grp_lock_add_ref(glock);
+ return PJ_SUCCESS;
+}
+
+static pj_status_t grp_lock_release(LOCK_OBJ *p)
+{
+ pj_grp_lock_t *glock = (pj_grp_lock_t*)p;
+ grp_lock_item *lck;
+
+ grp_lock_unset_owner_thread(glock);
+
+ lck = glock->lock_list.prev;
+ while (lck != &glock->lock_list) {
+ pj_lock_release(lck->lock);
+ lck = lck->prev;
+ }
+ return pj_grp_lock_dec_ref(glock);
+}
+
+static pj_status_t grp_lock_destroy(LOCK_OBJ *p)
+{
+ pj_grp_lock_t *glock = (pj_grp_lock_t*)p;
+ pj_pool_t *pool = glock->pool;
+ grp_lock_item *lck;
+ grp_destroy_callback *cb;
+
+ if (!glock->pool) {
+ /* already destroyed?! */
+ return PJ_EINVAL;
+ }
+
+ /* Release all chained locks */
+ lck = glock->lock_list.next;
+ while (lck != &glock->lock_list) {
+ if (lck->lock != glock->own_lock) {
+ int i;
+ for (i=0; i<glock->owner_cnt; ++i)
+ pj_lock_release(lck->lock);
+ }
+ lck = lck->next;
+ }
+
+ /* Call callbacks */
+ cb = glock->destroy_list.next;
+ while (cb != &glock->destroy_list) {
+ grp_destroy_callback *next = cb->next;
+ cb->handler(cb->comp);
+ cb = next;
+ }
+
+ pj_lock_destroy(glock->own_lock);
+ pj_atomic_destroy(glock->ref_cnt);
+ glock->pool = NULL;
+ pj_pool_release(pool);
+
+ return PJ_SUCCESS;
+}
+
+
+PJ_DEF(pj_status_t) pj_grp_lock_create( pj_pool_t *pool,
+ const pj_grp_lock_config *cfg,
+ pj_grp_lock_t **p_grp_lock)
+{
+ pj_grp_lock_t *glock;
+ grp_lock_item *own_lock;
+ pj_status_t status;
+
+ PJ_ASSERT_RETURN(pool && p_grp_lock, PJ_EINVAL);
+
+ PJ_UNUSED_ARG(cfg);
+
+ pool = pj_pool_create(pool->factory, "glck%p", 512, 512, NULL);
+ if (!pool)
+ return PJ_ENOMEM;
+
+ glock = PJ_POOL_ZALLOC_T(pool, pj_grp_lock_t);
+ glock->base.lock_object = glock;
+ glock->base.acquire = &grp_lock_acquire;
+ glock->base.tryacquire = &grp_lock_tryacquire;
+ glock->base.release = &grp_lock_release;
+ glock->base.destroy = &grp_lock_destroy;
+
+ glock->pool = pool;
+ pj_list_init(&glock->lock_list);
+ pj_list_init(&glock->destroy_list);
+#if PJ_GRP_LOCK_DEBUG
+ pj_list_init(&glock->ref_list);
+ pj_list_init(&glock->ref_free_list);
+#endif
+
+ status = pj_atomic_create(pool, 0, &glock->ref_cnt);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ status = pj_lock_create_recursive_mutex(pool, pool->obj_name,
+ &glock->own_lock);
+ if (status != PJ_SUCCESS)
+ goto on_error;
+
+ own_lock = PJ_POOL_ZALLOC_T(pool, grp_lock_item);
+ own_lock->lock = glock->own_lock;
+ pj_list_push_back(&glock->lock_list, own_lock);
+
+ *p_grp_lock = glock;
+ return PJ_SUCCESS;
+
+on_error:
+ grp_lock_destroy(glock);
+ return status;
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_destroy( pj_grp_lock_t *grp_lock)
+{
+ return grp_lock_destroy(grp_lock);
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_acquire( pj_grp_lock_t *grp_lock)
+{
+ return grp_lock_acquire(grp_lock);
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_tryacquire( pj_grp_lock_t *grp_lock)
+{
+ return grp_lock_tryacquire(grp_lock);
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_release( pj_grp_lock_t *grp_lock)
+{
+ return grp_lock_release(grp_lock);
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_replace( pj_grp_lock_t *old_lock,
+ pj_grp_lock_t *new_lock)
+{
+ grp_destroy_callback *ocb;
+
+ /* Move handlers from old to new */
+ ocb = old_lock->destroy_list.next;
+ while (ocb != &old_lock->destroy_list) {
+ grp_destroy_callback *ncb;
+
+ ncb = PJ_POOL_ALLOC_T(new_lock->pool, grp_destroy_callback);
+ ncb->comp = ocb->comp;
+ ncb->handler = ocb->handler;
+ pj_list_push_back(&new_lock->destroy_list, ncb);
+
+ ocb = ocb->next;
+ }
+
+ pj_list_init(&old_lock->destroy_list);
+
+ grp_lock_destroy(old_lock);
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_add_handler( pj_grp_lock_t *glock,
+ pj_pool_t *pool,
+ void *comp,
+ void (*destroy)(void *comp))
+{
+ grp_destroy_callback *cb;
+
+ grp_lock_acquire(glock);
+
+ if (pool == NULL)
+ pool = glock->pool;
+
+ cb = PJ_POOL_ZALLOC_T(pool, grp_destroy_callback);
+ cb->comp = comp;
+ cb->handler = destroy;
+ pj_list_push_back(&glock->destroy_list, cb);
+
+ grp_lock_release(glock);
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_del_handler( pj_grp_lock_t *glock,
+ void *comp,
+ void (*destroy)(void *comp))
+{
+ grp_destroy_callback *cb;
+
+ grp_lock_acquire(glock);
+
+ cb = glock->destroy_list.next;
+ while (cb != &glock->destroy_list) {
+ if (cb->comp == comp && cb->handler == destroy)
+ break;
+ cb = cb->next;
+ }
+
+ if (cb != &glock->destroy_list)
+ pj_list_erase(cb);
+
+ grp_lock_release(glock);
+ return PJ_SUCCESS;
+}
+
+static pj_status_t grp_lock_add_ref(pj_grp_lock_t *glock)
+{
+ pj_atomic_inc(glock->ref_cnt);
+ return PJ_SUCCESS;
+}
+
+static pj_status_t grp_lock_dec_ref(pj_grp_lock_t *glock)
+{
+ int cnt; /* for debugging */
+ if ((cnt=pj_atomic_dec_and_get(glock->ref_cnt)) == 0) {
+ grp_lock_destroy(glock);
+ return PJ_EGONE;
+ }
+ pj_assert(cnt > 0);
+ pj_grp_lock_dump(glock);
+ return PJ_SUCCESS;
+}
+
+#if PJ_GRP_LOCK_DEBUG
+PJ_DEF(pj_status_t) pj_grp_lock_add_ref_dbg(pj_grp_lock_t *glock,
+ const char *file,
+ int line)
+{
+ grp_lock_ref *ref;
+ pj_status_t status;
+
+ pj_enter_critical_section();
+ if (!pj_list_empty(&glock->ref_free_list)) {
+ ref = glock->ref_free_list.next;
+ pj_list_erase(ref);
+ } else {
+ ref = PJ_POOL_ALLOC_T(glock->pool, grp_lock_ref);
+ }
+
+ ref->file = file;
+ ref->line = line;
+ pj_list_push_back(&glock->ref_list, ref);
+
+ pj_leave_critical_section();
+
+ status = grp_lock_add_ref(glock);
+
+ if (status != PJ_SUCCESS) {
+ pj_enter_critical_section();
+ pj_list_erase(ref);
+ pj_list_push_back(&glock->ref_free_list, ref);
+ pj_leave_critical_section();
+ }
+
+ return status;
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_dec_ref_dbg(pj_grp_lock_t *glock,
+ const char *file,
+ int line)
+{
+ grp_lock_ref *ref;
+
+ pj_enter_critical_section();
+ /* Find the same source file */
+ ref = glock->ref_list.next;
+ while (ref != &glock->ref_list) {
+ if (strcmp(ref->file, file) == 0) {
+ pj_list_erase(ref);
+ pj_list_push_back(&glock->ref_free_list, ref);
+ break;
+ }
+ ref = ref->next;
+ }
+ pj_leave_critical_section();
+
+ if (ref == &glock->ref_list) {
+ PJ_LOG(2,(THIS_FILE, "pj_grp_lock_dec_ref_dbg() could not find "
+ "matching ref for %s", file));
+ }
+
+ return grp_lock_dec_ref(glock);
+}
+#else
+PJ_DEF(pj_status_t) pj_grp_lock_add_ref(pj_grp_lock_t *glock)
+{
+ return grp_lock_add_ref(glock);
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_dec_ref(pj_grp_lock_t *glock)
+{
+ return grp_lock_dec_ref(glock);
+}
+#endif
+
+PJ_DEF(int) pj_grp_lock_get_ref(pj_grp_lock_t *glock)
+{
+ return pj_atomic_get(glock->ref_cnt);
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_chain_lock( pj_grp_lock_t *glock,
+ pj_lock_t *lock,
+ int pos)
+{
+ grp_lock_item *lck, *new_lck;
+ int i;
+
+ grp_lock_acquire(glock);
+
+ for (i=0; i<glock->owner_cnt; ++i)
+ pj_lock_acquire(lock);
+
+ lck = glock->lock_list.next;
+ while (lck != &glock->lock_list) {
+ if (lck->prio >= pos)
+ break;
+ lck = lck->next;
+ }
+
+ new_lck = PJ_POOL_ZALLOC_T(glock->pool, grp_lock_item);
+ new_lck->prio = pos;
+ new_lck->lock = lock;
+ pj_list_insert_before(lck, new_lck);
+
+ /* this will also release the new lock */
+ grp_lock_release(glock);
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_grp_lock_unchain_lock( pj_grp_lock_t *glock,
+ pj_lock_t *lock)
+{
+ grp_lock_item *lck;
+
+ grp_lock_acquire(glock);
+
+ lck = glock->lock_list.next;
+ while (lck != &glock->lock_list) {
+ if (lck->lock == lock)
+ break;
+ lck = lck->next;
+ }
+
+ if (lck != &glock->lock_list) {
+ int i;
+
+ pj_list_erase(lck);
+ for (i=0; i<glock->owner_cnt; ++i)
+ pj_lock_release(lck->lock);
+ }
+
+ grp_lock_release(glock);
+ return PJ_SUCCESS;
+}
+
+PJ_DEF(void) pj_grp_lock_dump(pj_grp_lock_t *grp_lock)
+{
+#if PJ_GRP_LOCK_DEBUG
+ grp_lock_ref *ref = grp_lock->ref_list.next;
+ char info_buf[1000];
+ pj_str_t info;
+
+ info.ptr = info_buf;
+ info.slen = 0;
+
+ pj_grp_lock_acquire(grp_lock);
+ pj_enter_critical_section();
+
+ while (ref != &grp_lock->ref_list && info.slen < sizeof(info_buf)) {
+ char *start = info.ptr + info.slen;
+ int max_len = sizeof(info_buf) - info.slen;
+ int len;
+
+ len = pj_ansi_snprintf(start, max_len, "%s:%d ", ref->file, ref->line);
+ if (len < 1 || len >= max_len) {
+ len = strlen(ref->file);
+ if (len > max_len - 1)
+ len = max_len - 1;
+
+ memcpy(start, ref->file, len);
+ start[len++] = ' ';
+ }
+
+ info.slen += len;
+
+ ref = ref->next;
+ }
+
+ if (ref != &grp_lock->ref_list) {
+ int i;
+ for (i=0; i<4; ++i)
+ info_buf[sizeof(info_buf)-i-1] = '.';
+ }
+ info.ptr[info.slen-1] = '\0';
+
+ pj_leave_critical_section();
+ pj_grp_lock_release(grp_lock);
+
+ PJ_LOG(4,(THIS_FILE, "Group lock %p, ref_cnt=%d. Reference holders: %s",
+ grp_lock, pj_grp_lock_get_ref(grp_lock), info.ptr));
+#else
+ PJ_UNUSED_ARG(grp_lock);
+#endif
+}