Add exemplar use case for rcu locks
To demonstrate the use of RCU locks, convert CONF_MOD api to using rcu rather than RW locks Reviewed-by: Hugo Landau <hlandau@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/22729)
This commit is contained in:
parent
d0e1a0ae70
commit
504e72fc1a
@ -11,6 +11,7 @@
|
|||||||
#define OPENSSL_SUPPRESS_DEPRECATED
|
#define OPENSSL_SUPPRESS_DEPRECATED
|
||||||
|
|
||||||
#include "internal/cryptlib.h"
|
#include "internal/cryptlib.h"
|
||||||
|
#include "internal/rcu.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
@ -63,7 +64,7 @@ struct conf_imodule_st {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static CRYPTO_ONCE init_module_list_lock = CRYPTO_ONCE_STATIC_INIT;
|
static CRYPTO_ONCE init_module_list_lock = CRYPTO_ONCE_STATIC_INIT;
|
||||||
static CRYPTO_RWLOCK *module_list_lock = NULL;
|
static CRYPTO_RCU_LOCK *module_list_lock = NULL;
|
||||||
static STACK_OF(CONF_MODULE) *supported_modules = NULL; /* protected by lock */
|
static STACK_OF(CONF_MODULE) *supported_modules = NULL; /* protected by lock */
|
||||||
static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; /* protected by lock */
|
static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; /* protected by lock */
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ static int conf_modules_finish_int(void);
|
|||||||
|
|
||||||
static void module_lists_free(void)
|
static void module_lists_free(void)
|
||||||
{
|
{
|
||||||
CRYPTO_THREAD_lock_free(module_list_lock);
|
ossl_rcu_lock_free(module_list_lock);
|
||||||
module_list_lock = NULL;
|
module_list_lock = NULL;
|
||||||
|
|
||||||
sk_CONF_MODULE_free(supported_modules);
|
sk_CONF_MODULE_free(supported_modules);
|
||||||
@ -98,7 +99,7 @@ static void module_lists_free(void)
|
|||||||
|
|
||||||
DEFINE_RUN_ONCE_STATIC(do_init_module_list_lock)
|
DEFINE_RUN_ONCE_STATIC(do_init_module_list_lock)
|
||||||
{
|
{
|
||||||
module_list_lock = CRYPTO_THREAD_lock_new();
|
module_list_lock = ossl_rcu_lock_new(1);
|
||||||
if (module_list_lock == NULL) {
|
if (module_list_lock == NULL) {
|
||||||
ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
|
ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
|
||||||
return 0;
|
return 0;
|
||||||
@ -327,17 +328,24 @@ static CONF_MODULE *module_add(DSO *dso, const char *name,
|
|||||||
conf_init_func *ifunc, conf_finish_func *ffunc)
|
conf_init_func *ifunc, conf_finish_func *ffunc)
|
||||||
{
|
{
|
||||||
CONF_MODULE *tmod = NULL;
|
CONF_MODULE *tmod = NULL;
|
||||||
|
STACK_OF(CONF_MODULE) *old_modules;
|
||||||
|
STACK_OF(CONF_MODULE) *new_modules;
|
||||||
|
|
||||||
if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
|
if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!CRYPTO_THREAD_write_lock(module_list_lock))
|
ossl_rcu_write_lock(module_list_lock);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (supported_modules == NULL)
|
old_modules = ossl_rcu_deref(&supported_modules);
|
||||||
supported_modules = sk_CONF_MODULE_new_null();
|
|
||||||
if (supported_modules == NULL)
|
if (old_modules == NULL)
|
||||||
|
new_modules = sk_CONF_MODULE_new_null();
|
||||||
|
else
|
||||||
|
new_modules = sk_CONF_MODULE_dup(old_modules);
|
||||||
|
|
||||||
|
if (new_modules == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL)
|
if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -348,14 +356,18 @@ static CONF_MODULE *module_add(DSO *dso, const char *name,
|
|||||||
if (tmod->name == NULL)
|
if (tmod->name == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!sk_CONF_MODULE_push(supported_modules, tmod))
|
if (!sk_CONF_MODULE_push(new_modules, tmod))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
CRYPTO_THREAD_unlock(module_list_lock);
|
ossl_rcu_assign_ptr(&supported_modules, &new_modules);
|
||||||
|
ossl_rcu_write_unlock(module_list_lock);
|
||||||
|
ossl_synchronize_rcu(module_list_lock);
|
||||||
|
|
||||||
|
sk_CONF_MODULE_free(old_modules);
|
||||||
return tmod;
|
return tmod;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
CRYPTO_THREAD_unlock(module_list_lock);
|
ossl_rcu_write_unlock(module_list_lock);
|
||||||
if (tmod != NULL) {
|
if (tmod != NULL) {
|
||||||
OPENSSL_free(tmod->name);
|
OPENSSL_free(tmod->name);
|
||||||
OPENSSL_free(tmod);
|
OPENSSL_free(tmod);
|
||||||
@ -374,6 +386,8 @@ static CONF_MODULE *module_find(const char *name)
|
|||||||
CONF_MODULE *tmod;
|
CONF_MODULE *tmod;
|
||||||
int i, nchar;
|
int i, nchar;
|
||||||
char *p;
|
char *p;
|
||||||
|
STACK_OF(CONF_MODULE) *mods;
|
||||||
|
|
||||||
p = strrchr(name, '.');
|
p = strrchr(name, '.');
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
@ -384,18 +398,18 @@ static CONF_MODULE *module_find(const char *name)
|
|||||||
if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
|
if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!CRYPTO_THREAD_read_lock(module_list_lock))
|
ossl_rcu_read_lock(module_list_lock);
|
||||||
return NULL;
|
mods = ossl_rcu_deref(&supported_modules);
|
||||||
|
|
||||||
for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) {
|
for (i = 0; i < sk_CONF_MODULE_num(mods); i++) {
|
||||||
tmod = sk_CONF_MODULE_value(supported_modules, i);
|
tmod = sk_CONF_MODULE_value(mods, i);
|
||||||
if (strncmp(tmod->name, name, nchar) == 0) {
|
if (strncmp(tmod->name, name, nchar) == 0) {
|
||||||
CRYPTO_THREAD_unlock(module_list_lock);
|
ossl_rcu_read_unlock(module_list_lock);
|
||||||
return tmod;
|
return tmod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CRYPTO_THREAD_unlock(module_list_lock);
|
ossl_rcu_read_unlock(module_list_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,6 +420,8 @@ static int module_init(CONF_MODULE *pmod, const char *name, const char *value,
|
|||||||
int ret = 1;
|
int ret = 1;
|
||||||
int init_called = 0;
|
int init_called = 0;
|
||||||
CONF_IMODULE *imod = NULL;
|
CONF_IMODULE *imod = NULL;
|
||||||
|
STACK_OF(CONF_IMODULE) *old_modules;
|
||||||
|
STACK_OF(CONF_IMODULE) *new_modules;
|
||||||
|
|
||||||
/* Otherwise add initialized module to list */
|
/* Otherwise add initialized module to list */
|
||||||
imod = OPENSSL_malloc(sizeof(*imod));
|
imod = OPENSSL_malloc(sizeof(*imod));
|
||||||
@ -432,27 +448,33 @@ static int module_init(CONF_MODULE *pmod, const char *name, const char *value,
|
|||||||
if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
|
if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!CRYPTO_THREAD_write_lock(module_list_lock))
|
ossl_rcu_write_lock(module_list_lock);
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (initialized_modules == NULL) {
|
old_modules = ossl_rcu_deref(&initialized_modules);
|
||||||
initialized_modules = sk_CONF_IMODULE_new_null();
|
|
||||||
if (initialized_modules == NULL) {
|
if (old_modules == NULL)
|
||||||
CRYPTO_THREAD_unlock(module_list_lock);
|
new_modules = sk_CONF_IMODULE_new_null();
|
||||||
ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
|
else
|
||||||
goto err;
|
new_modules = sk_CONF_IMODULE_dup(old_modules);
|
||||||
}
|
|
||||||
|
if (new_modules == NULL) {
|
||||||
|
ossl_rcu_write_unlock(module_list_lock);
|
||||||
|
ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sk_CONF_IMODULE_push(initialized_modules, imod)) {
|
if (!sk_CONF_IMODULE_push(new_modules, imod)) {
|
||||||
CRYPTO_THREAD_unlock(module_list_lock);
|
ossl_rcu_write_unlock(module_list_lock);
|
||||||
ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
|
ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
pmod->links++;
|
pmod->links++;
|
||||||
|
|
||||||
CRYPTO_THREAD_unlock(module_list_lock);
|
ossl_rcu_assign_ptr(&initialized_modules, &new_modules);
|
||||||
|
ossl_rcu_write_unlock(module_list_lock);
|
||||||
|
ossl_synchronize_rcu(module_list_lock);
|
||||||
|
sk_CONF_IMODULE_free(old_modules);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -482,30 +504,46 @@ void CONF_modules_unload(int all)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
CONF_MODULE *md;
|
CONF_MODULE *md;
|
||||||
|
STACK_OF(CONF_MODULE) *old_modules;
|
||||||
|
STACK_OF(CONF_MODULE) *new_modules;
|
||||||
|
STACK_OF(CONF_MODULE) *to_delete;
|
||||||
|
|
||||||
if (!conf_modules_finish_int()) /* also inits module list lock */
|
if (!conf_modules_finish_int()) /* also inits module list lock */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!CRYPTO_THREAD_write_lock(module_list_lock))
|
ossl_rcu_write_lock(module_list_lock);
|
||||||
|
|
||||||
|
old_modules = ossl_rcu_deref(&supported_modules);
|
||||||
|
new_modules = sk_CONF_MODULE_dup(old_modules);
|
||||||
|
to_delete = sk_CONF_MODULE_new_null();
|
||||||
|
|
||||||
|
if (new_modules == NULL) {
|
||||||
|
ossl_rcu_write_unlock(module_list_lock);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* unload modules in reverse order */
|
/* unload modules in reverse order */
|
||||||
for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) {
|
for (i = sk_CONF_MODULE_num(new_modules) - 1; i >= 0; i--) {
|
||||||
md = sk_CONF_MODULE_value(supported_modules, i);
|
md = sk_CONF_MODULE_value(new_modules, i);
|
||||||
/* If static or in use and 'all' not set ignore it */
|
/* If static or in use and 'all' not set ignore it */
|
||||||
if (((md->links > 0) || !md->dso) && !all)
|
if (((md->links > 0) || !md->dso) && !all)
|
||||||
continue;
|
continue;
|
||||||
/* Since we're working in reverse this is OK */
|
/* Since we're working in reverse this is OK */
|
||||||
(void)sk_CONF_MODULE_delete(supported_modules, i);
|
(void)sk_CONF_MODULE_delete(new_modules, i);
|
||||||
module_free(md);
|
sk_CONF_MODULE_push(to_delete, md);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sk_CONF_MODULE_num(supported_modules) == 0) {
|
if (sk_CONF_MODULE_num(new_modules) == 0) {
|
||||||
sk_CONF_MODULE_free(supported_modules);
|
sk_CONF_MODULE_free(new_modules);
|
||||||
supported_modules = NULL;
|
new_modules = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRYPTO_THREAD_unlock(module_list_lock);
|
ossl_rcu_assign_ptr(&supported_modules, &new_modules);
|
||||||
|
ossl_rcu_write_unlock(module_list_lock);
|
||||||
|
ossl_synchronize_rcu(module_list_lock);
|
||||||
|
sk_CONF_MODULE_free(old_modules);
|
||||||
|
sk_CONF_MODULE_pop_free(to_delete, module_free);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unload a single module */
|
/* unload a single module */
|
||||||
@ -521,23 +559,27 @@ static void module_free(CONF_MODULE *md)
|
|||||||
static int conf_modules_finish_int(void)
|
static int conf_modules_finish_int(void)
|
||||||
{
|
{
|
||||||
CONF_IMODULE *imod;
|
CONF_IMODULE *imod;
|
||||||
|
STACK_OF(CONF_IMODULE) *old_modules;
|
||||||
|
STACK_OF(CONF_IMODULE) *new_modules = NULL;
|
||||||
|
|
||||||
if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
|
if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* If module_list_lock is NULL here it means we were already unloaded */
|
/* If module_list_lock is NULL here it means we were already unloaded */
|
||||||
if (module_list_lock == NULL
|
if (module_list_lock == NULL)
|
||||||
|| !CRYPTO_THREAD_write_lock(module_list_lock))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (sk_CONF_IMODULE_num(initialized_modules) > 0) {
|
ossl_rcu_write_lock(module_list_lock);
|
||||||
imod = sk_CONF_IMODULE_pop(initialized_modules);
|
old_modules = ossl_rcu_deref(&initialized_modules);
|
||||||
|
ossl_rcu_assign_ptr(&initialized_modules, &new_modules);
|
||||||
|
ossl_rcu_write_unlock(module_list_lock);
|
||||||
|
ossl_synchronize_rcu(module_list_lock);
|
||||||
|
|
||||||
|
while (sk_CONF_IMODULE_num(old_modules) > 0) {
|
||||||
|
imod = sk_CONF_IMODULE_pop(old_modules);
|
||||||
module_finish(imod);
|
module_finish(imod);
|
||||||
}
|
}
|
||||||
sk_CONF_IMODULE_free(initialized_modules);
|
sk_CONF_IMODULE_free(old_modules);
|
||||||
initialized_modules = NULL;
|
|
||||||
|
|
||||||
CRYPTO_THREAD_unlock(module_list_lock);
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user