mirror of https://github.com/openssl/openssl.git
hashtable: Support lockless reads
Also build it in the FIPS provider too and properly report error on insert when hashtable cannot be grown. Reviewed-by: Neil Horman <nhorman@openssl.org> Reviewed-by: Paul Dale <ppzgs1@gmail.com> (Merged from https://github.com/openssl/openssl/pull/24504)
This commit is contained in:
parent
6cdca7b9fe
commit
71fe7f0983
|
@ -1,4 +1,6 @@
|
|||
LIBS=../../libcrypto
|
||||
SOURCE[../../libcrypto]=\
|
||||
hashtable.c
|
||||
$COMMON=hashtable.c
|
||||
|
||||
SOURCE[../../libcrypto]=$COMMON
|
||||
SOURCE[../../providers/libfips.a]=$COMMON
|
||||
|
||||
|
|
|
@ -179,7 +179,7 @@ static void internal_free_nop(HT_VALUE *v)
|
|||
return;
|
||||
}
|
||||
|
||||
HT *ossl_ht_new(HT_CONFIG *conf)
|
||||
HT *ossl_ht_new(const HT_CONFIG *conf)
|
||||
{
|
||||
HT *new = OPENSSL_zalloc(sizeof(*new));
|
||||
|
||||
|
@ -427,7 +427,7 @@ static void free_old_neigh_table(void *arg)
|
|||
*/
|
||||
static int grow_hashtable(HT *h, size_t oldsize)
|
||||
{
|
||||
struct ht_mutable_data_st *newmd = OPENSSL_zalloc(sizeof(*newmd));
|
||||
struct ht_mutable_data_st *newmd;
|
||||
struct ht_mutable_data_st *oldmd = ossl_rcu_deref(&h->md);
|
||||
int rc = 0;
|
||||
uint64_t oldi, oldj, newi, newj;
|
||||
|
@ -436,7 +436,10 @@ static int grow_hashtable(HT *h, size_t oldsize)
|
|||
int rehashed;
|
||||
size_t newsize = oldsize * 2;
|
||||
|
||||
if (newmd == NULL)
|
||||
if (h->config.lockless_reads)
|
||||
goto out;
|
||||
|
||||
if ((newmd = OPENSSL_zalloc(sizeof(*newmd))) == NULL)
|
||||
goto out;
|
||||
|
||||
/* bucket list is always a power of 2 */
|
||||
|
@ -700,6 +703,9 @@ int ossl_ht_delete(HT *h, HT_KEY *key)
|
|||
HT_VALUE *nv = NULL;
|
||||
int rc = 0;
|
||||
|
||||
if (h->config.lockless_reads)
|
||||
return 0;
|
||||
|
||||
hash = h->config.ht_hash_fn(key->keybuf, key->keysize);
|
||||
|
||||
neigh_idx = hash & h->md->neighborhood_mask;
|
||||
|
@ -724,4 +730,3 @@ int ossl_ht_delete(HT *h, HT_KEY *key)
|
|||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ IMPLEMENT_HT_VALUE_TYPE_FNS
|
|||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
HT *ossl_ht_new(HT_CONFIG *conf);
|
||||
HT *ossl_ht_new(const HT_CONFIG *conf);
|
||||
void ossl_ht_free(HT *htable);
|
||||
void ossl_ht_read_lock(HT *htable);
|
||||
void ossl_ht_read_unlock(HT *htable);
|
||||
|
@ -66,14 +66,14 @@ contains configurations options for hashtable. Current config options consist
|
|||
of:
|
||||
I<ht_free_fn> The function to call to free a value, may be NULL.
|
||||
I<ht_hash_fn> The function to generate a hash value for a key, may be NULL.
|
||||
I<init_neighborhood_len> The initial number of neighborhoods in the hash table.
|
||||
I<init_neighborhoods> The initial number of neighborhoods in the hash table.
|
||||
|
||||
Note that init_bucket_len may be set to zero, which will use the default initial
|
||||
bucket size, which will be automatically expanded with the hash table load
|
||||
average reaches 0.75.
|
||||
|
||||
Note that lockless_read operation implies behavioral restrictions. Specifically
|
||||
Only element additions are allowed, deletion operations will fail
|
||||
only element additions are allowed, deletion operations will fail
|
||||
Hash table growth is inhibited. init_bucket_len should be set to an
|
||||
appropriate value to prevent performance degradation
|
||||
The table owner is responsible for ensuring there are no readers during a
|
||||
|
@ -281,6 +281,9 @@ provided filter
|
|||
ossl_ht_get() returns an B<HT_VALUE> pointer, or NULL if the element was not
|
||||
found.
|
||||
|
||||
ossl_ht_insert() returns 1 if an element was inserted, 0 if the element is
|
||||
already present, -1 on fatal errors (memory allocation or growth not allowed).
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
#include <stdio.h>
|
||||
|
|
|
@ -99,7 +99,7 @@ static void fuzz_free_cb(HT_VALUE *v)
|
|||
|
||||
int FuzzerInitialize(int *argc, char ***argv)
|
||||
{
|
||||
HT_CONFIG fuzz_conf = {NULL, fuzz_free_cb, NULL, 1, 0};
|
||||
HT_CONFIG fuzz_conf = {NULL, fuzz_free_cb, NULL, 0, 1};
|
||||
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
ERR_clear_error();
|
||||
|
|
|
@ -51,8 +51,9 @@ typedef struct ht_config_st {
|
|||
OSSL_LIB_CTX *ctx;
|
||||
void (*ht_free_fn)(HT_VALUE *obj);
|
||||
uint64_t (*ht_hash_fn)(uint8_t *key, size_t keylen);
|
||||
size_t init_neighborhoods;
|
||||
uint32_t collision_check;
|
||||
uint32_t init_neighborhoods;
|
||||
uint32_t lockless_reads;
|
||||
} HT_CONFIG;
|
||||
|
||||
/*
|
||||
|
@ -249,7 +250,7 @@ static void ossl_unused ossl_ht_strcase(char *tgt, const char *src, int len)
|
|||
/*
|
||||
* Create a new hashtable
|
||||
*/
|
||||
HT *ossl_ht_new(HT_CONFIG *conf);
|
||||
HT *ossl_ht_new(const HT_CONFIG *conf);
|
||||
|
||||
/*
|
||||
* Frees a hash table, potentially freeing all elements
|
||||
|
|
|
@ -1134,6 +1134,12 @@ int CRYPTO_secure_allocated(const void *ptr)
|
|||
return c_CRYPTO_secure_allocated(ptr);
|
||||
}
|
||||
|
||||
void *CRYPTO_aligned_alloc(size_t num, size_t align, void **freeptr,
|
||||
const char *file, int line)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BIO_snprintf(char *buf, size_t n, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
|
|
@ -230,8 +230,8 @@ static int test_int_hashtable(void)
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
};
|
||||
INTKEY key;
|
||||
int rc = 0;
|
||||
|
@ -408,8 +408,8 @@ static int test_hashtable_stress(void)
|
|||
NULL, /* use default context */
|
||||
hashtable_intfree, /* our free function */
|
||||
hashtable_hash, /* our hash function */
|
||||
1, /* Check collisions */
|
||||
625000, /* preset hash size */
|
||||
1, /* Check collisions */
|
||||
};
|
||||
HT *h;
|
||||
INTKEY key;
|
||||
|
@ -627,8 +627,8 @@ static int test_hashtable_multithread(void)
|
|||
NULL, /* use default context */
|
||||
hashtable_mt_free, /* our free function */
|
||||
NULL, /* default hash function */
|
||||
1, /* Check collisions */
|
||||
0, /* default hash size */
|
||||
1, /* Check collisions */
|
||||
};
|
||||
int ret = 0;
|
||||
thread_t workers[4];
|
||||
|
|
Loading…
Reference in New Issue