test-rcu-list: access n_reclaims and n_nodes_removed with atomic64

To avoid undefined behaviour.

Note that these "atomics" are atomic in the "access once" sense.
The variables are updated by a single thread at a time, so no
"full" atomics are necessary.

Signed-off-by: Emilio G. Cota <cota@braap.org>
Message-Id: <20180910232752.31565-6-cota@braap.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Emilio G. Cota 2018-09-10 19:27:45 -04:00 committed by Paolo Bonzini
parent ac8c77486c
commit 39fe576c82

View File

@ -33,8 +33,8 @@
static QemuMutex counts_mutex; static QemuMutex counts_mutex;
static long long n_reads = 0LL; static long long n_reads = 0LL;
static long long n_updates = 0LL; static long long n_updates = 0LL;
static long long n_reclaims = 0LL; static int64_t n_reclaims;
static long long n_nodes_removed = 0LL; static int64_t n_nodes_removed;
static long long n_nodes = 0LL; static long long n_nodes = 0LL;
static int g_test_in_charge = 0; static int g_test_in_charge = 0;
@ -104,7 +104,7 @@ static void reclaim_list_el(struct rcu_head *prcu)
struct list_element *el = container_of(prcu, struct list_element, rcu); struct list_element *el = container_of(prcu, struct list_element, rcu);
g_free(el); g_free(el);
/* Accessed only from call_rcu thread. */ /* Accessed only from call_rcu thread. */
n_reclaims++; atomic_set_i64(&n_reclaims, n_reclaims + 1);
} }
#if TEST_LIST_TYPE == 1 #if TEST_LIST_TYPE == 1
@ -232,7 +232,7 @@ static void *rcu_q_updater(void *arg)
qemu_mutex_lock(&counts_mutex); qemu_mutex_lock(&counts_mutex);
n_nodes += n_nodes_local; n_nodes += n_nodes_local;
n_updates += n_updates_local; n_updates += n_updates_local;
n_nodes_removed += n_removed_local; atomic_set_i64(&n_nodes_removed, n_nodes_removed + n_removed_local);
qemu_mutex_unlock(&counts_mutex); qemu_mutex_unlock(&counts_mutex);
return NULL; return NULL;
} }
@ -286,19 +286,21 @@ static void rcu_qtest(const char *test, int duration, int nreaders)
n_removed_local++; n_removed_local++;
} }
qemu_mutex_lock(&counts_mutex); qemu_mutex_lock(&counts_mutex);
n_nodes_removed += n_removed_local; atomic_set_i64(&n_nodes_removed, n_nodes_removed + n_removed_local);
qemu_mutex_unlock(&counts_mutex); qemu_mutex_unlock(&counts_mutex);
synchronize_rcu(); synchronize_rcu();
while (n_nodes_removed > n_reclaims) { while (atomic_read_i64(&n_nodes_removed) > atomic_read_i64(&n_reclaims)) {
g_usleep(100); g_usleep(100);
synchronize_rcu(); synchronize_rcu();
} }
if (g_test_in_charge) { if (g_test_in_charge) {
g_assert_cmpint(n_nodes_removed, ==, n_reclaims); g_assert_cmpint(atomic_read_i64(&n_nodes_removed), ==,
atomic_read_i64(&n_reclaims));
} else { } else {
printf("%s: %d readers; 1 updater; nodes read: " \ printf("%s: %d readers; 1 updater; nodes read: " \
"%lld, nodes removed: %lld; nodes reclaimed: %lld\n", "%lld, nodes removed: %"PRIi64"; nodes reclaimed: %"PRIi64"\n",
test, nthreadsrunning - 1, n_reads, n_nodes_removed, n_reclaims); test, nthreadsrunning - 1, n_reads,
atomic_read_i64(&n_nodes_removed), atomic_read_i64(&n_reclaims));
exit(0); exit(0);
} }
} }