From a064c4c14f7720026b28c6e082e8aa1aaca03089 Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Sun, 10 Jan 2016 15:42:09 -0800
Subject: [PATCH 2/2] Ticket #48406 - Avoid self deadlock by
 PR_Lock(conn->c_mutex)

Description:  Fixing ticket 48338 introduced a self deadlock.
To avoid the self deadlock, tried to remove PR_Lock(conn->c_mutex)
which looked harmless, but it introduced a crash by memory corruption.

This patch adds thin layer on top of PR_{Lock,Unlock}(conn->c_mutex),
which locks only when it is not already acquired in the thread and
unlocks only when it is acquired in the same level, respectively.
---
 ldap/servers/slapd/abandon.c         |   5 +-
 ldap/servers/slapd/bind.c            |   5 +-
 ldap/servers/slapd/connection.c      |  71 +++++++++++---------
 ldap/servers/slapd/conntable.c       |  20 +++---
 ldap/servers/slapd/daemon.c          |  27 +++++---
 ldap/servers/slapd/extendop.c        |  12 ++--
 ldap/servers/slapd/main.c            |   1 +
 ldap/servers/slapd/operation.c       |  20 +++---
 ldap/servers/slapd/opshared.c        |  19 +++---
 ldap/servers/slapd/pagedresults.c    | 125 +++++++++++++++++++++--------------
 ldap/servers/slapd/pblock.c          |  76 +++++++++++----------
 ldap/servers/slapd/proto-slap.h      |   8 +++
 ldap/servers/slapd/psearch.c         |  11 +--
 ldap/servers/slapd/saslbind.c        |  28 ++++----
 ldap/servers/slapd/slapi-plugin.h    |   5 ++
 ldap/servers/slapd/start_tls_extop.c |  12 ++--
 ldap/servers/slapd/thread_data.c     |  68 +++++++++++++++++++
 ldap/servers/slapd/unbind.c          |   5 +-
 ldap/servers/slapd/util.c            |  35 ++++++++++
 19 files changed, 365 insertions(+), 188 deletions(-)

diff --git a/ldap/servers/slapd/abandon.c b/ldap/servers/slapd/abandon.c
index 761b895..44517ec 100644
--- a/ldap/servers/slapd/abandon.c
+++ b/ldap/servers/slapd/abandon.c
@@ -37,6 +37,7 @@ do_abandon( Slapi_PBlock *pb )
 	ber_int_t	id;
 	Operation	*o;
 	BerElement	*ber = pb->pb_op->o_ber;
+	int is_local = 0;
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_abandon\n", 0, 0, 0 );
 
@@ -77,7 +78,7 @@ do_abandon( Slapi_PBlock *pb )
 	 * flag and abort the operation at a convenient time.
 	 */
 
-	PR_Lock( pb->pb_conn->c_mutex );
+	slapd_conn_lock(pb->pb_conn, &is_local);
 	for ( o = pb->pb_conn->c_ops; o != NULL; o = o->o_next ) {
 		if ( o->o_msgid == id && o != pb->pb_op)
 			break;
@@ -138,7 +139,7 @@ do_abandon( Slapi_PBlock *pb )
 			o->o_results.r.r_search.nentries, current_time() - o->o_time );
 	}
 
-	PR_Unlock( pb->pb_conn->c_mutex );
+	slapd_conn_unlock(pb->pb_conn, is_local);
 	/*
 	 * Wake up the persistent searches, so they
 	 * can notice if they've been abandoned.
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index 474b508..ef766b5 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -108,6 +108,7 @@ do_bind( Slapi_PBlock *pb )
     int minssf = 0;
     int minssf_exclude_rootdse = 0;
     Slapi_DN *original_sdn = NULL;
+    int is_local = 0;
 
     LDAPDebug( LDAP_DEBUG_TRACE, "do_bind\n", 0, 0, 0 );
 
@@ -258,7 +259,7 @@ do_bind( Slapi_PBlock *pb )
         slapi_pblock_get (pb, SLAPI_PWPOLICY, &pw_response_requested);
     }
 
-    PR_Lock( pb->pb_conn->c_mutex );
+    slapd_conn_lock(pb->pb_conn, &is_local);
 
     bind_credentials_clear( pb->pb_conn, PR_FALSE, /* do not lock conn */
                             PR_FALSE /* do not clear external creds. */ );
@@ -291,7 +292,7 @@ do_bind( Slapi_PBlock *pb )
      * bound user can work properly
      */
     pb->pb_conn->c_needpw = 0;
-    PR_Unlock( pb->pb_conn->c_mutex );
+    slapd_conn_unlock(pb->pb_conn, is_local);
 
     log_bind_access(pb, dn?dn:"empty", method, version, saslmech, NULL);
 
diff --git a/ldap/servers/slapd/connection.c b/ldap/servers/slapd/connection.c
index 1a9301a..d859c0f 100644
--- a/ldap/servers/slapd/connection.c
+++ b/ldap/servers/slapd/connection.c
@@ -745,11 +745,12 @@ int connection_acquire_nolock (Connection *conn) {
 int connection_is_free (Connection *conn)
 {
     int rc;
+    int is_local = 0;
 
-    PR_Lock(conn->c_mutex);
+    slapd_conn_lock(conn, &is_local);
     rc = conn->c_sd == SLAPD_INVALID_SOCKET && conn->c_refcnt == 0 &&
          !(conn->c_flags & CONN_FLAG_CLOSING);
-    PR_Unlock(conn->c_mutex);
+    slapd_conn_unlock(conn, is_local);
 
     return rc;
 }
@@ -1135,8 +1136,9 @@ int connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, i
 	PRErrorCode err = 0;
 	PRInt32 syserr = 0;
 	size_t buffer_data_avail;
+	int is_local = 0;
 
-	PR_Lock(conn->c_mutex);
+	slapd_conn_lock(conn, &is_local);
 	/*
 	 * if the socket is still valid, get the ber element
 	 * waiting for us on this connection. timeout is handled
@@ -1325,15 +1327,16 @@ int connection_read_operation(Connection *conn, Operation *op, ber_tag_t *tag, i
 	}
 	op->o_tag = *tag;
 done:
-	PR_Unlock(conn->c_mutex);
+	slapd_conn_unlock(conn, is_local);
 	return ret;
 }
 
 void connection_make_readable(Connection *conn)
 {
-	PR_Lock( conn->c_mutex );
+	int is_local = 0;
+	slapd_conn_lock(conn, &is_local);
 	conn->c_gettingber = 0;
-	PR_Unlock( conn->c_mutex );
+	slapd_conn_unlock(conn, is_local);
 	signal_listner();
 }
 
@@ -1355,7 +1358,8 @@ void connection_check_activity_level(Connection *conn)
 {
 	int current_count = 0;
 	int delta_count = 0;
-	PR_Lock( conn->c_mutex );
+	int is_local = 0;
+	slapd_conn_lock(conn, &is_local);
 	/* get the current op count */
 	current_count = conn->c_opscompleted;
 	/* compare to the previous op count */
@@ -1366,7 +1370,7 @@ void connection_check_activity_level(Connection *conn)
 	conn->c_private->previous_op_count = current_count;
 	/* update the last checked time */
 	conn->c_private->previous_count_check_time = current_time();
-	PR_Unlock( conn->c_mutex );
+	slapd_conn_unlock(conn, is_local);
 	LDAPDebug(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " activity level = %d\n",conn->c_connid,delta_count,0); 
 }
 
@@ -1410,7 +1414,8 @@ void connection_enter_leave_turbo(Connection *conn, int current_turbo_flag, int
 	int connection_count = 0;
 	int our_rank = 0;
 	int threshold_rank = 0;
-	PR_Lock(conn->c_mutex);
+	int is_local = 0;
+	slapd_conn_lock(conn, &is_local);
 	/* We can already be in turbo mode, or not */
 	current_mode = current_turbo_flag;
 	if (pagedresults_in_use_nolock(conn)) {
@@ -1466,7 +1471,7 @@ void connection_enter_leave_turbo(Connection *conn, int current_turbo_flag, int
 		}
 	  }
 	}
-	PR_Unlock(conn->c_mutex);
+	slapd_conn_unlock(conn, is_local);
 	if (current_mode != new_mode) {
 		if (current_mode) {
 			LDAPDebug(LDAP_DEBUG_CONNS,"conn %" NSPRIu64 " leaving turbo mode\n",conn->c_connid,0,0); 
@@ -1496,6 +1501,7 @@ connection_threadmain()
 	int maxthreads = 0;
 	int enable_nunc_stans = 0;
 	long bypasspollcnt = 0;
+	int is_local = 0;
 
 #ifdef ENABLE_NUNC_STANS
 	enable_nunc_stans = config_get_enable_nunc_stans();
@@ -1572,13 +1578,13 @@ connection_threadmain()
 			*/
 			PR_Sleep(PR_INTERVAL_NO_WAIT);
 
-			PR_Lock(conn->c_mutex);
+			slapd_conn_lock(conn, &is_local);
 			/* Make our own pb in turbo mode */
 			connection_make_new_pb(pb,conn);
 			if (connection_call_io_layer_callbacks(conn)) {
 				LDAPDebug0Args( LDAP_DEBUG_ANY, "Error: could not add/remove IO layers from connection\n" );
 			}
-			PR_Unlock(conn->c_mutex);
+			slapd_conn_unlock(conn, is_local);
 			if (! config_check_referral_mode()) {
 			  slapi_counter_increment(ops_initiated);
 			  slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsInOps); 
@@ -1693,7 +1699,7 @@ connection_threadmain()
  */
 			} else if (!enable_nunc_stans) { /* more data in conn - just put back on work_q - bypass poll */
 				bypasspollcnt++;
-				PR_Lock(conn->c_mutex);
+				slapd_conn_lock(conn, &is_local);
 				/* don't do this if it would put us over the max threads per conn */
 				if (conn->c_threadnumber < maxthreads) {
 					/* for turbo, c_idlesince is set above - for !turbo and
@@ -1708,7 +1714,7 @@ connection_threadmain()
 					/* keep count of how many times maxthreads has blocked an operation */
 					conn->c_maxthreadsblocked++;
 				}
-				PR_Unlock(conn->c_mutex);
+				slapd_conn_unlock(conn, is_local);
 			}
 		}
 
