Index: pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 4208)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 4420)
@@ -28,4 +28,5 @@
 #include <pj/pool.h>
 #include <pj/os.h>
+#include <pj/rand.h>
 #include <pj/string.h>
 #include <pj/assert.h>
@@ -91,7 +92,4 @@
 };
 
-/* Thread Local Storage ID for transaction lock */
-static long pjsip_tsx_lock_tls_id;
-
 /* Transaction state names */
 static const char *state_str[] = 
@@ -123,12 +121,4 @@
     TSX_HAS_RESOLVED_SERVER	= 16,
 };
-
-/* Transaction lock. */
-typedef struct tsx_lock_data {
-    struct tsx_lock_data *prev;
-    pjsip_transaction    *tsx;
-    int			  is_alive;
-} tsx_lock_data;
-
 
 /* Timer timeout value constants */
@@ -149,7 +139,4 @@
 
 /* Prototypes. */
-static void	   lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck);
-static pj_status_t unlock_tsx( pjsip_transaction *tsx, 
-                               struct tsx_lock_data *lck);
 static pj_status_t tsx_on_state_null(		pjsip_transaction *tsx, 
 				                pjsip_event *event);
@@ -179,6 +166,8 @@
 				       const pjsip_transport_state_info *info);
 static pj_status_t tsx_create( pjsip_module *tsx_user,
+                               pj_grp_lock_t *grp_lock,
 			       pjsip_transaction **p_tsx);
-static pj_status_t tsx_destroy( pjsip_transaction *tsx );
+static void	   tsx_on_destroy(void *arg);
+static pj_status_t tsx_shutdown( pjsip_transaction *tsx );
 static void	   tsx_resched_retransmission( pjsip_transaction *tsx );
 static pj_status_t tsx_retransmit( pjsip_transaction *tsx, int resched);
