aboutsummaryrefslogtreecommitdiff
path: root/openssl/crypto/bn/bn_mont.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2014-06-26 09:35:54 +0200
committermarha <marha@users.sourceforge.net>2014-06-26 09:35:54 +0200
commitd47db8d4713de42ccca071c9e8401fc7a213ed49 (patch)
tree7189b3c025315c514ae9d2835810b94d0e4e0e01 /openssl/crypto/bn/bn_mont.c
parent880395e8c3f451bf34b96da76fcee133b356e966 (diff)
parentc30d5eefc96925b4bef781806c7a0114eca1b8e0 (diff)
downloadvcxsrv-d47db8d4713de42ccca071c9e8401fc7a213ed49.tar.gz
vcxsrv-d47db8d4713de42ccca071c9e8401fc7a213ed49.tar.bz2
vcxsrv-d47db8d4713de42ccca071c9e8401fc7a213ed49.zip
Merge remote-tracking branch 'origin/released'
* origin/released: Opdated to openssl-1.0.1h xkeyboard-config fontconfig libX11 libxcb xcb-proto mesa xserver git update 26 June 2014 Conflicts: openssl/Makefile
Diffstat (limited to 'openssl/crypto/bn/bn_mont.c')
-rw-r--r--openssl/crypto/bn/bn_mont.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/openssl/crypto/bn/bn_mont.c b/openssl/crypto/bn/bn_mont.c
index 427b5cf4d..ee8532c7d 100644
--- a/openssl/crypto/bn/bn_mont.c
+++ b/openssl/crypto/bn/bn_mont.c
@@ -478,32 +478,38 @@ 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);
- if (!*pmont)
+ 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))
{
- CRYPTO_r_unlock(lock);
- CRYPTO_w_lock(lock);
- got_write_lock = 1;
+ BN_MONT_CTX_free(ret);
+ return NULL;
+ }
- if (!*pmont)
- {
- ret = BN_MONT_CTX_new();
- if (ret && !BN_MONT_CTX_set(ret, mod, ctx))
- BN_MONT_CTX_free(ret);
- else
- *pmont = ret;
- }
+ /* The locked compare-and-set, after the local work is done. */
+ CRYPTO_w_lock(lock);
+ if (*pmont)
+ {
+ BN_MONT_CTX_free(ret);
+ ret = *pmont;
}
-
- ret = *pmont;
-
- if (got_write_lock)
- CRYPTO_w_unlock(lock);
else
- CRYPTO_r_unlock(lock);
-
+ *pmont = ret;
+ CRYPTO_w_unlock(lock);
return ret;
}