Commit 685cc7c0 authored by Emilio G. Cota's avatar Emilio G. Cota Committed by Paolo Bonzini
Browse files

test-rcu-list: abstract the list implementation



So that we can test other implementations.

Signed-off-by: default avatarEmilio G. Cota <cota@braap.org>
Message-Id: <20180819091335.22863-8-cota@braap.org>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 23311b81
Loading
Loading
Loading
Loading
+30 −12
Original line number Diff line number Diff line
@@ -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();
        }