test-rcu-list: abstract the list implementation

So that we can test other implementations.

Signed-off-by: Emilio G. Cota <cota@braap.org>
Message-Id: <20180819091335.22863-8-cota@braap.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Emilio G. Cota 2018-08-19 05:13:31 -04:00 committed by Paolo Bonzini
parent 23311b8182
commit 685cc7c0ec

View file

@ -82,9 +82,16 @@ static void wait_all_threads(void)
n_threads = 0;
}
#ifndef TEST_LIST_TYPE
#define TEST_LIST_TYPE 1
#endif
struct list_element {
#if TEST_LIST_TYPE == 1
QLIST_ENTRY(list_element) entry;
#else
#error Invalid TEST_LIST_TYPE
#endif
struct rcu_head rcu;
};
@ -96,8 +103,19 @@ static void reclaim_list_el(struct rcu_head *prcu)
n_reclaims++;
}
#if TEST_LIST_TYPE == 1
static QLIST_HEAD(q_list_head, list_element) Q_list_head;
#define TEST_NAME "qlist"
#define TEST_LIST_REMOVE_RCU QLIST_REMOVE_RCU
#define TEST_LIST_INSERT_AFTER_RCU QLIST_INSERT_AFTER_RCU
#define TEST_LIST_INSERT_HEAD_RCU QLIST_INSERT_HEAD_RCU
#define TEST_LIST_FOREACH_RCU QLIST_FOREACH_RCU
#define TEST_LIST_FOREACH_SAFE_RCU QLIST_FOREACH_SAFE_RCU
#else
#error Invalid TEST_LIST_TYPE
#endif
static void *rcu_q_reader(void *arg)
{
long long n_reads_local = 0;
@ -113,7 +131,7 @@ static void *rcu_q_reader(void *arg)
while (atomic_read(&goflag) == GOFLAG_RUN) {
rcu_read_lock();
QLIST_FOREACH_RCU(el, &Q_list_head, entry) {
TEST_LIST_FOREACH_RCU(el, &Q_list_head, entry) {
n_reads_local++;
if (atomic_read(&goflag) == GOFLAG_STOP) {
break;
@ -150,10 +168,10 @@ static void *rcu_q_updater(void *arg)
target_el = select_random_el(RCU_Q_LEN);
j = 0;
/* FOREACH_RCU could work here but let's use both macros */
QLIST_FOREACH_SAFE_RCU(prev_el, &Q_list_head, entry, el) {
TEST_LIST_FOREACH_SAFE_RCU(prev_el, &Q_list_head, entry, el) {
j++;
if (target_el == j) {
QLIST_REMOVE_RCU(prev_el, entry);
TEST_LIST_REMOVE_RCU(prev_el, entry);
/* may be more than one updater in the future */
call_rcu1(&prev_el->rcu, reclaim_list_el);
n_removed_local++;
@ -165,12 +183,12 @@ static void *rcu_q_updater(void *arg)
}
target_el = select_random_el(RCU_Q_LEN);
j = 0;
QLIST_FOREACH_RCU(el, &Q_list_head, entry) {
TEST_LIST_FOREACH_RCU(el, &Q_list_head, entry) {
j++;
if (target_el == j) {
prev_el = g_new(struct list_element, 1);
struct list_element *new_el = g_new(struct list_element, 1);
n_nodes += n_nodes_local;
QLIST_INSERT_BEFORE_RCU(el, prev_el, entry);
TEST_LIST_INSERT_AFTER_RCU(el, new_el, entry);
break;
}
}
@ -195,7 +213,7 @@ static void rcu_qtest_init(void)
srand(time(0));
for (i = 0; i < RCU_Q_LEN; i++) {
new_el = g_new(struct list_element, 1);
QLIST_INSERT_HEAD_RCU(&Q_list_head, new_el, entry);
TEST_LIST_INSERT_HEAD_RCU(&Q_list_head, new_el, entry);
}
qemu_mutex_lock(&counts_mutex);
n_nodes += RCU_Q_LEN;
@ -230,8 +248,8 @@ static void rcu_qtest(const char *test, int duration, int nreaders)
create_thread(rcu_q_updater);
rcu_qtest_run(duration, nreaders);
QLIST_FOREACH_SAFE_RCU(prev_el, &Q_list_head, entry, el) {
QLIST_REMOVE_RCU(prev_el, entry);
TEST_LIST_FOREACH_SAFE_RCU(prev_el, &Q_list_head, entry, el) {
TEST_LIST_REMOVE_RCU(prev_el, entry);
call_rcu1(&prev_el->rcu, reclaim_list_el);
n_removed_local++;
}
@ -290,9 +308,9 @@ int main(int argc, char *argv[])
} else {
gtest_seconds = 20;
}
g_test_add_func("/rcu/qlist/single-threaded", gtest_rcuq_one);
g_test_add_func("/rcu/qlist/short-few", gtest_rcuq_few);
g_test_add_func("/rcu/qlist/long-many", gtest_rcuq_many);
g_test_add_func("/rcu/"TEST_NAME"/single-threaded", gtest_rcuq_one);
g_test_add_func("/rcu/"TEST_NAME"/short-few", gtest_rcuq_few);
g_test_add_func("/rcu/"TEST_NAME"/long-many", gtest_rcuq_many);
g_test_in_charge = 1;
return g_test_run();
}