diff options
Diffstat (limited to 'app/openssl/crypto/bn/bn_mont.c')
-rw-r--r-- | app/openssl/crypto/bn/bn_mont.c | 46 |
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; } |