RCU fix: Compile vxrcu.c file. Use Mutex semaphore instead of Binary semaphore. Runtime memory allocation for 'local_rcu_rwlock' (#58)

**NOTE:** Debug printfs have been added in this commit for tracing purposes.
OpenSSL, being a library, does not print error messages directly on stderr; instead, it maintains an
error queue. Proper handling of the error queue will be implemented in commits for debug and trace.

| TODO | Proper handling for debug messages in vxrcu.c |
| --- | --- |

Reviewed-on: http://13.234.246.121:3000/Neominds/ossl35vx69/pulls/58
Co-authored-by: siddhant <siddhant.singh@neominds.in>
Co-committed-by: siddhant <siddhant.singh@neominds.in>
This commit is contained in:
2026-07-30 20:24:57 +05:30
committed by neelimap
parent c088e4db41
commit 6ceca6ba38
5 changed files with 216 additions and 140 deletions
@@ -111,7 +111,7 @@ $UTIL_COMMON=\
threads_vxworks.c initthread.c \
context.c sparse_array.c asn1_dsa.c packet.c param_build.c \
param_build_set.c der_writer.c threads_lib.c params_dup.c \
time.c params_idx.c
time.c params_idx.c vxrcu.c
SOURCE[../libcrypto]=$UTIL_COMMON \
mem.c mem_sec.c \
@@ -23,7 +23,7 @@
#include <openssl/trace.h>
#include <openssl/engine.h>
#include "conf_local.h"
#include <openssl/vxrcu.c>
#include <openssl/vxrcu.h>
DEFINE_STACK_OF(CONF_MODULE)
DEFINE_STACK_OF(CONF_IMODULE)
@@ -0,0 +1,188 @@
#include <openssl/crypto.h>
#include <openssl/vxrcu.h>
static CRYPTO_RWLOCK_VX *local_rcu_rwlock = NULL;
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)
{
printf ("CRYPTO_atomic_load_int:: invalid parameter(s)\n");
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)
{
printf ("CRYPTO_atomic_store:: invalid parameter(s)\n");
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 = OPENSSL_malloc (sizeof(CRYPTO_RCU_LOCK));
if (!lock)
{
printf ("ossl_rcu_lock_new:: Failed to allocate memory for RCU lock\n");
return NULL;
}
lock->writer_lock = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
if (!(lock->writer_lock))
printf ("ossl_rcu_lock_new:: semMCreate failed for writer_lock\n");
lock->active_readers = 0;
if (!is_rwlock_init)
{
local_rcu_rwlock = OPENSSL_malloc (sizeof (CRYPTO_RWLOCK_VX));
if (!local_rcu_rwlock)
{
printf ("ossl_rcu_lock_new:: Failed to allocate memory\n");
return NULL;
}
memset (local_rcu_rwlock, sizeof (CRYPTO_RWLOCK_VX), 0);
local_rcu_rwlock->sem = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE);
if (!(local_rcu_rwlock->sem))
printf ("ossl_rcu_lock_new:: semMCreate failed for local_rcu_rwlock\n");
is_rwlock_init = 1;
}
return lock;
}
void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock)
{
if (is_rwlock_init)
{
semDelete (local_rcu_rwlock);
OPENSSL_free (local_rcu_rwlock);
local_rcu_rwlock = NULL;
is_rwlock_init = 0;
}
if (!lock)
{
printf ("ossl_rcu_lock_free:: RCU lock is NULL\n");
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)
{
semMTake (lock->writer_lock, WAIT_FOREVER);
}
void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock)
{
semMGive (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;
semMTake (lock->writer_lock, WAIT_FOREVER);
cb_items = lock->cb_items;
lock->cb_items = NULL;
semMGive (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)
{
if (!lock || !cb)
{
printf ("ossl_rcu_call:: invalid parameter(s)\n");
return 0;
}
struct rcu_cb_item *new = OPENSSL_zalloc(sizeof(*new));
if (!new)
{
printf ("ossl_rcu_call:: memory allocation for RCU callback failed\n");
return 0;
}
new->data = data;
new->fn = cb;
new->next = lock->cb_items;
lock->cb_items = new;
return 1;
}
@@ -1,138 +0,0 @@
#ifndef RCU_VX69_H
#define RCU_VX69_H
#include <semLib.h>
#include <vxAtomicLib.h>
#include "../crypto/rcu_internal.h"
typedef struct crypto_rwlock_st {
SEM_ID sem;
}CRYPTO_RWLOCK_VX;
/*---------- 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_EMPTY);
lock->active_readers = 0;
return lock;
}
void ossl_rcu_lock_free(CRYPTO_RCU_LOCK *lock)
{
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)
{
/* publish new pointer immediately */
*p = *v;
}
void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock)
{
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 */
while (lock->active_readers > 0)
taskDelay(1);
/* 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;
}
#endif
@@ -0,0 +1,26 @@
#ifndef RCU_VX69_H
#define RCU_VX69_H
#include <semLib.h>
#include <vxAtomicLib.h>
#include "../internal/rcu.h"
#include "../crypto/rcu_internal.h"
typedef struct crypto_rwlock_st {
SEM_ID sem;
}CRYPTO_RWLOCK_VX;
int CRYPTO_atomic_load_int(int *val, int *ret, CRYPTO_RWLOCK *lock);
int CRYPTO_atomic_store(uint64_t *dst, uint64_t val, CRYPTO_RWLOCK *lock);
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_read_unlock(CRYPTO_RCU_LOCK *lock);
void ossl_rcu_write_lock(CRYPTO_RCU_LOCK *lock);
void ossl_rcu_write_unlock(CRYPTO_RCU_LOCK *lock);
void *ossl_rcu_uptr_deref(void **p);
void ossl_rcu_assign_uptr(void **p, void **v);
void ossl_synchronize_rcu(CRYPTO_RCU_LOCK *lock);
int ossl_rcu_call(CRYPTO_RCU_LOCK *lock, rcu_cb_fn cb, void *data);
#endif /*RCU_VX69_H*/