@@ -271,8 +260,7 @@
 {
 #define SEPARATOR   '$'
-    char *key, *p, *end;
+    char *key, *p;
     int len;
     pj_size_t len_required;
-    pjsip_uri *req_uri;
     pj_str_t *host;
 
@@ -284,5 +272,4 @@
 
     host = &rdata->msg_info.via->sent_by.host;
-    req_uri = (pjsip_uri*)rdata->msg_info.msg->line.req.uri;
 
     /* Calculate length required. */
@@ -294,5 +281,4 @@
 		   16;			    /* Separator+Allowance. */
     key = p = (char*) pj_pool_alloc(pool, len_required);
-    end = p + len_required;
 
     /* Add role. */
@@ -452,11 +438,4 @@
     timeout_timer_val = td_timer_val;
 
-    /* Initialize TLS ID for transaction lock. */
-    status = pj_thread_local_alloc(&pjsip_tsx_lock_tls_id);
-    if (status != PJ_SUCCESS)
-	return status;
-
-    pj_thread_local_set(pjsip_tsx_lock_tls_id, NULL);
-
     /*
      * Initialize transaction layer structure.
@@ -483,5 +462,5 @@
     }
 
-    /* Create mutex. */
+    /* Create group lock. */
     status = pj_mutex_create_recursive(pool, "tsxlayer", &mod_tsx_layer.mutex);
     if (status != PJ_SUCCESS) {
@@ -666,6 +645,8 @@
      */
     PJ_TODO(FIX_RACE_CONDITION_HERE);
+    PJ_RACE_ME(5);
+
     if (tsx && lock)
-	pj_mutex_lock(tsx->mutex);
+	pj_grp_lock_acquire(tsx->grp_lock);
 
     return tsx;
@@ -712,5 +693,5 @@
 	    pjsip_tsx_terminate(tsx, PJSIP_SC_SERVICE_UNAVAILABLE);
 	    mod_tsx_layer_unregister_tsx(tsx);
-	    tsx_destroy(tsx);
+	    tsx_shutdown(tsx);
 	}
 	it = next;
@@ -735,7 +716,4 @@
     /* Release pool. */
     pjsip_endpt_release_pool(mod_tsx_layer.endpt, mod_tsx_layer.pool);
-
-    /* Free TLS */
-    pj_thread_local_free(pjsip_tsx_lock_tls_id);
 
     /* Mark as unregistered. */
@@ -814,4 +792,5 @@
      */
     PJ_TODO(FIX_RACE_CONDITION_HERE);
+    PJ_RACE_ME(5);
 
     /* Pass the message to the transaction. */
@@ -863,4 +842,5 @@
      */
     PJ_TODO(FIX_RACE_CONDITION_HERE);
+    PJ_RACE_ME(5);
 
     /* Pass the message to the transaction. */
@@ -929,41 +909,4 @@
  *****************************************************************************
  **/
-/*
- * Lock transaction and set the value of Thread Local Storage.
- */
-static void lock_tsx(pjsip_transaction *tsx, struct tsx_lock_data *lck)
-{
-    struct tsx_lock_data *prev_data;
-
-    pj_mutex_lock(tsx->mutex);
-    prev_data = (struct tsx_lock_data *) 
-                    pj_thread_local_get(pjsip_tsx_lock_tls_id);
-    lck->prev = prev_data;
-    lck->tsx = tsx;
-    lck->is_alive = 1;
-    pj_thread_local_set(pjsip_tsx_lock_tls_id, lck);
-}
-
-
-/*
- * Unlock transaction.
- * This will selectively unlock the mutex ONLY IF the transaction has not been 
- * destroyed. The function knows whether the transaction has been destroyed
- * because when transaction is destroyed the is_alive flag for the transaction
- * will be set to zero.
- */
-static pj_status_t unlock_tsx( pjsip_transaction *tsx, 
-                               struct tsx_lock_data *lck)
-{
-    pj_assert( (void*)pj_thread_local_get(pjsip_tsx_lock_tls_id) == lck);
-    pj_assert( lck->tsx == tsx );
-    pj_thread_local_set(pjsip_tsx_lock_tls_id, lck->prev);
-    if (lck->is_alive)
-	pj_mutex_unlock(tsx->mutex);
-
-    return lck->is_alive ? PJ_SUCCESS : PJSIP_ETSXDESTROYED;
-}
-
-
 /* Lock transaction for accessing the timeout timer only. */
 static void lock_timer(pjsip_transaction *tsx)
@@ -982,4 +925,5 @@
  */
 static pj_status_t tsx_create( pjsip_module *tsx_user,
+                               pj_grp_lock_t *grp_lock,
 			       pjsip_transaction **p_tsx)
 {
@@ -1010,14 +954,20 @@
     tsx->timeout_timer.cb = &tsx_timer_callback;
     
-    status = pj_mutex_create_recursive(pool, tsx->obj_name, &tsx->mutex);
-    if (status != PJ_SUCCESS) {
-	pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool);
-	return status;
-    }
+    if (grp_lock) {
+	tsx->grp_lock = grp_lock;
+    } else {
+	status = pj_grp_lock_create(pool, NULL, &tsx->grp_lock);
+	if (status != PJ_SUCCESS) {
+	    pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool);
+	    return status;
+	}
+    }
+
+    pj_grp_lock_add_ref(tsx->grp_lock);
+    pj_grp_lock_add_handler(tsx->grp_lock, tsx->pool, tsx, &tsx_on_destroy);
 
     status = pj_mutex_create_simple(pool, tsx->obj_name, &tsx->mutex_b);
     if (status != PJ_SUCCESS) {
-	pj_mutex_destroy(tsx->mutex);
-	pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool);
+	tsx_shutdown(tsx);
 	return status;
     }
@@ -1027,15 +977,26 @@
 }
 
