mirror of
https://github.com/openssl/openssl.git
synced 2024-11-21 01:15:20 +08:00
Optimise OPENSSL_init_crypto
If everything has already been initialised we can check this with a single test at the beginning of OPENSSL_init_crypto() and therefore reduce the amount of time spent in this function. Since this is called via very many codepaths this should have significant performance benefits. Partially fixes #13725 and #13578 Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> (Merged from https://github.com/openssl/openssl/pull/13733)
This commit is contained in:
parent
d5e742de65
commit
db6bcc81ab
@ -34,6 +34,7 @@
|
|||||||
#include <openssl/trace.h>
|
#include <openssl/trace.h>
|
||||||
|
|
||||||
static int stopped = 0;
|
static int stopped = 0;
|
||||||
|
static uint64_t optsdone = 0;
|
||||||
|
|
||||||
typedef struct ossl_init_stop_st OPENSSL_INIT_STOP;
|
typedef struct ossl_init_stop_st OPENSSL_INIT_STOP;
|
||||||
struct ossl_init_stop_st {
|
struct ossl_init_stop_st {
|
||||||
@ -464,6 +465,28 @@ void OPENSSL_cleanup(void)
|
|||||||
*/
|
*/
|
||||||
int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
|
int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
|
||||||
{
|
{
|
||||||
|
uint64_t tmp;
|
||||||
|
int aloaddone = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We ignore failures from this function. It is probably because we are
|
||||||
|
* on a platform that doesn't support lockless atomic loads (we may not
|
||||||
|
* have created init_lock yet so we can't use it). This is just an
|
||||||
|
* optimisation to skip the full checks in this function if we don't need
|
||||||
|
* to, so we carry on regardless in the event of failure.
|
||||||
|
*
|
||||||
|
* There could be a race here with other threads, so that optsdone has not
|
||||||
|
* been updated yet, even though the options have in fact been initialised.
|
||||||
|
* This doesn't matter - it just means we will run the full function
|
||||||
|
* unnecessarily - but all the critical code is contained in RUN_ONCE
|
||||||
|
* functions anyway so we are safe.
|
||||||
|
*/
|
||||||
|
if (CRYPTO_atomic_load(&optsdone, &tmp, NULL)) {
|
||||||
|
if ((tmp & opts) == opts)
|
||||||
|
return 1;
|
||||||
|
aloaddone = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO(3.0): This function needs looking at with a view to moving most/all
|
* TODO(3.0): This function needs looking at with a view to moving most/all
|
||||||
* of this into OSSL_LIB_CTX.
|
* of this into OSSL_LIB_CTX.
|
||||||
@ -492,6 +515,18 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
|
|||||||
if (opts & OPENSSL_INIT_BASE_ONLY)
|
if (opts & OPENSSL_INIT_BASE_ONLY)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* init_lock should definitely be set up now, so we can now repeat the
|
||||||
|
* same check from above but be sure that it will work even on platforms
|
||||||
|
* without lockless CRYPTO_atomic_load
|
||||||
|
*/
|
||||||
|
if (!aloaddone) {
|
||||||
|
if (!CRYPTO_atomic_load(&optsdone, &tmp, init_lock))
|
||||||
|
return 0;
|
||||||
|
if ((tmp & opts) == opts)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now we don't always set up exit handlers, the INIT_BASE_ONLY calls
|
* Now we don't always set up exit handlers, the INIT_BASE_ONLY calls
|
||||||
* should not have the side-effect of setting up exit handlers, and
|
* should not have the side-effect of setting up exit handlers, and
|
||||||
@ -614,6 +649,9 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
|
|||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!CRYPTO_atomic_or(&optsdone, opts, &tmp, init_lock))
|
||||||
|
return 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user