Skip to content

Commit

Permalink
Fix threadstest wrapping again
Browse files Browse the repository at this point in the history
It turns out that (particularly on macosx 14), its possible that
stochastic scheduling will result in the write side of the rcu test
running frequently, resulting in wraps of the counter used in the test
(even when its a uint64_t).  Address this by allowing single wraps of
the counter (i.e. the old value of the counter can be larger than the
new value, but only once).  Only fail the test if multiple iterations
find that the counter has gone backwards
  • Loading branch information
nhorman committed Mar 25, 2024
1 parent 01eaf20 commit bd0c1e7
Showing 1 changed file with 33 additions and 4 deletions.
37 changes: 33 additions & 4 deletions test/threadstest.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,6 @@ static int writer2_iterations = 0;
static uint64_t *writer_ptr = NULL;
static uint64_t global_ctr = 0;
static int rcu_torture_result = 1;

static void free_old_rcu_data(void *data)
{
CRYPTO_free(data, NULL, 0);
Expand Down Expand Up @@ -348,6 +347,9 @@ static void writer2_fn(void)
CRYPTO_atomic_add(&writer2_done, 1, &local, NULL);
}

#define NO_WRAP 0
#define WRAPPED_LAST_ITER 1
#define BETTER_NOT_WRAP 2
static void reader_fn(int *iterations)
{
unsigned int count = 0;
Expand All @@ -356,6 +358,7 @@ static void reader_fn(int *iterations)
uint64_t oldval = 0;
int lw1 = 0;
int lw2 = 0;
int wrap = NO_WRAP;

while (lw1 != 1 || lw2 != 1) {
CRYPTO_atomic_add(&writer1_done, 0, &lw1, NULL);
Expand All @@ -364,9 +367,35 @@ static void reader_fn(int *iterations)
ossl_rcu_read_lock(rcu_lock);
valp = ossl_rcu_deref(&writer_ptr);
val = (valp == NULL) ? 0 : *valp;
if (oldval > val) {
TEST_info("rcu torture value went backwards!");
rcu_torture_result = 0;

/*
* If we didn't wrap before, and we see a wrap
* condition, mark it as such
*/
if (oldval > val && wrap == NO_WRAP) {
wrap = WRAPPED_LAST_ITER;
}

/*
* If this iteration wrapped, indicate that
* its ok, but we better not wrap again
*/
if (wrap == WRAPPED_LAST_ITER) {
wrap = BETTER_NOT_WRAP;
} else {
/*
* We get here if we've wrapped once, but we better not go
* backwards again
*/
if (oldval > val) {
TEST_info("rcu torture value went backwards! %llu : %llu", (unsigned long long)oldval, (unsigned long long)val);
rcu_torture_result = 0;
} else {
/*
* If we get here, we've successfully wrapped, and can continue
*/
wrap = NO_WRAP;
}
}
oldval = val; /* just try to deref the pointer */
ossl_rcu_read_unlock(rcu_lock);
Expand Down

0 comments on commit bd0c1e7

Please sign in to comment.