@@ -1744,14 +1750,14 @@ connection_threadmain()
 
 done:	
 		if (doshutdown) {
-			PR_Lock(conn->c_mutex);
+			slapd_conn_lock(conn, &is_local);
 			connection_remove_operation_ext(pb, conn, op);
 			connection_make_readable_nolock(conn);
 			conn->c_threadnumber--;
 			slapi_counter_decrement(conns_in_maxthreads);
 			slapi_counter_decrement(g_get_global_snmp_vars()->ops_tbl.dsConnectionsInMaxThreads);
 			connection_release_nolock(conn);
-			PR_Unlock(conn->c_mutex);
+			slapd_conn_unlock(conn, is_local);
 			signal_listner();
 			return;
 		}
@@ -1768,9 +1774,9 @@ done:
 		slapi_counter_increment(ops_completed);
 		/* If this op isn't a persistent search, remove it */
 		if ( pb->pb_op->o_flags & OP_FLAG_PS ) {
-			    PR_Lock( conn->c_mutex );
+				slapd_conn_lock(conn, &is_local);
 			    connection_release_nolock (conn); /* psearch acquires ref to conn - release this one now */
-			    PR_Unlock( conn->c_mutex );
+				slapd_conn_unlock(conn, is_local);
 			    /* ps_add makes a shallow copy of the pb - so we
 			     * can't free it or init it here - just memset it to 0
 			     * ps_send_results will call connection_remove_operation_ext to free it
@@ -1778,7 +1784,7 @@ done:
 			    memset(pb, 0, sizeof(*pb));
 		} else {
 			/* delete from connection operation queue & decr refcnt */
-			PR_Lock( conn->c_mutex );
+			slapd_conn_lock(conn, &is_local);
 			connection_remove_operation_ext( pb, conn, op );
 
 			/* If we're in turbo mode, we keep our reference to the connection alive */
@@ -1819,7 +1825,7 @@ done:
 					signal_listner();
 				}
 			}
-			PR_Unlock( conn->c_mutex );
+			slapd_conn_unlock(conn, is_local);
 		}
 	} /* while (1) */
 }
@@ -2078,17 +2084,18 @@ op_copy_identity(Connection *conn, Operation *op)
 {
     size_t dnlen;
     size_t typelen;
+    int is_local = 0;
 
-	PR_Lock( conn->c_mutex );
-	dnlen= conn->c_dn ? strlen (conn->c_dn) : 0;
-	typelen= conn->c_authtype ? strlen (conn->c_authtype) : 0;
+    slapd_conn_lock(conn, &is_local);
+    dnlen= conn->c_dn ? strlen (conn->c_dn) : 0;
+    typelen= conn->c_authtype ? strlen (conn->c_authtype) : 0;
 
-	slapi_sdn_done(&op->o_sdn);
-	slapi_ch_free_string(&(op->o_authtype));
+    slapi_sdn_done(&op->o_sdn);
+    slapi_ch_free_string(&(op->o_authtype));
     if (dnlen <= 0 && typelen <= 0) {
         op->o_authtype = NULL;
     } else {
-	    slapi_sdn_set_dn_byval(&op->o_sdn,conn->c_dn);
+        slapi_sdn_set_dn_byval(&op->o_sdn,conn->c_dn);
         op->o_authtype = slapi_ch_strdup(conn->c_authtype);
         /* set the thread data bind dn index */
         slapi_td_set_dn(slapi_ch_strdup(conn->c_dn));
@@ -2111,14 +2118,15 @@ op_copy_identity(Connection *conn, Operation *op)
         op->o_ssf = conn->c_local_ssf;
     }
 
-    PR_Unlock( conn->c_mutex );
+    slapd_conn_unlock(conn, is_local);
 }
 
 /* Sets the SSL SSF in the connection struct. */
 static void
 connection_set_ssl_ssf(Connection *conn)
 {
-	PR_Lock( conn->c_mutex );
+	int is_local = 0;
+	slapd_conn_lock(conn, &is_local);
 
 	if (conn->c_flags & CONN_FLAG_SSL) {
 		SSL_SecurityStatus(conn->c_prfd, NULL, NULL, NULL, &(conn->c_ssl_ssf), NULL, NULL);
@@ -2126,7 +2134,7 @@ connection_set_ssl_ssf(Connection *conn)
 		conn->c_ssl_ssf = 0;
 	}
 
-	PR_Unlock( conn->c_mutex );
+	slapd_conn_unlock(conn, is_local);
 }
 
 static int
@@ -2173,9 +2181,10 @@ log_ber_too_big_error(const Connection *conn, ber_len_t ber_len,
 void
 disconnect_server( Connection *conn, PRUint64 opconnid, int opid, PRErrorCode reason, PRInt32 error )
 {
-	PR_Lock( conn->c_mutex );
+	int is_local = 0;
+	slapd_conn_lock(conn, &is_local);
 	disconnect_server_nomutex( conn, opconnid, opid, reason, error );
-	PR_Unlock( conn->c_mutex );
+	slapd_conn_unlock(conn, is_local);
 }
 
 static ps_wakeup_all_fn_ptr ps_wakeup_all_fn = NULL;
diff --git a/ldap/servers/slapd/conntable.c b/ldap/servers/slapd/conntable.c
index d5b9058..eee03ad 100644
--- a/ldap/servers/slapd/conntable.c
+++ b/ldap/servers/slapd/conntable.c
@@ -83,13 +83,14 @@ void
 connection_table_abandon_all_operations(Connection_Table *ct)
 {
 	int	i;
+	int is_local = 0;
 	for ( i = 0; i < ct->size; i++ )
 	{
-		if ( ct->c[i].c_mutex != NULL )
+		if ( ct->c[i].c_mutex )
 		{
-			PR_Lock( ct->c[i].c_mutex );
+			slapd_conn_lock(&(ct->c[i]), &is_local);
 			connection_abandon_operations( &ct->c[i] );
-			PR_Unlock( ct->c[i].c_mutex );
+			slapd_conn_unlock(&(ct->c[i]), is_local);
 		}
 	}
 }
@@ -342,6 +343,7 @@ connection_table_as_entry(Connection_Table *ct, Slapi_Entry *e)
 	struct berval	*vals[2];
 	int	i, nconns, nreadwaiters;
 	struct tm utm;
+	int is_local = 0;
 
 	vals[0] = &val;
 	vals[1] = NULL;
@@ -360,7 +362,7 @@ connection_table_as_entry(Connection_Table *ct, Slapi_Entry *e)
 		/* Can't take c_mutex if holding table_mutex; temporarily unlock */ 
 		PR_Unlock( ct->table_mutex );
 
-		PR_Lock( ct->c[i].c_mutex );
+		slapd_conn_lock(&(ct->c[i]), &is_local);
 		if ( ct->c[i].c_sd != SLAPD_INVALID_SOCKET )
 		{
 			char buf2[20];
@@ -420,7 +422,7 @@ connection_table_as_entry(Connection_Table *ct, Slapi_Entry *e)
 			attrlist_merge( &e->e_attrs, "connection", vals );
 			slapi_ch_free_string(&newbuf);
 		}
-		PR_Unlock( ct->c[i].c_mutex );
+		slapd_conn_unlock(&(ct->c[i]), is_local);
 	}
 
 	PR_snprintf( buf, sizeof(buf), "%d", nconns );
@@ -458,14 +460,16 @@ void
 connection_table_dump_activity_to_errors_log(Connection_Table *ct)
 {
 	int i;
+	int is_local = 0;
+
 	for ( i = 0; i < ct->size; i++ )
 	{
 		Connection *c= &(ct->c[i]);
-		if ( c->c_mutex != NULL )
+		if ( c->c_mutex )
 		{
 			/* Find the connection we are referring to */
 			int j= c->c_fdi;
-			PR_Lock( c->c_mutex );
+			slapd_conn_lock(c, &is_local);
 			if ( (c->c_sd != SLAPD_INVALID_SOCKET) && 
 			     (j >= 0) && (c->c_prfd == ct->fd[j].fd) )
 			{
@@ -475,7 +479,7 @@ connection_table_dump_activity_to_errors_log(Connection_Table *ct)
 					LDAPDebug( LDAP_DEBUG_CONNS,"activity on %d%s\n", i, r ? "r" : "",0 );
 				}
 			}
-			PR_Unlock( c->c_mutex );
+			slapd_conn_unlock(c, is_local);
 		}
 	}
 }
diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 8413937..e3e806d 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -1489,6 +1489,7 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
 	slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
 	int max_threads_per_conn = config_get_maxthreadsperconn();
 	int n_listeners = 0;