-
-/* Destroy transaction. */
-static pj_status_t tsx_destroy( pjsip_transaction *tsx )
-{
-    struct tsx_lock_data *lck;
-
+/* Really destroy transaction, when grp_lock reference is zero */
+static void tsx_on_destroy( void *arg )
+{
+    pjsip_transaction *tsx = (pjsip_transaction*)arg;
+
+    PJ_LOG(5,(tsx->obj_name, "Transaction destroyed!"));
+
+    pj_mutex_destroy(tsx->mutex_b);
+    pjsip_endpt_release_pool(tsx->endpt, tsx->pool);
+}
+
+/* Shutdown transaction. */
+static pj_status_t tsx_shutdown( pjsip_transaction *tsx )
+{
     /* Release the transport */
     tsx_update_transport(tsx, NULL);
 
-    /* Decrement reference counter in transport selector */
-    pjsip_tpselector_dec_ref(&tsx->tp_sel);
+    /* Decrement reference counter in transport selector, only if
+     * we haven't been called before */
+    if (!tsx->terminating) {
+	pjsip_tpselector_dec_ref(&tsx->tp_sel);
+    }
 
     /* Free last transmitted message. */
@@ -1057,4 +1018,5 @@
     /* Clear some pending flags. */
     tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED | TSX_HAS_PENDING_SEND);
+
 
     /* Refuse to destroy transaction if it has pending resolving. */
@@ -1064,22 +1026,12 @@
 	PJ_LOG(4,(tsx->obj_name, "Will destroy later because transport is "
 				 "in progress"));
-	return PJ_EBUSY;
-    }
-
-    /* Clear TLS, so that mutex will not be unlocked */
-    lck = (struct tsx_lock_data*) pj_thread_local_get(pjsip_tsx_lock_tls_id);
-    while (lck) {
-	if (lck->tsx == tsx) {
-	    lck->is_alive = 0;
-	}
-	lck = lck->prev;
-    }
-
-    pj_mutex_destroy(tsx->mutex_b);
-    pj_mutex_destroy(tsx->mutex);
-
-    PJ_LOG(5,(tsx->obj_name, "Transaction destroyed!"));
-
-    pjsip_endpt_release_pool(tsx->endpt, tsx->pool);
+    }
+
+    if (!tsx->terminating) {
+	tsx->terminating = PJ_TRUE;
+	pj_grp_lock_dec_ref(tsx->grp_lock);
+    }
+
+    /* No acccess to tsx after this, it may have been destroyed */
 
     return PJ_SUCCESS;
@@ -1094,5 +1046,4 @@
     pjsip_event event;
     pjsip_transaction *tsx = (pjsip_transaction*) entry->user_data;
-    struct tsx_lock_data lck;
 
     PJ_UNUSED_ARG(theap);
@@ -1108,7 +1059,7 @@
 
     /* Dispatch event to transaction. */
-    lock_tsx(tsx, &lck);
+    pj_grp_lock_acquire(tsx->grp_lock);
     (*tsx->state_handler)(tsx, &event);
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_release(tsx->grp_lock);
 
     pj_log_pop_indent();
@@ -1209,5 +1160,5 @@
 
 	/* Destroy transaction. */
-	tsx_destroy(tsx);
+	tsx_shutdown(tsx);
     }
 
@@ -1221,4 +1172,12 @@
 PJ_DEF(pj_status_t) pjsip_tsx_create_uac( pjsip_module *tsx_user,
 					  pjsip_tx_data *tdata,
+					  pjsip_transaction **p_tsx)
+{
+    return pjsip_tsx_create_uac2(tsx_user, tdata, NULL, p_tsx);
+}
+
+PJ_DEF(pj_status_t) pjsip_tsx_create_uac2(pjsip_module *tsx_user,
+					  pjsip_tx_data *tdata,
+					  pj_grp_lock_t *grp_lock,
 					  pjsip_transaction **p_tsx)
 {
@@ -1228,5 +1187,4 @@
     pjsip_via_hdr *via;
     pjsip_host_info dst_info;
-    struct tsx_lock_data lck;
     pj_status_t status;
 
@@ -1252,5 +1210,5 @@
 
     /* Create transaction instance. */
-    status = tsx_create( tsx_user, &tsx);
+    status = tsx_create( tsx_user, grp_lock, &tsx);
     if (status != PJ_SUCCESS)
 	return status;
@@ -1258,5 +1216,5 @@
 
     /* Lock transaction. */
-    lock_tsx(tsx, &lck);
+    pj_grp_lock_acquire(tsx->grp_lock);
 
     /* Role is UAC. */
@@ -1324,6 +1282,6 @@
     status = pjsip_get_request_dest(tdata, &dst_info);
     if (status != PJ_SUCCESS) {
-	unlock_tsx(tsx, &lck);
-	tsx_destroy(tsx);
+	pj_grp_lock_release(tsx->grp_lock);
+	tsx_shutdown(tsx);
 	return status;
     }
@@ -1336,6 +1294,6 @@
 	pj_assert(!"Bug in branch_param generator (i.e. not unique)");
 	*/
-	unlock_tsx(tsx, &lck);
-	tsx_destroy(tsx);
+	pj_grp_lock_release(tsx->grp_lock);
+	tsx_shutdown(tsx);
 	return status;
     }
