DEFINE_RUN_ONCE_STATIC(do_init_module_list_lock)
{
- module_list_lock = ossl_rcu_lock_new(1);
+ module_list_lock = ossl_rcu_lock_new(1, NULL);
if (module_list_lock == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_CRYPTO_LIB);
return 0;
void *global_properties;
void *drbg;
void *drbg_nonce;
+ CRYPTO_THREAD_LOCAL rcu_local_key;
#ifndef FIPS_MODULE
void *provider_conf;
void *bio_core;
{
int exdata_done = 0;
+ if (!CRYPTO_THREAD_init_local(&ctx->rcu_local_key, NULL))
+ return 0;
+
ctx->lock = CRYPTO_THREAD_lock_new();
if (ctx->lock == NULL)
- return 0;
+ goto err;
ctx->rand_crngt_lock = CRYPTO_THREAD_lock_new();
if (ctx->rand_crngt_lock == NULL)
CRYPTO_THREAD_lock_free(ctx->rand_crngt_lock);
CRYPTO_THREAD_lock_free(ctx->lock);
+ CRYPTO_THREAD_cleanup_local(&ctx->rcu_local_key);
memset(ctx, '\0', sizeof(*ctx));
return 0;
}
CRYPTO_THREAD_lock_free(ctx->lock);
ctx->rand_crngt_lock = NULL;
ctx->lock = NULL;
+ CRYPTO_THREAD_cleanup_local(&ctx->rcu_local_key);
return 1;
}
return "Non-default library context";
#endif
}
+
+CRYPTO_THREAD_LOCAL *ossl_lib_ctx_get_rcukey(OSSL_LIB_CTX *libctx)
+{
+ libctx = ossl_lib_ctx_get_concrete(libctx);
+ if (libctx == NULL)
+ return NULL;
+ return &libctx->rcu_local_key;
+}
struct rcu_cb_item *cb_items;
};
-CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers)
+CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx)
{
struct rcu_lock_st *lock;
# define ATOMIC_OR_FETCH(p, v, o) fallback_atomic_or_fetch(p, v)
# endif
-static CRYPTO_THREAD_LOCAL rcu_thr_key;
-
/*
* users is broken up into 2 parts
* bits 0-15 current readers
/* Callbacks to call for next ossl_synchronize_rcu */
struct rcu_cb_item *cb_items;
+ /* The context we are being created against */
+ OSSL_LIB_CTX *ctx;
+
/* rcu generation counter for in-order retirement */
uint32_t id_ctr;
pthread_cond_t prior_signal;
};
-/*
- * Called on thread exit to free the pthread key
- * associated with this thread, if any
- */
-static void free_rcu_thr_data(void *ptr)
-{
- struct rcu_thr_data *data =
- (struct rcu_thr_data *)CRYPTO_THREAD_get_local(&rcu_thr_key);
-
- OPENSSL_free(data);
- CRYPTO_THREAD_set_local(&rcu_thr_key, NULL);
-}
-
-static void ossl_rcu_init(void)
-{
- CRYPTO_THREAD_init_local(&rcu_thr_key, NULL);
-}
-
/* Read side acquisition of the current qp */
static struct rcu_qp *get_hold_current_qp(struct rcu_lock_st *lock)
{
return &lock->qp_group[qp_idx];
}
+static void ossl_rcu_free_local_data(void *arg)
+{
+ OSSL_LIB_CTX *ctx = arg;
+ CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(ctx);
+ struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey);
+ OPENSSL_free(data);
+}
+
void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock)
{
struct rcu_thr_data *data;
int i, available_qp = -1;
+ CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx);
/*
* we're going to access current_qp here so ask the
* processor to fetch it
*/
- data = CRYPTO_THREAD_get_local(&rcu_thr_key);
+ data = CRYPTO_THREAD_get_local(lkey);
if (data == NULL) {
data = OPENSSL_zalloc(sizeof(*data));
OPENSSL_assert(data != NULL);
- CRYPTO_THREAD_set_local(&rcu_thr_key, data);
- ossl_init_thread_start(NULL, NULL, free_rcu_thr_data);
+ CRYPTO_THREAD_set_local(lkey, data);
+ ossl_init_thread_start(NULL, lock->ctx, ossl_rcu_free_local_data);
}
for (i = 0; i < MAX_QPS; i++) {
void ossl_rcu_read_unlock(CRYPTO_RCU_LOCK *lock)
{
int i;
- struct rcu_thr_data *data = CRYPTO_THREAD_get_local(&rcu_thr_key);
+ CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx);
+ struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey);
uint64_t ret;
assert(data != NULL);
ATOMIC_STORE(pvoid, p, v, __ATOMIC_RELEASE);
}
-static CRYPTO_ONCE rcu_init_once = CRYPTO_ONCE_STATIC_INIT;
-
-CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers)
+CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx)
{
struct rcu_lock_st *new;
- if (!CRYPTO_THREAD_run_once(&rcu_init_once, ossl_rcu_init))
- return NULL;
-
if (num_writers < 1)
num_writers = 1;
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+ if (ctx == NULL)
+ return 0;
+
new = OPENSSL_zalloc(sizeof(*new));
if (new == NULL)
return NULL;
+ new->ctx = ctx;
pthread_mutex_init(&new->write_lock, NULL);
pthread_mutex_init(&new->prior_lock, NULL);
pthread_mutex_init(&new->alloc_lock, NULL);
} CRYPTO_win_rwlock;
# endif
-static CRYPTO_THREAD_LOCAL rcu_thr_key;
-
# define READER_SHIFT 0
# define ID_SHIFT 32
# define READER_SIZE 32
*/
struct rcu_lock_st {
struct rcu_cb_item *cb_items;
+ OSSL_LIB_CTX *ctx;
uint32_t id_ctr;
struct rcu_qp *qp_group;
size_t group_count;
CRYPTO_CONDVAR *prior_signal;
};
-/*
- * Called on thread exit to free the pthread key
- * associated with this thread, if any
- */
-static void free_rcu_thr_data(void *ptr)
-{
- struct rcu_thr_data *data =
- (struct rcu_thr_data *)CRYPTO_THREAD_get_local(&rcu_thr_key);
-
- OPENSSL_free(data);
- CRYPTO_THREAD_set_local(&rcu_thr_key, NULL);
-}
-
-
-static void ossl_rcu_init(void)
-{
- CRYPTO_THREAD_init_local(&rcu_thr_key, NULL);
- ossl_init_thread_start(NULL, NULL, free_rcu_thr_data);
-}
-
static struct rcu_qp *allocate_new_qp_group(struct rcu_lock_st *lock,
int count)
{
return new;
}
-static CRYPTO_ONCE rcu_init_once = CRYPTO_ONCE_STATIC_INIT;
-
-CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers)
+CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx)
{
struct rcu_lock_st *new;
- if (!CRYPTO_THREAD_run_once(&rcu_init_once, ossl_rcu_init))
- return NULL;
-
if (num_writers < 1)
num_writers = 1;
+ ctx = ossl_lib_ctx_get_concrete(ctx);
+ if (ctx == NULL)
+ return 0;
+
new = OPENSSL_zalloc(sizeof(*new));
if (new == NULL)
return NULL;
+ new->ctx = ctx;
new->write_lock = ossl_crypto_mutex_new();
new->alloc_signal = ossl_crypto_condvar_new();
new->prior_signal = ossl_crypto_condvar_new();
return &lock->qp_group[qp_idx];
}
+static void ossl_rcu_free_local_data(void *arg)
+{
+ OSSL_LIB_CTX *ctx = arg;
+ CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(ctx);
+ struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey);
+ OPENSSL_free(data);
+}
+
void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock)
{
struct rcu_thr_data *data;
int i;
int available_qp = -1;
+ CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx);
/*
* we're going to access current_qp here so ask the
* processor to fetch it
*/
- data = CRYPTO_THREAD_get_local(&rcu_thr_key);
+ data = CRYPTO_THREAD_get_local(lkey);
if (data == NULL) {
data = OPENSSL_zalloc(sizeof(*data));
OPENSSL_assert(data != NULL);
- CRYPTO_THREAD_set_local(&rcu_thr_key, data);
+ CRYPTO_THREAD_set_local(lkey, data);
+ ossl_init_thread_start(NULL, lock->ctx, ossl_rcu_free_local_data);
}
for (i = 0; i < MAX_QPS; i++) {
void ossl_rcu_read_unlock(CRYPTO_RCU_LOCK *lock)
{
- struct rcu_thr_data *data = CRYPTO_THREAD_get_local(&rcu_thr_key);
+ CRYPTO_THREAD_LOCAL *lkey = ossl_lib_ctx_get_rcukey(lock->ctx);
+ struct rcu_thr_data *data = CRYPTO_THREAD_get_local(lkey);
int i;
LONG64 ret;
=head1 SYNOPSIS
- CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers);
+ CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx);
void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock);
void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock);
void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock);
indicates the number of write side threads which may execute
ossl_synchronize_rcu() in parallel. The value must be at least 1, but may be
larger to obtain increased write side throughput at the cost of additional
-internal memory usage. A value of 1 is generally recommended.
+internal memory usage. A value of 1 is generally recommended. The I<ctx>
+parameter references the library context in which the lock is allocated.
=item *
OSSL_EX_DATA_GLOBAL *ossl_lib_ctx_get_ex_data_global(OSSL_LIB_CTX *ctx);
const char *ossl_lib_ctx_get_descriptor(OSSL_LIB_CTX *libctx);
+CRYPTO_THREAD_LOCAL *ossl_lib_ctx_get_rcukey(OSSL_LIB_CTX *libctx);
OSSL_LIB_CTX *ossl_crypto_ex_data_get_ossl_lib_ctx(const CRYPTO_EX_DATA *ad);
int ossl_crypto_new_ex_data_ex(OSSL_LIB_CTX *ctx, int class_index, void *obj,
# define OPENSSL_RCU_H
# pragma once
+#include "crypto/context.h"
+
typedef void (*rcu_cb_fn)(void *data);
typedef struct rcu_lock_st CRYPTO_RCU_LOCK;
-CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers);
+CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx);
void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock);
void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock);
void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock);
writer2_done = 0;
rcu_torture_result = 1;
- rcu_lock = ossl_rcu_lock_new(1);
+ rcu_lock = ossl_rcu_lock_new(1, NULL);
TEST_info("Staring rcu torture");
t1 = ossl_time_now();
*(void **) (&f) = arg;
f();
+ OPENSSL_thread_stop();
return NULL;
}