+	int is_local = 0;
 
 	accept_new_connections = ((ct->size - g_get_current_conn_count())
 		> slapdFrontendConfig->reservedescriptors);
@@ -1624,7 +1625,7 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
 		}
 		else
 		{
-			PR_Lock( c->c_mutex );
+			slapd_conn_lock(c, &is_local);
 			if (c->c_flags & CONN_FLAG_CLOSING)
 			{
 				/* A worker thread has marked that this connection
@@ -1673,7 +1674,7 @@ setup_pr_read_pds(Connection_Table *ct, PRFileDesc **n_tcps, PRFileDesc **s_tcps
 					c->c_fdi = SLAPD_INVALID_SOCKET_INDEX;
 				}
 			}
-			PR_Unlock( c->c_mutex );
+			slapd_conn_unlock(c, is_local);
 		}
 		c = next;
 	}
@@ -1692,7 +1693,7 @@ handle_timeout( void )
 	time_t curtime = current_time();
 
 	if (0 == prevtime) {
-		prevtime = time (&housekeeping_fire_time);		
+		prevtime = time (&housekeeping_fire_time);
 	}
 
 	if ( difftime(curtime, prevtime) >= 
@@ -1734,6 +1735,7 @@ handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll)
 	Connection *c;
 	time_t curtime = current_time();
 	int maxthreads = config_get_maxthreadsperconn();
+	int is_local = 0;
 
 #if LDAP_DEBUG
 	if ( slapd_ldap_debug & LDAP_DEBUG_CONNS )
@@ -1752,7 +1754,7 @@ handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll)
 	{
 		if ( c->c_mutex != NULL )
 		{
-			PR_Lock( c->c_mutex );
+			slapd_conn_lock(c, &is_local);
 			if ( connection_is_active_nolock (c) && c->c_gettingber == 0 )
 			{
 			    PRInt16 out_flags;
@@ -1809,7 +1811,7 @@ handle_pr_read_ready(Connection_Table *ct, PRIntn num_poll)
 								   SLAPD_DISCONNECT_IDLE_TIMEOUT, EAGAIN );
 				}
 			}
-			PR_Unlock( c->c_mutex );
+			slapd_conn_unlock(c, is_local);
 		}
 	}
 }
@@ -1843,6 +1845,7 @@ ns_handle_closure(struct ns_job_t *job)
 {
 	Connection *c = (Connection *)ns_job_get_data(job);
 	int do_yield = 0;
+	int is_local = 0;
 
 	/* this function must be called from the event loop thread */
 #ifdef DEBUG
@@ -1855,12 +1858,12 @@ ns_handle_closure(struct ns_job_t *job)
 		return;
 	}
 #endif
-	PR_Lock(c->c_mutex);
+	slapd_conn_lock(c, &is_local);
 	connection_release_nolock_ext(c, 1); /* release ref acquired for event framework */
 	PR_ASSERT(c->c_ns_close_jobs == 1); /* should be exactly 1 active close job - this one */
 	c->c_ns_close_jobs--; /* this job is processing closure */
 	do_yield = ns_handle_closure_nomutex(c);
-	PR_Unlock(c->c_mutex);
+	slapd_conn_unlock(c, is_local);
 	ns_job_done(job);
 	if (do_yield) {
 		/* closure not done - another reference still outstanding */
@@ -1938,6 +1941,7 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
 {
 	int maxthreads = config_get_maxthreadsperconn();
 	Connection *c = (Connection *)ns_job_get_data(job);
+	int is_local = 0;
 
 	/* this function must be called from the event loop thread */
 #ifdef DEBUG
@@ -1951,7 +1955,7 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
 	}
 #endif
 
-	PR_Lock(c->c_mutex);
+	slapd_conn_lock(c, &is_local);
 	LDAPDebug2Args(LDAP_DEBUG_CONNS, "activity on conn %" NSPRIu64 " for fd=%d\n",
 		       c->c_connid, c->c_sd);
 	/* if we were called due to some i/o event, see what the state of the socket is */
@@ -1998,7 +2002,7 @@ ns_handle_pr_read_ready(struct ns_job_t *job)
 		LDAPDebug2Args(LDAP_DEBUG_CONNS, "queued conn %" NSPRIu64 " for fd=%d\n",
 			       c->c_connid, c->c_sd);
 	}
-	PR_Unlock(c->c_mutex);
+	slapd_conn_unlock(c, is_local);
 	ns_job_done(job);
 	return;
 }
@@ -2488,6 +2492,7 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
 	PRFileDesc *pr_clonefd = NULL;
 	ber_len_t maxbersize;
 	slapdFrontendConfig_t *fecfg = getFrontendConfig();
+	int is_local = 0;
 
 	if (newconn) {
 		*newconn = NULL;
@@ -2505,7 +2510,7 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
 		PR_Close(pr_acceptfd);
 		return -1;
 	}
