Don't hold CRYPTO_LOCK_RSA during time-consuming operations.
diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c
index f92a302..35db9e5 100644
--- a/crypto/rsa/rsa_eay.c
+++ b/crypto/rsa/rsa_eay.c
@@ -141,26 +141,28 @@
 	
 	if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
 		{
-		CRYPTO_w_lock(CRYPTO_LOCK_RSA);
-		if (rsa->_method_mod_n == NULL)
+		BN_MONT_CTX* bn_mont_ctx;
+		if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
+			goto err;
+		if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
 			{
-			BN_MONT_CTX* bn_mont_ctx;
-			if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
-				{
-				CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
-				goto err;
-				}
-			if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
-				{
-				BN_MONT_CTX_free(bn_mont_ctx);
-				CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
-				goto err;
-				}
-			rsa->_method_mod_n = bn_mont_ctx;
+			BN_MONT_CTX_free(bn_mont_ctx);
+			goto err;
 			}
-		CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+		if (rsa->_method_mod_n == NULL) /* other thread may have finished first */
+			{
+			CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+			if (rsa->_method_mod_n == NULL)
+				{
+				rsa->_method_mod_n = bn_mont_ctx;
+				bn_mont_ctx = NULL;
+				}
+			CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+			}
+		if (bn_mont_ctx)
+			BN_MONT_CTX_free(bn_mont_ctx);
 		}
-
+		
 	if (!meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
 		rsa->_method_mod_n)) goto err;
 
@@ -393,26 +395,28 @@
 	/* do the decrypt */
 	if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
 		{
-		CRYPTO_w_lock(CRYPTO_LOCK_RSA);
-		if (rsa->_method_mod_n == NULL)
+		BN_MONT_CTX* bn_mont_ctx;
+		if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
+			goto err;
+		if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
 			{
-			BN_MONT_CTX* bn_mont_ctx;
-			if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
-				{
-				CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
-				goto err;
-				}
-			if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
-				{
-				BN_MONT_CTX_free(bn_mont_ctx);
-				CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
-				goto err;
-				}
-			rsa->_method_mod_n = bn_mont_ctx;
+			BN_MONT_CTX_free(bn_mont_ctx);
+			goto err;
 			}
-		CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+		if (rsa->_method_mod_n == NULL) /* other thread may have finished first */
+			{
+			CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+			if (rsa->_method_mod_n == NULL)
+				{
+				rsa->_method_mod_n = bn_mont_ctx;
+				bn_mont_ctx = NULL;
+				}
+			CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+			}
+		if (bn_mont_ctx)
+			BN_MONT_CTX_free(bn_mont_ctx);
 		}
-
+		
 	if (!meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
 		rsa->_method_mod_n)) goto err;
 
@@ -462,48 +466,53 @@
 		{
 		if (rsa->_method_mod_p == NULL)
 			{
-			CRYPTO_w_lock(CRYPTO_LOCK_RSA);
-			if (rsa->_method_mod_p == NULL)
+			BN_MONT_CTX* bn_mont_ctx;
+			if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
+				goto err;
+			if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->p,ctx))
 				{
-				BN_MONT_CTX* bn_mont_ctx;
-				if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
-					{
-					CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
-					goto err;
-					}
-				if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->p,ctx))
-					{
-					BN_MONT_CTX_free(bn_mont_ctx);
-					CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
-					goto err;
-					}
-				rsa->_method_mod_p = bn_mont_ctx;
+				BN_MONT_CTX_free(bn_mont_ctx);
+				goto err;
 				}
+			if (rsa->_method_mod_p == NULL) /* other thread may have finished first */
+				{
+				CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+				if (rsa->_method_mod_p == NULL)
+					{
+					rsa->_method_mod_p = bn_mont_ctx;
+					bn_mont_ctx = NULL;
+					}
 				CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+				}
+			if (bn_mont_ctx)
+				BN_MONT_CTX_free(bn_mont_ctx);
 			}
+
 		if (rsa->_method_mod_q == NULL)
 			{
-			CRYPTO_w_lock(CRYPTO_LOCK_RSA);
-			if (rsa->_method_mod_q == NULL)
+			BN_MONT_CTX* bn_mont_ctx;
+			if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
+				goto err;
+			if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->q,ctx))
 				{
-				BN_MONT_CTX* bn_mont_ctx;
-				if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
-					{
-					CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+				BN_MONT_CTX_free(bn_mont_ctx);
 					goto err;
-					}
-				if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->q,ctx))
-					{
-					BN_MONT_CTX_free(bn_mont_ctx);
-					CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
-					goto err;
-					}
-				rsa->_method_mod_q = bn_mont_ctx;
 				}
-			CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+			if (rsa->_method_mod_q == NULL) /* other thread may have finished first */
+				{
+				CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+				if (rsa->_method_mod_q == NULL)
+					{
+					rsa->_method_mod_q = bn_mont_ctx;
+					bn_mont_ctx = NULL;
+					}
+				CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+				}
+			if (bn_mont_ctx)
+				BN_MONT_CTX_free(bn_mont_ctx);
 			}
 		}
-
+		
 	if (!BN_mod(&r1,I,rsa->q,ctx)) goto err;
 	if (!meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx,
 		rsa->_method_mod_q)) goto err;