implement RCU (Read-Copy-Update) operations. NOTE: vxrcu.c should be included in the openssl generated Makefile by ./Configure. (#20)

Reviewed-on: http://13.234.246.121:3000/Neominds/ossl35vx69/pulls/20
Co-authored-by: siddhant <siddhant.singh@neominds.in>
Co-committed-by: siddhant <siddhant.singh@neominds.in>
This commit is contained in:
2026-07-30 19:34:51 +05:30
committed by neelimap
parent f0336e6b57
commit 87219deb19
3 changed files with 171 additions and 0 deletions
@@ -23,6 +23,7 @@
#include <openssl/trace.h> #include <openssl/trace.h>
#include <openssl/engine.h> #include <openssl/engine.h>
#include "conf_local.h" #include "conf_local.h"
#include <openssl/vxrcu.c>
DEFINE_STACK_OF(CONF_MODULE) DEFINE_STACK_OF(CONF_MODULE)
DEFINE_STACK_OF(CONF_IMODULE) DEFINE_STACK_OF(CONF_IMODULE)
@@ -12,9 +12,21 @@
# pragma once # pragma once
#include "crypto/context.h" #include "crypto/context.h"
#include <types/vxWind.h>
typedef void (*rcu_cb_fn)(void *data); typedef void (*rcu_cb_fn)(void *data);
struct rcu_lock_st{
/* Callbacks to call for next ossl_synchronize_rcu */
struct rcu_cb_item *cb_items;
/* Mutex for writers */
SEM_ID writer_lock;
/* Reader counter */
volatile int active_readers;
};
typedef struct rcu_lock_st CRYPTO_RCU_LOCK; typedef struct rcu_lock_st CRYPTO_RCU_LOCK;
CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx); CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx);
@@ -0,0 +1,158 @@
#include <semLib.h>
#include <vxAtomicLib.h>
#include "../crypto/rcu_internal.h"
typedef struct crypto_rwlock_st {
SEM_ID sem;
}CRYPTO_RWLOCK_VX;
static CRYPTO_RWLOCK_VX *local_rcu_rwlock;
static int is_rwlock_init = 0;
/*---------- Atomic routines ----------*/
int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock)
{
CRYPTO_RWLOCK_VX *vx;
if (!val || !ret || !lock)
return 0;
vx = (CRYPTO_RWLOCK_VX *)lock;
semTake (vx->sem, WAIT_FOREVER);
*ret = *val;
semGive (vx->sem);
return 1;
}
int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock)
{
CRYPTO_RWLOCK_VX *vx;
if (!dst || !lock)
return 0;
vx = (CRYPTO_RWLOCK_VX *)lock;
semTake (vx->sem, WAIT_FOREVER);
*dst = val;
semGive (vx->sem);
return 1;
}
/*---------- RCU routines ----------*/
CRYPTO_RCU_LOCK *ossl_rcu_lock_new(int num_writers, OSSL_LIB_CTX *ctx)
{
CRYPTO_RCU_LOCK *lock = malloc (sizeof(CRYPTO_RCU_LOCK));
if (!lock)
return NULL;
lock->writer_lock = semBCreate (SEM_Q_PRIORITY |
SEM_DELETE_SAFE | SEM_INVERSION_SAFE,
SEM_EMPTY);
lock->active_readers = 0;
if (!is_rwlock_init)
{
local_rcu_rwlock->sem = semBCreate (SEM_Q_PRIORITY |
SEM_DELETE_SAFE | SEM_INVERSION_SAFE,
SEM_EMPTY);
is_rwlock_init = 1;
}
return lock;
}
void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock)
{
if (is_rwlock_init)
{
semDelete (local_rcu_rwlock->sem);
is_rwlock_init = 0;
}
if (!lock) return;
semDelete (lock->writer_lock);
free(lock);
}
void ossl_rcu_read_lock(CRYPTO_RCU_LOCK *lock)
{
vxAtomicInc (&(lock->active_readers));
}
void ossl_rcu_read_unlock(CRYPTO_RCU_LOCK *lock)
{
vxAtomicDec (&(lock->active_readers));
}
void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock)
{
semBTake (lock->writer_lock, WAIT_FOREVER);
}
void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock)
{
semBGive (lock->writer_lock);
}
void *ossl_rcu_uptr_deref(void **p)
{
/* readers just dereference safely */
return *p;
}
void ossl_rcu_assign_uptr(void **p, void **v)
{
void *ret, *val;
ret = p;
val = v;
/* publish new pointer immediately */
CRYPTO_atomic_load_int (val, ret, local_rcu_rwlock);
}
void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock)
{
int retVal=0;
struct rcu_cb_item *cb_items, *tmpcb;
semBTake (lock->writer_lock, WAIT_FOREVER);
cb_items = lock->cb_items;
lock->cb_items = NULL;
semBGive (lock->writer_lock);
/* Wait until all readers finish */
do {
CRYPTO_atomic_load_int(&(lock->active_readers), &retVal, local_rcu_rwlock);
taskDelay(0);
}while (retVal > 0);
/* handle any callbacks that we have */
while (cb_items != NULL) {
tmpcb = cb_items;
cb_items = cb_items->next;
tmpcb->fn(tmpcb->data);
OPENSSL_free(tmpcb);
}
}
int ossl_rcu_call(CRYPTO_RCU_LOCK *lock, rcu_cb_fn cb, void *data)
{
struct rcu_cb_item *new = OPENSSL_zalloc(sizeof(*new));
if (!lock || !cb) return 0;
if (new == NULL)
return 0;
new->data = data;
new->fn = cb;
new->next = lock->cb_items;
lock->cb_items = new;
return 1;
}