* #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
+}