@@ -1343,5 +1301,5 @@
 
     /* Unlock transaction and return. */
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_release(tsx->grp_lock);
 
     pj_log_push_indent();
@@ -1360,4 +1318,12 @@
 PJ_DEF(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user,
 					  pjsip_rx_data *rdata,
+					  pjsip_transaction **p_tsx)
+{
+    return pjsip_tsx_create_uas2(tsx_user, rdata, NULL, p_tsx);
+}
+
+PJ_DEF(pj_status_t) pjsip_tsx_create_uas2(pjsip_module *tsx_user,
+					  pjsip_rx_data *rdata,
+					  pj_grp_lock_t *grp_lock,
 					  pjsip_transaction **p_tsx)
 {
@@ -1367,5 +1333,4 @@
     pjsip_cseq_hdr *cseq;
     pj_status_t status;
-    struct tsx_lock_data lck;
 
     /* Validate arguments. */
@@ -1405,5 +1370,5 @@
      * Create transaction instance. 
      */
-    status = tsx_create( tsx_user, &tsx);
+    status = tsx_create( tsx_user, grp_lock, &tsx);
     if (status != PJ_SUCCESS)
 	return status;
@@ -1411,5 +1376,5 @@
 
     /* Lock transaction. */
-    lock_tsx(tsx, &lck);
+    pj_grp_lock_acquire(tsx->grp_lock);
 
     /* Role is UAS */
@@ -1428,6 +1393,6 @@
                                   PJSIP_ROLE_UAS, &tsx->method, rdata);
     if (status != PJ_SUCCESS) {
-	unlock_tsx(tsx, &lck);
-        tsx_destroy(tsx);
+	pj_grp_lock_release(tsx->grp_lock);
+	tsx_shutdown(tsx);
         return status;
     }
@@ -1455,6 +1420,6 @@
     status = pjsip_get_response_addr( tsx->pool, rdata, &tsx->res_addr );
     if (status != PJ_SUCCESS) {
-	unlock_tsx(tsx, &lck);
-	tsx_destroy(tsx);
+	pj_grp_lock_release(tsx->grp_lock);
+	tsx_shutdown(tsx);
 	return status;
     }
@@ -1477,6 +1442,6 @@
     status = mod_tsx_layer_register_tsx(tsx);
     if (status != PJ_SUCCESS) {
-	unlock_tsx(tsx, &lck);
-	tsx_destroy(tsx);
+	pj_grp_lock_release(tsx->grp_lock);
+	tsx_shutdown(tsx);
 	return status;
     }
@@ -1486,5 +1451,5 @@
 
     /* Unlock transaction and return. */
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_release(tsx->grp_lock);
 
     pj_log_push_indent();