-	PR_Lock( conn->c_mutex );
+	slapd_conn_lock(conn, &is_local);
 
 	/*
 	 * Set the default idletimeout and the handle.  We'll update c_idletimeout
@@ -2604,7 +2609,7 @@ handle_new_connection(Connection_Table *ct, int tcps, PRFileDesc *pr_acceptfd, i
 		connection_table_move_connection_on_to_active_list(the_connection_table,conn);
 	}
 
-	PR_Unlock( conn->c_mutex );
+	slapd_conn_unlock(conn, is_local);
 
 	g_increment_current_conn_count();
 
diff --git a/ldap/servers/slapd/extendop.c b/ldap/servers/slapd/extendop.c
index 94036c6..9a72d26 100644
--- a/ldap/servers/slapd/extendop.c
+++ b/ldap/servers/slapd/extendop.c
@@ -30,6 +30,7 @@ static void extop_handle_import_start(Slapi_PBlock *pb, char *extoid,
     Slapi_Backend *be = NULL;
     struct berval bv;
     int ret;
+    int is_local = 0;
 
     if (extval == NULL || extval->bv_val == NULL) {
         LDAPDebug(LDAP_DEBUG_ANY,
@@ -61,7 +62,7 @@ static void extop_handle_import_start(Slapi_PBlock *pb, char *extoid,
         send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL);
         return;
     }
-	suffix = slapi_sdn_get_dn(sdn);
+    suffix = slapi_sdn_get_dn(sdn);
     /*    be = slapi_be_select(sdn); */
     be = slapi_mapping_tree_find_backend_for_sdn(sdn);
     if (be == NULL || be == defbackend_get_backend()) {
@@ -135,10 +136,10 @@ static void extop_handle_import_start(Slapi_PBlock *pb, char *extoid,
     /* okay, the import is starting now -- save the backend in the
      * connection block & mark this connection as belonging to a bulk import
      */
-    PR_Lock(pb->pb_conn->c_mutex);
+    slapd_conn_lock(pb->pb_conn, &is_local);
     pb->pb_conn->c_flags |= CONN_FLAG_IMPORT;
     pb->pb_conn->c_bi_backend = be;
-    PR_Unlock(pb->pb_conn->c_mutex);
+    slapd_conn_unlock(pb->pb_conn, is_local);
 
     slapi_pblock_set(pb, SLAPI_EXT_OP_RET_OID, EXTOP_BULK_IMPORT_START_OID);
     bv.bv_val = NULL;
@@ -159,12 +160,13 @@ static void extop_handle_import_done(Slapi_PBlock *pb, char *extoid,
     Slapi_Backend *be;
     struct berval bv;
     int ret;
+    int is_local = 0;
 
-    PR_Lock(pb->pb_conn->c_mutex);
+    slapd_conn_lock(pb->pb_conn, &is_local);
     pb->pb_conn->c_flags &= ~CONN_FLAG_IMPORT;
     be = pb->pb_conn->c_bi_backend;
     pb->pb_conn->c_bi_backend = NULL;
-    PR_Unlock(pb->pb_conn->c_mutex);
+    slapd_conn_unlock(pb->pb_conn, is_local);
 
     if ((be == NULL) || (be->be_wire_import == NULL)) {
         /* can this even happen? */
diff --git a/ldap/servers/slapd/main.c b/ldap/servers/slapd/main.c
index b048dc5..e432cb2 100644
--- a/ldap/servers/slapd/main.c
+++ b/ldap/servers/slapd/main.c
@@ -1042,6 +1042,7 @@ main( int argc, char **argv)
 		/* init the thread data indexes */
 		slapi_td_dn_init();
 		slapi_td_plugin_lock_init();
+		slapi_td_conn_lock_init();
 
 		/* 
 		 * Initialize password storage in entry extension.
diff --git a/ldap/servers/slapd/operation.c b/ldap/servers/slapd/operation.c
index 869298b..d02f968 100644
--- a/ldap/servers/slapd/operation.c
+++ b/ldap/servers/slapd/operation.c
@@ -569,8 +569,9 @@ void operation_parameters_free(struct slapi_operation_parameters **sop)
 int slapi_connection_acquire(Slapi_Connection *conn)
 {
     int rc;
+    int is_local = 0;
 
-    PR_Lock(conn->c_mutex);
+    slapd_conn_lock(conn, &is_local);
     /* rc = connection_acquire_nolock(conn); */
     /* connection in the closing state can't be acquired */
     if (conn->c_flags & CONN_FLAG_CLOSING)
@@ -586,7 +587,7 @@ int slapi_connection_acquire(Slapi_Connection *conn)
         conn->c_refcnt++;
         rc = 0;
     }
-    PR_Unlock(conn->c_mutex);
+    slapd_conn_unlock(conn, is_local);
     return(rc);
 }
 
@@ -596,7 +597,8 @@ slapi_connection_remove_operation( Slapi_PBlock *pb, Slapi_Connection *conn, Sla
 	int rc = 0;
 	Slapi_Operation **olist= &conn->c_ops;
 	Slapi_Operation **tmp;
-	PR_Lock( conn->c_mutex );
+	int is_local = 0;
+	slapd_conn_lock(conn, &is_local);
 	/* connection_remove_operation_ext(pb, conn,op); */
 	for ( tmp = olist; *tmp != NULL && *tmp != op; tmp = &(*tmp)->o_next )
 		;	/* NULL */
@@ -614,15 +616,15 @@ slapi_connection_remove_operation( Slapi_PBlock *pb, Slapi_Connection *conn, Sla
 	if (release) {
 		/* connection_release_nolock(conn); */
 		if (conn->c_refcnt <= 0) {
-        		slapi_log_error(SLAPI_LOG_FATAL, "connection",
-		                "conn=%" NSPRIu64 " fd=%d Attempt to release connection that is not acquired\n",
-		                conn->c_connid, conn->c_sd);
-        		rc = -1;
+			slapi_log_error(SLAPI_LOG_FATAL, "connection",
+			                "conn=%" NSPRIu64 " fd=%d Attempt to release connection that is not acquired\n",
+			                conn->c_connid, conn->c_sd);
+			rc = -1;
 		} else {
-        		conn->c_refcnt--;
+			conn->c_refcnt--;
 			rc = 0;
 		}
 	}
-	PR_Unlock( conn->c_mutex );
+	slapd_conn_unlock(conn, is_local);
 	return (rc);
 }
diff --git a/ldap/servers/slapd/opshared.c b/ldap/servers/slapd/opshared.c
index 20761d5..6ba0201 100644
--- a/ldap/servers/slapd/opshared.c
+++ b/ldap/servers/slapd/opshared.c
@@ -239,6 +239,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
   int             index = 0;
   int             sent_result = 0;
   unsigned int    pr_stat = 0;
+  int is_local = 0;
 
   ber_int_t pagesize = -1;
   ber_int_t estimate = 0; /* estimated search result set size */
@@ -675,7 +676,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
        * In async paged result case, the search result might be released
        * by other theads.  We need to double check it in the locked region.
        */
-      PR_Lock(pb->pb_conn->c_mutex);
+      slapd_conn_lock(pb->pb_conn, &is_local);
       pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, 1/*locked*/, pr_idx);
       if (pr_search_result) {
         if (pagedresults_is_abandoned_or_notavailable(pb->pb_conn, 1/*locked*/, pr_idx)) {
@@ -683,7 +684,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
           /* Previous operation was abandoned and the simplepaged object is not in use. */
           send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL);
           rc = LDAP_SUCCESS;
-          PR_Unlock(pb->pb_conn->c_mutex);
+          slapd_conn_unlock(pb->pb_conn, is_local);
           goto free_and_return;
         } else {
           slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
@@ -692,7 +693,7 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
           /* search result could be reset in the backend/dse */
           slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
           pagedresults_set_search_result(pb->pb_conn, operation, sr, 1/*locked*/, pr_idx);
-          PR_Unlock(pb->pb_conn->c_mutex);
+          slapd_conn_unlock(pb->pb_conn, is_local);
         }
       } else {
         pr_stat = PAGEDRESULTS_SEARCH_END;
@@ -826,10 +827,10 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
         /* PAGED RESULTS */
         if (op_is_pagedresults(operation)) {
             /* cleanup the slot */
-            PR_Lock(pb->pb_conn->c_mutex);
+            slapd_conn_lock(pb->pb_conn, &is_local);
             pagedresults_set_search_result(pb->pb_conn, operation, NULL, 1, pr_idx);
             rc = pagedresults_set_current_be(pb->pb_conn, NULL, pr_idx, 1);
-            PR_Unlock(pb->pb_conn->c_mutex);
+            slapd_conn_unlock(pb->pb_conn, is_local);
         }
         if (1 == flag_no_such_object) {
             break;
@@ -871,11 +872,11 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
             slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
             if (PAGEDRESULTS_SEARCH_END == pr_stat) {
               /* no more entries, but at least another backend */
-              PR_Lock(pb->pb_conn->c_mutex);
+              slapd_conn_lock(pb->pb_conn, &is_local);
               pagedresults_set_search_result(pb->pb_conn, operation, NULL, 1, pr_idx);
               be->be_search_results_release(&sr);
               rc = pagedresults_set_current_be(pb->pb_conn, next_be, pr_idx, 1);
-              PR_Unlock(pb->pb_conn->c_mutex);
+              slapd_conn_unlock(pb->pb_conn, is_local);
               if (NULL == next_be) {
                   /* no more entries && no more backends */
                   curr_search_count = -1;
@@ -900,9 +901,9 @@ op_shared_search (Slapi_PBlock *pb, int send_result)
             next_be = NULL; /* to break the loop */
             if (operation->o_status & SLAPI_OP_STATUS_ABANDONED) {
                 /* It turned out this search was abandoned. */
-                PR_Lock(pb->pb_conn->c_mutex);
+                slapd_conn_lock(pb->pb_conn, &is_local);
                 pagedresults_free_one_msgid_nolock( pb->pb_conn, operation->o_msgid);
-                PR_Unlock(pb->pb_conn->c_mutex);
+                slapd_conn_unlock(pb->pb_conn, is_local);
                 /* paged-results-request was abandoned; making an empty cookie. */
                 pagedresults_set_response_control(pb, 0, estimate, -1, pr_idx);
                 send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL);
diff --git a/ldap/servers/slapd/pagedresults.c b/ldap/servers/slapd/pagedresults.c
index 4458cfb..22dee6b 100644
--- a/ldap/servers/slapd/pagedresults.c
+++ b/ldap/servers/slapd/pagedresults.c
@@ -61,6 +61,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
     time_t ctime = current_time();
     int i;
     int maxreqs = config_get_maxsimplepaged_per_conn();
+    int is_local = 0;
 
     LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_parse_control_value\n");
     if ( NULL == conn || NULL == op || NULL == pagesize || NULL == index ) {
@@ -98,7 +99,7 @@ pagedresults_parse_control_value( Slapi_PBlock *pb,
         return LDAP_UNWILLING_TO_PERFORM;
     }
 
-    PR_Lock(conn->c_mutex);
+    slapd_conn_lock(conn, &is_local);
     /* the ber encoding is no longer needed */
     ber_free(ber, 1);
     if ( cookie.bv_len <= 0 ) {
@@ -204,7 +205,7 @@ bail:
             }
         }
     }
-    PR_Unlock(conn->c_mutex);
+    slapd_conn_unlock(conn, is_local);
 
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_parse_control_value: idx %d\n", *index);
@@ -294,6 +295,7 @@ int
 pagedresults_free_one( Connection *conn, Operation *op, int index )
 {
     int rc = -1;
+    int is_local = 0;
 
     if (!op_is_pagedresults(op)) {
         return 0; /* noop */
@@ -301,7 +303,7 @@ pagedresults_free_one( Connection *conn, Operation *op, int index )
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_free_one: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (conn->c_pagedresults.prl_count <= 0) {
             LDAPDebug2Args(LDAP_DEBUG_TRACE, "pagedresults_free_one: "
                            "conn=%d paged requests list count is %d\n",
@@ -312,7 +314,7 @@ pagedresults_free_one( Connection *conn, Operation *op, int index )
             conn->c_pagedresults.prl_count--;
             rc = 0;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
 
     LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_free_one: %d\n", rc);
@@ -361,14 +363,15 @@ Slapi_Backend *
 pagedresults_get_current_be(Connection *conn, int index)
 {
     Slapi_Backend *be = NULL;
+    int is_local = 0;
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_get_current_be: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             be = conn->c_pagedresults.prl_list[index].pr_current_be;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_get_current_be: %p\n", be);
@@ -379,15 +382,16 @@ int
 pagedresults_set_current_be(Connection *conn, Slapi_Backend *be, int index, int nolock)
 {
     int rc = -1;
+    int is_local = 0;
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_set_current_be: idx=%d\n", index);
     if (conn && (index > -1)) {
-        if (!nolock) PR_Lock(conn->c_mutex);
+        if (!nolock) slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             conn->c_pagedresults.prl_list[index].pr_current_be = be;
         }
         rc = 0;
-        if (!nolock) PR_Unlock(conn->c_mutex);
+        if (!nolock) slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_set_current_be: %d\n", rc);
@@ -398,6 +402,7 @@ void *
 pagedresults_get_search_result(Connection *conn, Operation *op, int locked, int index)
 {
     void *sr = NULL;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return sr; /* noop */
     }
@@ -406,13 +411,13 @@ pagedresults_get_search_result(Connection *conn, Operation *op, int locked, int
                    locked?"locked":"not locked", index);
     if (conn && (index > -1)) {
         if (!locked) {
-            PR_Lock(conn->c_mutex);
+            slapd_conn_lock(conn, &is_local);
         }
         if (index < conn->c_pagedresults.prl_maxlen) {
             sr = conn->c_pagedresults.prl_list[index].pr_search_result_set;
         }
         if (!locked) {
-            PR_Unlock(conn->c_mutex);
+            slapd_conn_unlock(conn, is_local);
         }
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
@@ -424,6 +429,7 @@ int
 pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, int locked, int index)
 {
     int rc = -1;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return 0; /* noop */
     }
@@ -431,7 +437,7 @@ pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, int lo
                    "--> pagedresults_set_search_result: idx=%d, sr=%p\n",
                    index, sr);
     if (conn && (index > -1)) {
-        if (!locked) PR_Lock(conn->c_mutex);
+        if (!locked) slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             PagedResults *prp = conn->c_pagedresults.prl_list + index;
             if (!(prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED) || !sr) {
@@ -440,7 +446,7 @@ pagedresults_set_search_result(Connection *conn, Operation *op, void *sr, int lo
             }
             rc = 0;
         }
-        if (!locked) PR_Unlock(conn->c_mutex);
+        if (!locked) slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_set_search_result: %d\n", rc);
@@ -451,17 +457,18 @@ int
 pagedresults_get_search_result_count(Connection *conn, Operation *op, int index)
 {
     int count = 0;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return count; /* noop */
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_get_search_result_count: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             count = conn->c_pagedresults.prl_list[index].pr_search_result_count;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_get_search_result_count: %d\n", count);
@@ -473,17 +480,18 @@ pagedresults_set_search_result_count(Connection *conn, Operation *op,
                                      int count, int index)
 {
     int rc = -1;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return rc; /* noop */
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_set_search_result_count: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             conn->c_pagedresults.prl_list[index].pr_search_result_count = count;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
         rc = 0;
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
@@ -497,6 +505,7 @@ pagedresults_get_search_result_set_size_estimate(Connection *conn,
                                                  int index)
 {
     int count = 0;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return count; /* noop */
     }
@@ -504,11 +513,11 @@ pagedresults_get_search_result_set_size_estimate(Connection *conn,
                   "--> pagedresults_get_search_result_set_size_estimate: "
                   "idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             count = conn->c_pagedresults.prl_list[index].pr_search_result_set_size_estimate;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_get_search_result_set_size_estimate: %d\n",
@@ -522,6 +531,7 @@ pagedresults_set_search_result_set_size_estimate(Connection *conn,
                                                  int count, int index)
 {
     int rc = -1;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return rc; /* noop */
     }
@@ -529,11 +539,11 @@ pagedresults_set_search_result_set_size_estimate(Connection *conn,
                   "--> pagedresults_set_search_result_set_size_estimate: "
                   "idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             conn->c_pagedresults.prl_list[index].pr_search_result_set_size_estimate = count;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
         rc = 0;
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
@@ -546,17 +556,18 @@ int
 pagedresults_get_with_sort(Connection *conn, Operation *op, int index)
 {
     int flags = 0;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return flags; /* noop */
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_get_with_sort: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             flags = conn->c_pagedresults.prl_list[index].pr_flags&CONN_FLAG_PAGEDRESULTS_WITH_SORT;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_get_with_sort: %p\n", flags);
@@ -568,20 +579,21 @@ pagedresults_set_with_sort(Connection *conn, Operation *op,
                            int flags, int index)
 {
     int rc = -1;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return rc; /* noop */
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_set_with_sort: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             if (flags & OP_FLAG_SERVER_SIDE_SORTING) {
                 conn->c_pagedresults.prl_list[index].pr_flags |=
                                                CONN_FLAG_PAGEDRESULTS_WITH_SORT;
             }
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
         rc = 0;
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_set_with_sort: %d\n", rc);
@@ -592,17 +604,18 @@ int
 pagedresults_get_unindexed(Connection *conn, Operation *op, int index)
 {
     int flags = 0;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return flags; /* noop */
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_get_unindexed: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             flags = conn->c_pagedresults.prl_list[index].pr_flags&CONN_FLAG_PAGEDRESULTS_UNINDEXED;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_get_unindexed: %p\n", flags);
@@ -613,18 +626,19 @@ int
 pagedresults_set_unindexed(Connection *conn, Operation *op, int index)
 {
     int rc = -1;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return rc; /* noop */
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_set_unindexed: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             conn->c_pagedresults.prl_list[index].pr_flags |=
                                                CONN_FLAG_PAGEDRESULTS_UNINDEXED;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
         rc = 0;
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
@@ -636,17 +650,18 @@ int
 pagedresults_get_sort_result_code(Connection *conn, Operation *op, int index)
 {
     int code = LDAP_OPERATIONS_ERROR;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return code; /* noop */
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_get_sort_result_code: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             code = conn->c_pagedresults.prl_list[index].pr_sort_result_code;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_get_sort_result_code: %d\n", code);
@@ -658,17 +673,18 @@ pagedresults_set_sort_result_code(Connection *conn, Operation *op,
                                   int code, int index)
 {
     int rc = -1;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return rc; /* noop */
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_set_sort_result_code: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             conn->c_pagedresults.prl_list[index].pr_sort_result_code = code;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
         rc = 0;
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
@@ -681,17 +697,18 @@ pagedresults_set_timelimit(Connection *conn, Operation *op,
                            time_t timelimit, int index)
 {
     int rc = -1;
+    int is_local = 0;
     if (!op_is_pagedresults(op)) {
         return rc; /* noop */
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_set_timelimit: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             conn->c_pagedresults.prl_list[index].pr_timelimit = timelimit;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
         rc = 0;
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_set_timelimit: %d\n", rc);
@@ -740,6 +757,7 @@ pagedresults_cleanup(Connection *conn, int needlock)
     int rc = 0;
     int i;
     PagedResults *prp = NULL;
+    int is_local = 0;
 
     LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_cleanup\n");
 
@@ -749,7 +767,7 @@ pagedresults_cleanup(Connection *conn, int needlock)
     }
 
     if (needlock) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
     }
     for (i = 0; conn->c_pagedresults.prl_list &&
                 i < conn->c_pagedresults.prl_maxlen; i++) {
@@ -767,7 +785,7 @@ pagedresults_cleanup(Connection *conn, int needlock)
     }
     conn->c_pagedresults.prl_count = 0;
     if (needlock) {
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_cleanup: %d\n", rc);
     return rc;
@@ -785,6 +803,7 @@ pagedresults_cleanup_all(Connection *conn, int needlock)
     int rc = 0;
     int i;
     PagedResults *prp = NULL;
+    int is_local = 0;
 
     LDAPDebug0Args(LDAP_DEBUG_TRACE, "--> pagedresults_cleanup_all\n");
 
@@ -794,7 +813,7 @@ pagedresults_cleanup_all(Connection *conn, int needlock)
     }
 
     if (needlock) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
     }
     for (i = 0; conn->c_pagedresults.prl_list &&
                 i < conn->c_pagedresults.prl_maxlen; i++) {
@@ -813,7 +832,7 @@ pagedresults_cleanup_all(Connection *conn, int needlock)
     conn->c_pagedresults.prl_maxlen = 0;
     conn->c_pagedresults.prl_count = 0;
     if (needlock) {
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE, "<-- pagedresults_cleanup_all: %d\n", rc);
     return rc;
@@ -829,10 +848,11 @@ int
 pagedresults_check_or_set_processing(Connection *conn, int index)
 {
     int ret = 0;
+    int is_local = 0;
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_check_or_set_processing\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             ret = (conn->c_pagedresults.prl_list[index].pr_flags &
                    CONN_FLAG_PAGEDRESULTS_PROCESSING);
@@ -840,7 +860,7 @@ pagedresults_check_or_set_processing(Connection *conn, int index)
             conn->c_pagedresults.prl_list[index].pr_flags |=
                                               CONN_FLAG_PAGEDRESULTS_PROCESSING;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_check_or_set_processing: %d\n", ret);
@@ -856,10 +876,11 @@ int
 pagedresults_reset_processing(Connection *conn, int index)
 {
     int ret = 0;
+    int is_local = 0;
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "--> pagedresults_reset_processing: idx=%d\n", index);
     if (conn && (index > -1)) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             ret = (conn->c_pagedresults.prl_list[index].pr_flags &
                    CONN_FLAG_PAGEDRESULTS_PROCESSING);
@@ -867,7 +888,7 @@ pagedresults_reset_processing(Connection *conn, int index)
             conn->c_pagedresults.prl_list[index].pr_flags &=
                                              ~CONN_FLAG_PAGEDRESULTS_PROCESSING;
         }
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_reset_processing: %d\n", ret);
@@ -978,12 +999,13 @@ void
 pagedresults_lock( Connection *conn, int index )
 {
     PagedResults *prp;
+    int is_local = 0;
     if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
         return;
     }
-    PR_Lock(conn->c_mutex);
+    slapd_conn_lock(conn, &is_local);
     prp = conn->c_pagedresults.prl_list + index;
-    PR_Unlock(conn->c_mutex);
+    slapd_conn_unlock(conn, is_local);
     if (prp->pr_mutex) {
         PR_Lock(prp->pr_mutex);
     }
@@ -994,12 +1016,13 @@ void
 pagedresults_unlock( Connection *conn, int index )
 {
     PagedResults *prp;
+    int is_local = 0;
     if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
         return;
     }
-    PR_Lock(conn->c_mutex);
+    slapd_conn_lock(conn, &is_local);
     prp = conn->c_pagedresults.prl_list + index;
-    PR_Unlock(conn->c_mutex);
+    slapd_conn_unlock(conn, is_local);
     if (prp->pr_mutex) {
         PR_Unlock(prp->pr_mutex);
     }
@@ -1010,15 +1033,16 @@ int
 pagedresults_is_abandoned_or_notavailable(Connection *conn, int locked, int index)
 {
     PagedResults *prp;
+    int is_local = 0;
     if (!conn || (index < 0) || (index >= conn->c_pagedresults.prl_maxlen)) {
         return 1; /* not abandoned, but do not want to proceed paged results op. */
     }
     if (!locked) {
-        PR_Lock(conn->c_mutex);
+        slapd_conn_lock(conn, &is_local);
     }
     prp = conn->c_pagedresults.prl_list + index;
     if (!locked) {
-        PR_Unlock(conn->c_mutex);
+        slapd_conn_unlock(conn, is_local);
     }
     return prp->pr_flags & CONN_FLAG_PAGEDRESULTS_ABANDONED;
 }
@@ -1030,6 +1054,7 @@ pagedresults_set_search_result_pb(Slapi_PBlock *pb, void *sr, int locked)
     Connection *conn = NULL;
     Operation *op = NULL;
     int index = -1;
+    int is_local = 0;
     if (!pb) {
         return 0;
     }
@@ -1042,12 +1067,12 @@ pagedresults_set_search_result_pb(Slapi_PBlock *pb, void *sr, int locked)
     LDAPDebug2Args(LDAP_DEBUG_TRACE,
                    "--> pagedresults_set_search_result_pb: idx=%d, sr=%p\n", index, sr);
     if (conn && (index > -1)) {
-        if (!locked) PR_Lock(conn->c_mutex);
+        if (!locked) slapd_conn_lock(conn, &is_local);
         if (index < conn->c_pagedresults.prl_maxlen) {
             conn->c_pagedresults.prl_list[index].pr_search_result_set = sr;
             rc = 0;
         }
-        if (!locked) PR_Unlock(conn->c_mutex);
+        if (!locked) slapd_conn_unlock(conn, is_local);
     }
     LDAPDebug1Arg(LDAP_DEBUG_TRACE,
                   "<-- pagedresults_set_search_result_pb: %d\n", rc);
diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c
index bf57a33..fddb4cd 100644
--- a/ldap/servers/slapd/pblock.c
+++ b/ldap/servers/slapd/pblock.c
@@ -117,8 +117,9 @@ if ( PBLOCK ->pb_plugin->plg_type != TYPE) return( -1 )
 int
 slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 {
-    char *authtype;
+	char *authtype;
 	Slapi_Backend		*be;
+	int is_local = 0;
 
 	PR_ASSERT( NULL != pblock );
 	PR_ASSERT( NULL != value );
@@ -174,10 +175,10 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 		          "Connection is NULL and hence cannot access SLAPI_CONN_DN \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		(*(char **)value) = (NULL == pblock->pb_conn->c_dn ? NULL :
 		    slapi_ch_strdup( pblock->pb_conn->c_dn ));
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_AUTHTYPE:/* deprecated */
 		if (pblock->pb_conn == NULL) {
@@ -185,9 +186,9 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 		          "Connection is NULL and hence cannot access SLAPI_CONN_AUTHTYPE \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
-                authtype = pblock->pb_conn->c_authtype;
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
+		authtype = pblock->pb_conn->c_authtype;
+		slapd_conn_unlock(pblock->pb_conn, is_local);
                 if (authtype == NULL) {
                     (*(char **)value) = NULL;
                 } else if (strcasecmp(authtype, SLAPD_AUTH_NONE) == 0) {
@@ -212,10 +213,10 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 		          "Connection is NULL and hence cannot access SLAPI_CONN_AUTHMETHOD \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		(*(char **)value) = pblock->pb_conn->c_authtype ?
                     slapi_ch_strdup(pblock->pb_conn->c_authtype) : NULL;
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_CLIENTNETADDR:
 		if (pblock->pb_conn == NULL)
@@ -223,14 +224,14 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 			memset( value, 0, sizeof( PRNetAddr ));
 			break;
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		if ( pblock->pb_conn->cin_addr == NULL ) {
 			memset( value, 0, sizeof( PRNetAddr ));
 		} else {
 			(*(PRNetAddr *)value) =
 			    *(pblock->pb_conn->cin_addr);
 		}
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_SERVERNETADDR:
 		if (pblock->pb_conn == NULL)
@@ -238,14 +239,14 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 			memset( value, 0, sizeof( PRNetAddr ));
 			break;
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		if ( pblock->pb_conn->cin_destaddr == NULL ) {
 			memset( value, 0, sizeof( PRNetAddr ));
 		} else {
 			(*(PRNetAddr *)value) =
 				*(pblock->pb_conn->cin_destaddr);
 		}
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_CLIENTIP:
 		if (pblock->pb_conn == NULL)
@@ -253,7 +254,7 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 			memset( value, 0, sizeof( struct in_addr ));
 			break;
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		if ( pblock->pb_conn->cin_addr == NULL ) {
 			memset( value, 0, sizeof( struct in_addr ));
 		} else {
@@ -268,7 +269,7 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 				memset( value, 0, sizeof( struct in_addr ));
 			}
 		}
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_SERVERIP:
 		if (pblock->pb_conn == NULL)
@@ -276,7 +277,7 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 			memset( value, 0, sizeof( struct in_addr ));
 			break;
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		if ( pblock->pb_conn->cin_destaddr == NULL ) {
 			memset( value, 0, sizeof( PRNetAddr ));
 		} else {
@@ -292,7 +293,7 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 			}
 
 		}
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_IS_REPLICATION_SESSION:
 		if (pblock->pb_conn == NULL) {
@@ -300,9 +301,9 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 		          "Connection is NULL and hence cannot access SLAPI_CONN_IS_REPLICATION_SESSION \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		(*(int *)value) = pblock->pb_conn->c_isreplication_session;
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_IS_SSL_SESSION:
 		if (pblock->pb_conn == NULL) {
@@ -310,9 +311,9 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 		          "Connection is NULL and hence cannot access SLAPI_CONN_IS_SSL_SESSION \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		(*(int *)value) = pblock->pb_conn->c_flags & CONN_FLAG_SSL;
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_SASL_SSF:
 		if (pblock->pb_conn == NULL) {
@@ -320,9 +321,9 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 			  "Connection is NULL and hence cannot access SLAPI_CONN_SASL_SSF \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		(*(int *)value) = pblock->pb_conn->c_sasl_ssf;
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_SSL_SSF:
 		if (pblock->pb_conn == NULL) {
@@ -330,9 +331,9 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 			  "Connection is NULL and hence cannot access SLAPI_CONN_SSL_SSF \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		(*(int *)value) = pblock->pb_conn->c_ssl_ssf;
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_LOCAL_SSF:
 		if (pblock->pb_conn == NULL) {
@@ -340,9 +341,9 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 			    "Connection is NULL and hence cannot access SLAPI_CONN_LOCAL_SSF \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		(*(int *)value) = pblock->pb_conn->c_local_ssf;
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_CERT:
 		if (pblock->pb_conn == NULL) {
@@ -1953,7 +1954,8 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value )
 int
 slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
 {
-    char *authtype;
+	char *authtype;
+	int is_local = 0;
 
 	PR_ASSERT( NULL != pblock );
 
@@ -2020,10 +2022,10 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
 		          "Connection is NULL and hence cannot access SLAPI_CONN_AUTHMETHOD \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
-                slapi_ch_free((void**)&pblock->pb_conn->c_authtype);
+		slapd_conn_lock(pblock->pb_conn, &is_local);
+		slapi_ch_free((void**)&pblock->pb_conn->c_authtype);
 		pblock->pb_conn->c_authtype = slapi_ch_strdup((char *) value);
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 	case SLAPI_CONN_IS_REPLICATION_SESSION:
 		if (pblock->pb_conn == NULL) {
@@ -2031,9 +2033,9 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value )
 		          "Connection is NULL and hence cannot access SLAPI_CONN_IS_REPLICATION_SESSION \n", 0, 0, 0 );
 			return (-1);
 		}
-		PR_Lock( pblock->pb_conn->c_mutex );
+		slapd_conn_lock(pblock->pb_conn, &is_local);
 		pblock->pb_conn->c_isreplication_session = *((int *) value);
-		PR_Unlock( pblock->pb_conn->c_mutex );
+		slapd_conn_unlock(pblock->pb_conn, is_local);
 		break;
 
 	/* stuff related to config file processing */
@@ -3570,8 +3572,9 @@ void
 bind_credentials_clear( Connection *conn, PRBool lock_conn,
 		PRBool clear_externalcreds )
 {
+    int is_local = 0;
     if ( lock_conn ) {
-        PR_Lock( conn->c_mutex );
+        slapd_conn_lock(conn, &is_local);
     }
 
     if ( conn->c_dn != NULL ) {		/* a non-anonymous bind has occurred */
@@ -3597,7 +3600,7 @@ bind_credentials_clear( Connection *conn, PRBool lock_conn,
     }
 
     if ( lock_conn ) {
-        PR_Unlock( conn->c_mutex );
+        slapd_conn_unlock(conn, is_local);
     }
 
 }
@@ -3653,10 +3656,11 @@ void
 bind_credentials_set( Connection *conn, char *authtype, char *normdn,
 		char *extauthtype, char *externaldn, CERTCertificate *clientcert, Slapi_Entry * bind_target_entry )
 {
-	PR_Lock( conn->c_mutex );
+	int is_local = 0;
+	slapd_conn_lock(conn, &is_local);
 	bind_credentials_set_nolock(conn, authtype, normdn,
 		extauthtype, externaldn, clientcert, bind_target_entry);
-	PR_Unlock( conn->c_mutex );
+	slapd_conn_unlock(conn, is_local);
 }
 
 void
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index f0a5257..cb45c38 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -807,6 +807,14 @@ int strarray2str( char **a, char *buf, size_t buflen, int include_quotes );
 int slapd_chown_if_not_owner(const char *filename, uid_t uid, gid_t gid);
 int slapd_comp_path(char *p0, char *p1);
 
+/*
+ * Lock / Unlock conn->c_mutex
+ * Lock conn->c_mutex only when it is not acquired in the thread.
+ * Unlock conn->c_mutex only when it is acquired in the same level.
+ */
+void slapd_conn_lock(Connection *conn, int *is_local);
+void slapd_conn_unlock(Connection *conn, int is_local);
+
 
 /*
  * modify.c
diff --git a/ldap/servers/slapd/psearch.c b/ldap/servers/slapd/psearch.c
index c9d23cf..ad89cea 100644
--- a/ldap/servers/slapd/psearch.c
+++ b/ldap/servers/slapd/psearch.c
@@ -272,14 +272,15 @@ ps_send_results( void *arg )
 	char **pbattrs = NULL;
 	int conn_acq_flag = 0;
 	Slapi_Connection *conn = NULL;
+	int is_local = 0;
     
     g_incr_active_threadcnt();
 
     /* need to acquire a reference to this connection so that it will not
        be released or cleaned up out from under us */
-    PR_Lock( ps->ps_pblock->pb_conn->c_mutex );
+    slapd_conn_lock(ps->ps_pblock->pb_conn, &is_local);
     conn_acq_flag = connection_acquire_nolock(ps->ps_pblock->pb_conn);    
-    PR_Unlock( ps->ps_pblock->pb_conn->c_mutex );
+    slapd_conn_unlock(ps->ps_pblock->pb_conn, is_local);
 
 	if (conn_acq_flag) {
 		slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search",
@@ -397,7 +398,7 @@ ps_send_results( void *arg )
 
     conn = ps->ps_pblock->pb_conn; /* save to release later - connection_remove_operation_ext will NULL the pb_conn */
     /* Clean up the connection structure */
-    PR_Lock( conn->c_mutex );
+    slapd_conn_lock(conn, &is_local);
 
 	slapi_log_error(SLAPI_LOG_CONNS, "Persistent Search",
 					"conn=%" NSPRIu64 " op=%d Releasing the connection and operation\n",
@@ -407,9 +408,9 @@ ps_send_results( void *arg )
 
     /* Decrement the connection refcnt */
     if (conn_acq_flag == 0) { /* we acquired it, so release it */
-	connection_release_nolock (conn);
+        connection_release_nolock (conn);
     }
-    PR_Unlock( conn->c_mutex );
+    slapd_conn_unlock(conn, is_local);
     conn = NULL;
 
     PR_DestroyLock ( ps->ps_lock );
diff --git a/ldap/servers/slapd/saslbind.c b/ldap/servers/slapd/saslbind.c
index b05c7ae..6b11774 100644
--- a/ldap/servers/slapd/saslbind.c
+++ b/ldap/servers/slapd/saslbind.c
@@ -653,6 +653,7 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
     const char *str;
     char *dupstr;
     sasl_conn_t *sasl_conn;
+    int is_local = 0;
 
     LDAPDebug( LDAP_DEBUG_TRACE, "=> ids_sasl_listmech\n", 0, 0, 0 );
 
@@ -667,7 +668,7 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
     if (sasl_conn == NULL) return ret;
 
     /* sasl library mechanisms are connection dependent */
-    PR_Lock(pb->pb_conn->c_mutex);
+    slapd_conn_lock(pb->pb_conn, &is_local);
     if (sasl_listmech(sasl_conn, 
                       NULL,     /* username */
                       "", ",", "",
@@ -680,7 +681,7 @@ char **ids_sasl_listmech(Slapi_PBlock *pb)
         charray_free(others);
         slapi_ch_free((void**)&dupstr);
     }
-    PR_Unlock(pb->pb_conn->c_mutex);
+    slapd_conn_unlock(pb->pb_conn, is_local);
 
     LDAPDebug( LDAP_DEBUG_TRACE, "<= ids_sasl_listmech\n", 0, 0, 0 );
 
@@ -757,19 +758,20 @@ void ids_sasl_check_bind(Slapi_PBlock *pb)
     Slapi_Entry *bind_target_entry = NULL, *referral = NULL;
     Slapi_Backend *be = NULL;
     char errorbuf[BUFSIZ];
+    int is_local = 0;
 
     LDAPDebug( LDAP_DEBUG_TRACE, "=> ids_sasl_check_bind\n", 0, 0, 0 );
 
     PR_ASSERT(pb);
     PR_ASSERT(pb->pb_conn);
 
-    PR_Lock(pb->pb_conn->c_mutex); /* BIG LOCK */
+    slapd_conn_lock(pb->pb_conn, &is_local); /* BIG LOCK */
     continuing = pb->pb_conn->c_flags & CONN_FLAG_SASL_CONTINUE;
     pb->pb_conn->c_flags &= ~CONN_FLAG_SASL_CONTINUE; /* reset flag */
 
     sasl_conn = (sasl_conn_t*)pb->pb_conn->c_sasl_conn;
     if (sasl_conn == NULL) {
-        PR_Unlock(pb->pb_conn->c_mutex);
+        slapd_conn_unlock(pb->pb_conn, is_local); /* BIG LOCK */
         send_ldap_result( pb, LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL,
                           "sasl library unavailable", 0, NULL );
         return;
@@ -850,7 +852,7 @@ void ids_sasl_check_bind(Slapi_PBlock *pb)
         if (sasl_conn == NULL) {
             send_ldap_result( pb, LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL,
                           "sasl library unavailable", 0, NULL );
-            PR_Unlock(pb->pb_conn->c_mutex); /* BIG LOCK */
+            slapd_conn_unlock(pb->pb_conn, is_local); /* BIG LOCK */
             return;
         }
     }
@@ -866,7 +868,7 @@ sasl_check_result:
         /* retrieve the authenticated username */
         if (sasl_getprop(sasl_conn, SASL_USERNAME,
                          (const void**)&username) != SASL_OK) {
-            PR_Unlock(pb->pb_conn->c_mutex); /* BIG LOCK */
+            slapd_conn_unlock(pb->pb_conn, is_local); /* BIG LOCK */
             send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
                              "could not obtain sasl username", 0, NULL);
             break;
@@ -887,7 +889,7 @@ sasl_check_result:
             }
         }
         if (dn == NULL) {
-            PR_Unlock(pb->pb_conn->c_mutex); /* BIG LOCK */
+            slapd_conn_unlock(pb->pb_conn, is_local); /* BIG LOCK */
             send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL,
                              "could not get auth dn from sasl", 0, NULL);
             break;
@@ -928,7 +930,7 @@ sasl_check_result:
                                     slapi_ch_strdup(normdn), 
                                     NULL, NULL, NULL, bind_target_entry);
 
-        PR_Unlock(pb->pb_conn->c_mutex); /* BIG LOCK */
+        slapd_conn_unlock(pb->pb_conn, is_local); /* BIG LOCK */
 
         if (plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_BIND_FN ) != 0){
             break;
@@ -1003,9 +1005,9 @@ sasl_check_result:
         /* see if we negotiated a security layer */
         if (*ssfp > 0) {
             /* Enable SASL I/O on the connection */
-            PR_Lock(pb->pb_conn->c_mutex);
+            slapd_conn_lock(pb->pb_conn, &is_local);
             connection_set_io_layer_cb(pb->pb_conn, sasl_io_enable, NULL, NULL);
-            PR_Unlock(pb->pb_conn->c_mutex);
+            slapd_conn_unlock(pb->pb_conn, is_local);
         }
 
         /* send successful result */
@@ -1018,7 +1020,7 @@ sasl_check_result:
 
     case SASL_CONTINUE:         /* another step needed */
         pb->pb_conn->c_flags |= CONN_FLAG_SASL_CONTINUE;
-        PR_Unlock(pb->pb_conn->c_mutex); /* BIG LOCK */
+        slapd_conn_unlock(pb->pb_conn, is_local); /* BIG LOCK */
 
         if (plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_BIND_FN ) != 0){
             break;
@@ -1040,7 +1042,7 @@ sasl_check_result:
 
     case SASL_NOMECH:
 
-        PR_Unlock(pb->pb_conn->c_mutex); /* BIG LOCK */
+        slapd_conn_unlock(pb->pb_conn, is_local); /* BIG LOCK */
         send_ldap_result(pb, LDAP_AUTH_METHOD_NOT_SUPPORTED, NULL,
                          "sasl mechanism not supported", 0, NULL);
         break;
@@ -1048,7 +1050,7 @@ sasl_check_result:
     default:                    /* other error */
         errstr = sasl_errdetail(sasl_conn);
 
-        PR_Unlock(pb->pb_conn->c_mutex); /* BIG LOCK */
+        slapd_conn_unlock(pb->pb_conn, is_local); /* BIG LOCK */
         send_ldap_result(pb, LDAP_INVALID_CREDENTIALS, NULL,
                          (char*)errstr, 0, NULL);
         break;
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index d2b076b..977e039 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -5556,11 +5556,16 @@ int slapi_td_plugin_lock_init(void);
 int slapi_td_get_plugin_locked(void);
 int slapi_td_set_plugin_locked(void);
 int slapi_td_set_plugin_unlocked(void);
+int slapi_td_conn_lock_init(void);
+int slapi_td_get_conn_locked(void);
+int slapi_td_set_conn_locked(void);
+int slapi_td_set_conn_unlocked(void);
 
 
 /*  Thread Local Storage Index Types  */
 #define SLAPI_TD_REQUESTOR_DN		1
 #define SLAPI_TD_PLUGIN_LIST_LOCK		2
+#define SLAPI_TD_CONN_LOCK			3
 
 /*
  * routines for dealing with controls
diff --git a/ldap/servers/slapd/start_tls_extop.c b/ldap/servers/slapd/start_tls_extop.c
index 69b8607..d8857ef 100644
--- a/ldap/servers/slapd/start_tls_extop.c
+++ b/ldap/servers/slapd/start_tls_extop.c
@@ -129,6 +129,7 @@ start_tls( Slapi_PBlock *pb )
 	Connection      *conn;
 	int             ldaprc = LDAP_SUCCESS;
 	char            *ldapmsg = NULL;
+	int is_local = 0;
 
 	/* Get the pb ready for sending Start TLS Extended Responses back to the client. 
 	 * The only requirement is to set the LDAP OID of the extended response to the START_TLS_OID. */
@@ -172,7 +173,7 @@ start_tls( Slapi_PBlock *pb )
 	/* At least we know that the request was indeed an Start TLS one. */
 
 	conn = pb->pb_conn;
-	PR_Lock( conn->c_mutex );
+	slapd_conn_lock(conn, &is_local);
 	/* cannot call slapi_send_ldap_result with mutex locked - will deadlock if ber_flush returns error */
 	if ( conn->c_prfd == (PRFileDesc *) NULL ) {
 		slapi_log_error( SLAPI_LOG_PLUGIN, "start_tls",
@@ -246,10 +247,10 @@ start_tls( Slapi_PBlock *pb )
 	 * we send a success response back to the client. */
 	ldapmsg = "Start TLS request accepted.Server willing to negotiate SSL.";
 unlock_and_return:
-	PR_Unlock( conn->c_mutex );
+	slapd_conn_unlock(conn, is_local);
 	slapi_send_ldap_result( pb, ldaprc, NULL, ldapmsg, 0, NULL );
 
-	return( SLAPI_PLUGIN_EXTENDED_SENT_RESULT );	
+	return( SLAPI_PLUGIN_EXTENDED_SENT_RESULT );
 
 }/* start_tls */
 
@@ -270,6 +271,7 @@ start_tls_graceful_closure( Connection *c, Slapi_PBlock * pb, int is_initiator )
 	struct slapdplugin  *plugin;
 	int secure = 0;
 	PRFileDesc *ssl_fd;
+	int is_local = 0;
 
 	if ( pblock == NULL ) {
 	       pblock = slapi_pblock_new();
@@ -312,7 +314,7 @@ start_tls_graceful_closure( Connection *c, Slapi_PBlock * pb, int is_initiator )
 	   */
 	}
 
-	PR_Lock( c->c_mutex );
+	slapd_conn_lock(c, &is_local);
 
 	/* "Unimport" the socket from SSL, i.e. get rid of the upper layer of the 
 	 * file descriptor stack, which represents SSL. 
@@ -342,7 +344,7 @@ start_tls_graceful_closure( Connection *c, Slapi_PBlock * pb, int is_initiator )
 
 	bind_credentials_clear( c, PR_FALSE, PR_TRUE );
 
-	PR_Unlock( c->c_mutex );
+	slapd_conn_unlock(c, is_local);
 
 	return ( SLAPI_PLUGIN_EXTENDED_SENT_RESULT );
 }    
diff --git a/ldap/servers/slapd/thread_data.c b/ldap/servers/slapd/thread_data.c
index 46a0c20..98f2285 100644
--- a/ldap/servers/slapd/thread_data.c
+++ b/ldap/servers/slapd/thread_data.c
@@ -19,6 +19,7 @@ void td_dn_destructor(void *priv);
  */
 static PRUintn td_requestor_dn;  /* TD_REQUESTOR_DN */
 static PRUintn td_plugin_list; /* SLAPI_TD_PLUGIN_LIST_LOCK - integer set to 1 or zero */
+static PRUintn td_conn_locked; /* SLAPI_TD_CONN_LOCK - integer set to 1 or zero */
 
 /*
  *   Index types defined in slapi-plugin.h
@@ -56,6 +57,11 @@ slapi_td_init(int indexType)
                 return PR_FAILURE;
             }
             break;
+        case SLAPI_TD_CONN_LOCK:
+        	if(PR_NewThreadPrivateIndex(&td_conn_locked, NULL) == PR_FAILURE){
+                return PR_FAILURE;
+            }
+            break;
 
         default:
             return PR_FAILURE;
@@ -89,6 +95,15 @@ slapi_td_set_val(int indexType, void *value)
                 return PR_FAILURE;
             }
             break;
+        case SLAPI_TD_CONN_LOCK:
+            if(td_conn_locked){
+                if(PR_SetThreadPrivate(td_conn_locked, value) == PR_FAILURE){
+                    return PR_FAILURE;
+                }
+            } else {
+                return PR_FAILURE;
+            }
+            break;
         default:
             return PR_FAILURE;
     }
@@ -117,6 +132,13 @@ slapi_td_get_val(int indexType, void **value)
                 *value = 0;
             }
             break;
+        case SLAPI_TD_CONN_LOCK:
+            if(td_conn_locked){
+                *value = PR_GetThreadPrivate(td_conn_locked);
+            } else {
+                *value = 0;
+            }
+            break;
         default:
             *value = NULL;
             return;
@@ -201,6 +223,52 @@ slapi_td_get_dn(char **value)
 }
 
 
+/* connection locking */
+int
+slapi_td_conn_lock_init()
+{
+    if(slapi_td_init(SLAPI_TD_CONN_LOCK) == PR_FAILURE){
+        return PR_FAILURE;
+    }
+
+    return PR_SUCCESS;
+}
+
+int
+slapi_td_set_conn_locked()
+{
+    int val = 67890;
+
+    if(slapi_td_set_val(SLAPI_TD_CONN_LOCK, (void *)&val) == PR_FAILURE){
+        return PR_FAILURE;
+    }
+
+    return PR_SUCCESS;
+}
+
+int
+slapi_td_set_conn_unlocked()
+{
+    if(slapi_td_set_val(SLAPI_TD_CONN_LOCK, NULL) == PR_FAILURE){
+        return PR_FAILURE;
+    }
+
+    return PR_SUCCESS;
+}
+
+int
+slapi_td_get_conn_locked()
+{
+    int *value = 0;
+
+    slapi_td_get_val(SLAPI_TD_CONN_LOCK, (void **)&value);
+    if(value){
+        return 1;
+    } else{
+        return 0;
+    }
+}
+
 /*
  *   Destructor Functions
  */
diff --git a/ldap/servers/slapd/unbind.c b/ldap/servers/slapd/unbind.c
index 9b6a70f..d75fcee 100644
--- a/ldap/servers/slapd/unbind.c
+++ b/ldap/servers/slapd/unbind.c
@@ -38,6 +38,7 @@ do_unbind( Slapi_PBlock *pb )
 	BerElement	*ber;
 	int		err;
 	int ignore_criticality = 1;
+	int is_local = 0;
 
 	LDAPDebug( LDAP_DEBUG_TRACE, "do_unbind\n", 0, 0, 0 );
 
@@ -73,9 +74,9 @@ do_unbind( Slapi_PBlock *pb )
 	}
 
 	/* target spec is used to decide which plugins are applicable for the operation */
-	PR_Lock( pb->pb_conn->c_mutex );
+	slapd_conn_lock(pb->pb_conn, &is_local);
 	operation_set_target_spec_str (operation, pb->pb_conn->c_dn);
-	PR_Unlock( pb->pb_conn->c_mutex );
+	slapd_conn_unlock(pb->pb_conn, is_local);
 
 	/* ONREPL - plugins should be called and passed bind dn and, possibly, other data */
 
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
index dbe69f0..9f4835d 100644
--- a/ldap/servers/slapd/util.c
+++ b/ldap/servers/slapd/util.c
@@ -1432,3 +1432,38 @@ slapi_uniqueIDRdnSize()
 	}
 	return util_uniqueidlen;
 }
+
+/*
+ * Lock / Unlock conn->c_mutex
+ * Lock conn->c_mutex only when it is not acquired in the thread.
+ * Unlock conn->c_mutex only when it is acquired in the same level.
+ */
+void
+slapd_conn_lock(Connection *conn, int *is_local)
+{
+    if (!is_local) {
+        LDAPDebug0Args(LDAP_DEBUG_ANY, "slapd_conn_lock: NULL is_local\n");
+        PR_ASSERT(0);
+    }
+    if (slapi_td_get_conn_locked()) {
+        /*
+         * c_mutex is already locked in the thread.
+         * safe to step forward.
+         */
+        *is_local = 0;
+    } else {
+        PR_Lock(conn->c_mutex);
+        slapi_td_set_conn_locked();
+        *is_local = 1;
+    }
+}
+
+void
+slapd_conn_unlock(Connection *conn, int is_local)
+{
+    if (is_local && slapi_td_get_conn_locked()) {
+        PR_Unlock(conn->c_mutex);
+        slapi_td_set_conn_unlocked();
+    }
+}
+
-- 
2.4.3

