ex_data: convert to new-style locking.
Change-Id: Id81f986f433805837b58a6ddd13ec146ff62c30b Reviewed-on: https://boringssl-review.googlesource.com/4323 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
+29
-40
@@ -122,37 +122,32 @@
|
||||
/* global_impl is the implementation that we use at runtime. */
|
||||
static const CRYPTO_EX_DATA_IMPL *global_impl = NULL;
|
||||
|
||||
/* global_impl_once protects the call to |global_impl_init|. */
|
||||
static CRYPTO_once_t global_impl_once = CRYPTO_ONCE_INIT;
|
||||
|
||||
/* global_user_set_impl is a pointer to a user provided implementation. If this
|
||||
* is non-NULL at the point of the first use of ex_data, |global_impl| will be
|
||||
* set to this value. */
|
||||
static const CRYPTO_EX_DATA_IMPL *global_user_set_impl = NULL;
|
||||
|
||||
/* ex_data_default_impl is a the default implementation, defined in
|
||||
* ex_data_impl.c. */
|
||||
extern const CRYPTO_EX_DATA_IMPL ex_data_default_impl;
|
||||
|
||||
/* get_impl returns the current ex_data implementatation. */
|
||||
static const CRYPTO_EX_DATA_IMPL *get_impl(void) {
|
||||
const CRYPTO_EX_DATA_IMPL *impl;
|
||||
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
|
||||
impl = global_impl;
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
|
||||
|
||||
if (impl != NULL) {
|
||||
return impl;
|
||||
}
|
||||
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
|
||||
/* global_impl_init is called once in order to set |global_impl|. */
|
||||
static void global_impl_init(void) {
|
||||
global_impl = global_user_set_impl;
|
||||
if (global_impl == NULL) {
|
||||
global_impl = &ex_data_default_impl;
|
||||
}
|
||||
impl = global_impl;
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
|
||||
return impl;
|
||||
}
|
||||
|
||||
int CRYPTO_get_ex_new_index(int class_value, long argl, void *argp,
|
||||
CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func,
|
||||
CRYPTO_EX_free *free_func) {
|
||||
const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
|
||||
return impl->get_new_index(class_value, argl, argp, new_func, dup_func,
|
||||
free_func);
|
||||
CRYPTO_once(&global_impl_once, global_impl_init);
|
||||
return global_impl->get_new_index(class_value, argl, argp, new_func, dup_func,
|
||||
free_func);
|
||||
}
|
||||
|
||||
int CRYPTO_set_ex_data(CRYPTO_EX_DATA *ad, int index, void *val) {
|
||||
@@ -188,44 +183,38 @@ void *CRYPTO_get_ex_data(const CRYPTO_EX_DATA *ad, int idx) {
|
||||
}
|
||||
|
||||
int CRYPTO_ex_data_new_class(void) {
|
||||
const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
|
||||
return impl->new_class();
|
||||
CRYPTO_once(&global_impl_once, global_impl_init);
|
||||
return global_impl->new_class();
|
||||
}
|
||||
|
||||
int CRYPTO_new_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
|
||||
const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
|
||||
return impl->new_ex_data(class_value, obj, ad);
|
||||
CRYPTO_once(&global_impl_once, global_impl_init);
|
||||
return global_impl->new_ex_data(class_value, obj, ad);
|
||||
}
|
||||
|
||||
int CRYPTO_dup_ex_data(int class_value, CRYPTO_EX_DATA *to,
|
||||
const CRYPTO_EX_DATA *from) {
|
||||
const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
|
||||
return impl->dup_ex_data(class_value, to, from);
|
||||
CRYPTO_once(&global_impl_once, global_impl_init);
|
||||
return global_impl->dup_ex_data(class_value, to, from);
|
||||
}
|
||||
|
||||
void CRYPTO_free_ex_data(int class_value, void *obj, CRYPTO_EX_DATA *ad) {
|
||||
const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
|
||||
impl->free_ex_data(class_value, obj, ad);
|
||||
CRYPTO_once(&global_impl_once, global_impl_init);
|
||||
global_impl->free_ex_data(class_value, obj, ad);
|
||||
}
|
||||
|
||||
const CRYPTO_EX_DATA_IMPL *CRYPTO_get_ex_data_implementation(void) {
|
||||
return get_impl();
|
||||
CRYPTO_once(&global_impl_once, global_impl_init);
|
||||
return global_impl;
|
||||
}
|
||||
|
||||
int CRYPTO_set_ex_data_implementation(const CRYPTO_EX_DATA_IMPL *impl) {
|
||||
int ret = 0;
|
||||
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
|
||||
if (global_impl == NULL) {
|
||||
ret = 1;
|
||||
global_impl = impl;
|
||||
}
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
|
||||
|
||||
return ret;
|
||||
global_user_set_impl = impl;
|
||||
CRYPTO_once(&global_impl_once, global_impl_init);
|
||||
return (global_impl == impl);
|
||||
}
|
||||
|
||||
void CRYPTO_cleanup_all_ex_data(void) {
|
||||
const CRYPTO_EX_DATA_IMPL *const impl = get_impl();
|
||||
impl->cleanup();
|
||||
CRYPTO_once(&global_impl_once, global_impl_init);
|
||||
global_impl->cleanup();
|
||||
}
|
||||
|
||||
+25
-37
@@ -132,15 +132,19 @@ typedef struct st_ex_class_item {
|
||||
int class_value;
|
||||
} EX_CLASS_ITEM;
|
||||
|
||||
static CRYPTO_once_t global_classes_once = CRYPTO_ONCE_INIT;
|
||||
static struct CRYPTO_STATIC_MUTEX global_classes_lock =
|
||||
CRYPTO_STATIC_MUTEX_INIT;
|
||||
static LHASH_OF(EX_CLASS_ITEM) *global_classes = NULL;
|
||||
|
||||
static struct CRYPTO_STATIC_MUTEX global_next_class_lock =
|
||||
CRYPTO_STATIC_MUTEX_INIT;
|
||||
static int global_next_class = 100;
|
||||
|
||||
static int new_class(void) {
|
||||
int ret;
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
|
||||
ret = global_next_class++;
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
|
||||
CRYPTO_STATIC_MUTEX_lock_write(&global_next_class_lock);
|
||||
const int ret = global_next_class++;
|
||||
CRYPTO_STATIC_MUTEX_unlock(&global_next_class_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -170,50 +174,34 @@ static void class_free(EX_CLASS_ITEM *item) {
|
||||
OPENSSL_free(item);
|
||||
}
|
||||
|
||||
static LHASH_OF(EX_CLASS_ITEM) *get_classes(void) {
|
||||
LHASH_OF(EX_CLASS_ITEM) *ret;
|
||||
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
|
||||
ret = global_classes;
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
|
||||
|
||||
if (ret != NULL) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
|
||||
if (global_classes == NULL) {
|
||||
global_classes = lh_EX_CLASS_ITEM_new(class_hash, class_cmp);
|
||||
}
|
||||
ret = global_classes;
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
|
||||
|
||||
return ret;
|
||||
static void global_classes_init(void) {
|
||||
global_classes = lh_EX_CLASS_ITEM_new(class_hash, class_cmp);
|
||||
}
|
||||
|
||||
static void cleanup(void) {
|
||||
LHASH_OF(EX_CLASS_ITEM) *classes = get_classes();
|
||||
CRYPTO_once(&global_classes_once, global_classes_init);
|
||||
|
||||
if (classes != NULL) {
|
||||
lh_EX_CLASS_ITEM_doall(classes, class_free);
|
||||
lh_EX_CLASS_ITEM_free(classes);
|
||||
if (global_classes != NULL) {
|
||||
lh_EX_CLASS_ITEM_doall(global_classes, class_free);
|
||||
lh_EX_CLASS_ITEM_free(global_classes);
|
||||
}
|
||||
|
||||
global_classes = NULL;
|
||||
}
|
||||
|
||||
static EX_CLASS_ITEM *get_class(int class_value) {
|
||||
LHASH_OF(EX_CLASS_ITEM) *const classes = get_classes();
|
||||
EX_CLASS_ITEM template, *class_item;
|
||||
int ok = 0;
|
||||
|
||||
if (classes == NULL) {
|
||||
CRYPTO_once(&global_classes_once, global_classes_init);
|
||||
|
||||
if (global_classes == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
|
||||
CRYPTO_STATIC_MUTEX_lock_write(&global_classes_lock);
|
||||
template.class_value = class_value;
|
||||
class_item = lh_EX_CLASS_ITEM_retrieve(classes, &template);
|
||||
class_item = lh_EX_CLASS_ITEM_retrieve(global_classes, &template);
|
||||
if (class_item != NULL) {
|
||||
ok = 1;
|
||||
} else {
|
||||
@@ -223,12 +211,12 @@ static EX_CLASS_ITEM *get_class(int class_value) {
|
||||
class_item->meth = sk_CRYPTO_EX_DATA_FUNCS_new_null();
|
||||
if (class_item->meth != NULL) {
|
||||
EX_CLASS_ITEM *old_data;
|
||||
ok = lh_EX_CLASS_ITEM_insert(classes, &old_data, class_item);
|
||||
ok = lh_EX_CLASS_ITEM_insert(global_classes, &old_data, class_item);
|
||||
assert(old_data == NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
|
||||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock);
|
||||
|
||||
if (!ok) {
|
||||
if (class_item) {
|
||||
@@ -268,7 +256,7 @@ static int get_new_index(int class_value, long argl, void *argp,
|
||||
funcs->dup_func = dup_func;
|
||||
funcs->free_func = free_func;
|
||||
|
||||
CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
|
||||
CRYPTO_STATIC_MUTEX_lock_write(&global_classes_lock);
|
||||
|
||||
if (!sk_CRYPTO_EX_DATA_FUNCS_push(item->meth, funcs)) {
|
||||
OPENSSL_PUT_ERROR(CRYPTO, get_new_index, ERR_R_MALLOC_FAILURE);
|
||||
@@ -279,7 +267,7 @@ static int get_new_index(int class_value, long argl, void *argp,
|
||||
ret = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth) - 1;
|
||||
|
||||
err:
|
||||
CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
|
||||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -301,12 +289,12 @@ static int get_func_pointers(STACK_OF(CRYPTO_EX_DATA_FUNCS) **out,
|
||||
/* CRYPTO_EX_DATA_FUNCS structures are static once set, so we can take a
|
||||
* shallow copy of the list under lock and then use the structures without
|
||||
* the lock held. */
|
||||
CRYPTO_r_lock(CRYPTO_LOCK_EX_DATA);
|
||||
CRYPTO_STATIC_MUTEX_lock_read(&global_classes_lock);
|
||||
n = sk_CRYPTO_EX_DATA_FUNCS_num(item->meth);
|
||||
if (n > 0) {
|
||||
*out = sk_CRYPTO_EX_DATA_FUNCS_dup(item->meth);
|
||||
}
|
||||
CRYPTO_r_unlock(CRYPTO_LOCK_EX_DATA);
|
||||
CRYPTO_STATIC_MUTEX_unlock(&global_classes_lock);
|
||||
|
||||
if (n > 0 && *out == NULL) {
|
||||
OPENSSL_PUT_ERROR(CRYPTO, get_func_pointers, ERR_R_MALLOC_FAILURE);
|
||||
|
||||
Reference in New Issue
Block a user