@@ -1505,11 +1470,9 @@
 					    const pjsip_tpselector *sel)
 {
-    struct tsx_lock_data lck;
-
     /* Must be UAC transaction */
     PJ_ASSERT_RETURN(tsx && sel, PJ_EINVAL);
 
     /* Start locking the transaction. */
-    lock_tsx(tsx, &lck);
+    pj_grp_lock_acquire(tsx->grp_lock);
 
     /* Decrement reference counter of previous transport selector */
@@ -1523,5 +1486,5 @@
 
     /* Unlock transaction. */
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_release(tsx->grp_lock);
 
     return PJ_SUCCESS;
@@ -1548,6 +1511,4 @@
 PJ_DEF(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx, int code )
 {
-    struct tsx_lock_data lck;
-
     PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL);
 
@@ -1561,8 +1522,8 @@
     pj_log_push_indent();
 
-    lock_tsx(tsx, &lck);
+    pj_grp_lock_acquire(tsx->grp_lock);
     tsx_set_status_code(tsx, code, NULL);
     tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, PJSIP_EVENT_USER, NULL);
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_release(tsx->grp_lock);
 
     pj_log_pop_indent();
@@ -1579,6 +1540,4 @@
 PJ_DEF(pj_status_t) pjsip_tsx_stop_retransmit(pjsip_transaction *tsx)
 {
-    struct tsx_lock_data lck;
-
     PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL);
     PJ_ASSERT_RETURN(tsx->role == PJSIP_ROLE_UAC &&
@@ -1590,5 +1549,5 @@
     pj_log_push_indent();
 
-    lock_tsx(tsx, &lck);
+    pj_grp_lock_acquire(tsx->grp_lock);
     /* Cancel retransmission timer. */
     if (tsx->retransmit_timer.id != 0) {
@@ -1596,5 +1555,5 @@
 	tsx->retransmit_timer.id = 0;
     }
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_release(tsx->grp_lock);
 
     pj_log_pop_indent();
@@ -1618,6 +1577,6 @@
 		     PJ_EINVALIDOP);
 
-    /* Note: must not call lock_tsx() as that would introduce deadlock.
-     * See #1121.
+    /* Note: must not call pj_grp_lock_acquire(tsx->grp_lock) as
+     * that would introduce deadlock. See #1121.
      */
     lock_timer(tsx);
@@ -1660,5 +1619,4 @@
 {
     pjsip_event event;
-    struct tsx_lock_data lck;
     pj_status_t status;
 
@@ -1676,5 +1634,5 @@
 
     /* Dispatch to transaction. */
-    lock_tsx(tsx, &lck);
+    pj_grp_lock_acquire(tsx->grp_lock);
 
     /* Set transport selector to tdata */
@@ -1684,5 +1642,5 @@
     status = (*tsx->state_handler)(tsx, &event);
 
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_release(tsx->grp_lock);
 
     /* Only decrement reference counter when it returns success.
@@ -1707,6 +1665,4 @@
 {
     pjsip_event event;
-    struct tsx_lock_data lck;
-    pj_status_t status;
 
     PJ_LOG(5,(tsx->obj_name, "Incoming %s in state %s", 
@@ -1721,7 +1677,7 @@
 
     /* Dispatch to transaction. */
-    lock_tsx(tsx, &lck);
-    status = (*tsx->state_handler)(tsx, &event);
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_acquire(tsx->grp_lock);
+    (*tsx->state_handler)(tsx, &event);
+    pj_grp_lock_release(tsx->grp_lock);
 
     pj_log_pop_indent();
@@ -1735,5 +1691,4 @@
     pjsip_transaction *tsx = (pjsip_transaction*) send_state->token;
     pjsip_tx_data *tdata = send_state->tdata;
-    struct tsx_lock_data lck;
 
     /* Check if transaction has cancelled itself from this transmit
@@ -1749,9 +1704,9 @@
     }
 
+    pj_grp_lock_acquire(tsx->grp_lock);
+
     /* Reset */
     tdata->mod_data[mod_tsx_layer.mod.id] = NULL;
     tsx->pending_tx = NULL;
-
-    lock_tsx(tsx, &lck);
 
     if (sent > 0) {
@@ -1783,5 +1738,5 @@
 	    tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED, 
 			   PJSIP_EVENT_UNKNOWN, NULL );
-	    unlock_tsx(tsx, &lck);
+	    pj_grp_lock_release(tsx->grp_lock);
 	    return;
 	}
@@ -1825,5 +1780,5 @@
 	    err =pj_strerror(-sent, errmsg, sizeof(errmsg));
 
