summaryrefslogtreecommitdiff
path: root/app/openssl/crypto/bn/bn_mont.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/openssl/crypto/bn/bn_mont.c')
-rw-r--r--app/openssl/crypto/bn/bn_mont.c46
1 files changed, 20 insertions, 26 deletions
diff --git a/app/openssl/crypto/bn/bn_mont.c b/app/openssl/crypto/bn/bn_mont.c
index ee8532c7..427b5cf4 100644
--- a/app/openssl/crypto/bn/bn_mont.c
+++ b/app/openssl/crypto/bn/bn_mont.c
@@ -478,38 +478,32 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
const BIGNUM *mod, BN_CTX *ctx)
{
+ int got_write_lock = 0;
BN_MONT_CTX *ret;
CRYPTO_r_lock(lock);
- ret = *pmont;
- CRYPTO_r_unlock(lock);
- if (ret)
- return ret;
-
- /* We don't want to serialise globally while doing our lazy-init math in
- * BN_MONT_CTX_set. That punishes threads that are doing independent
- * things. Instead, punish the case where more than one thread tries to
- * lazy-init the same 'pmont', by having each do the lazy-init math work
- * independently and only use the one from the thread that wins the race
- * (the losers throw away the work they've done). */
- ret = BN_MONT_CTX_new();
- if (!ret)
- return NULL;
- if (!BN_MONT_CTX_set(ret, mod, ctx))
+ if (!*pmont)
{
- BN_MONT_CTX_free(ret);
- return NULL;
- }
+ CRYPTO_r_unlock(lock);
+ CRYPTO_w_lock(lock);
+ got_write_lock = 1;
- /* The locked compare-and-set, after the local work is done. */
- CRYPTO_w_lock(lock);
- if (*pmont)
- {
- BN_MONT_CTX_free(ret);
- ret = *pmont;
+ if (!*pmont)
+ {
+ ret = BN_MONT_CTX_new();
+ if (ret && !BN_MONT_CTX_set(ret, mod, ctx))
+ BN_MONT_CTX_free(ret);
+ else
+ *pmont = ret;
+ }
}
+
+ ret = *pmont;
+
+ if (got_write_lock)
+ CRYPTO_w_unlock(lock);
else
- *pmont = ret;
- CRYPTO_w_unlock(lock);
+ CRYPTO_r_unlock(lock);
+
return ret;
}