-	    PJ_LOG(2,(tsx->obj_name, 
+	    PJ_LOG(2,(tsx->obj_name,
 		      "Failed to send %s! err=%d (%s)",
 		      pjsip_tx_data_get_info(send_state->tdata), -sent,
@@ -1863,11 +1818,8 @@
 
 	} else {
-	    char errmsg[PJ_ERR_MSG_SIZE];
-
-	    PJ_LOG(2,(tsx->obj_name, 
-		      "Temporary failure in sending %s, "
-		      "will try next server. Err=%d (%s)",
-		      pjsip_tx_data_get_info(send_state->tdata), -sent,
-		      pj_strerror(-sent, errmsg, sizeof(errmsg)).ptr));
+	    PJ_PERROR(2,(tsx->obj_name, -sent,
+		         "Temporary failure in sending %s, "
+		         "will try next server",
+		         pjsip_tx_data_get_info(send_state->tdata)));
 
 	    /* Reset retransmission count */
@@ -1894,5 +1846,5 @@
     }
 
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_release(tsx->grp_lock);
 }
 
@@ -1904,5 +1856,4 @@
     if (sent < 0) {
 	pjsip_transaction *tsx = (pjsip_transaction*) token;
-	struct tsx_lock_data lck;
 	char errmsg[PJ_ERR_MSG_SIZE];
 	pj_str_t err;
@@ -1913,7 +1864,7 @@
 
 	PJ_LOG(2,(tsx->obj_name, "Transport failed to send %s! Err=%d (%s)",
-		  pjsip_tx_data_get_info(tdata), -sent, errmsg));
-
-	lock_tsx(tsx, &lck);
+		pjsip_tx_data_get_info(tdata), -sent, errmsg));
+
+	pj_grp_lock_acquire(tsx->grp_lock);
 
 	/* Release transport. */
@@ -1925,5 +1876,5 @@
 		       PJSIP_EVENT_TRANSPORT_ERROR, tdata );
 
-	unlock_tsx(tsx, &lck);
+	pj_grp_lock_release(tsx->grp_lock);
    }
 }
@@ -1941,5 +1892,4 @@
     if (state == PJSIP_TP_STATE_DISCONNECTED) {
 	pjsip_transaction *tsx;
-	struct tsx_lock_data lck;
 
 	pj_assert(tp && info && info->user_data);
@@ -1947,5 +1897,5 @@
 	tsx = (pjsip_transaction*)info->user_data;
 
-	lock_tsx(tsx, &lck);
+	pj_grp_lock_acquire(tsx->grp_lock);
 
 	/* Terminate transaction when transport disconnected */
@@ -1960,5 +1910,5 @@
 	}
 
-	unlock_tsx(tsx, &lck);
+	pj_grp_lock_release(tsx->grp_lock);
     }
 }
@@ -1992,10 +1942,7 @@
 
 	if (status != PJ_SUCCESS) {
-	    char errmsg[PJ_ERR_MSG_SIZE];
-
-	    PJ_LOG(2,(tsx->obj_name, 
-		      "Error sending %s: Err=%d (%s)",
-		      pjsip_tx_data_get_info(tdata), status, 
-		      pj_strerror(status, errmsg, sizeof(errmsg)).ptr));
+	    PJ_PERROR(2,(tsx->obj_name, status,
+		         "Error sending %s",
+		         pjsip_tx_data_get_info(tdata)));
 
 	    /* On error, release transport to force using full transport
@@ -2110,13 +2057,12 @@
 						  pjsip_tx_data *tdata)
 {
-    struct tsx_lock_data lck;
     pj_status_t status;
 
-    lock_tsx(tsx, &lck);
+    pj_grp_lock_acquire(tsx->grp_lock);
     if (tdata == NULL) {
 	tdata = tsx->last_tx;
     }
     status = tsx_send_msg(tsx, tdata);
-    unlock_tsx(tsx, &lck);
+    pj_grp_lock_release(tsx->grp_lock);
 
     /* Only decrement reference counter when it returns success.
