/*
 * rcuq_test.c
 *
 * usage: rcuq_test <readers> <duration>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Copyright (c) 2013 Mike D. Day, IBM Corporation.
 */

#include <glib.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "qemu/atomic.h"
#include "qemu/rcu.h"
#include "qemu/compiler.h"
#include "qemu/osdep.h"
#include "qemu/thread.h"
#include "qemu/rcu_queue.h"

/*
 * Test variables.
 */

long long n_reads = 0LL;
long long n_updates = 0LL;
long long n_reclaims = 0LL;
long long n_nodes_removed = 0LL;
long long n_nodes = 0LL;
int g_test_in_charge = 0;

int nthreadsrunning;

char argsbuf[64];

#define GOFLAG_INIT 0
#define GOFLAG_RUN  1
#define GOFLAG_STOP 2

static volatile int goflag = GOFLAG_INIT;

#define RCU_READ_RUN 1000
#define RCU_UPDATE_RUN 10
#define NR_THREADS 100
#define RCU_Q_LEN 100

static QemuThread threads[NR_THREADS];
static struct rcu_reader_data *data[NR_THREADS];
static int n_threads;

static int select_random_el(int max)
{
    return (rand() % max);
}


static void create_thread(void *(*func)(void *))
{
    if (n_threads >= NR_THREADS) {
        fprintf(stderr, "Thread limit of %d exceeded!\n", NR_THREADS);
        exit(-1);
    }
    qemu_thread_create(&threads[n_threads], "test", func, &data[n_threads],
                       QEMU_THREAD_JOINABLE);
    n_threads++;
}

static void wait_all_threads(void)
{
    int i;

    for (i = 0; i < n_threads; i++) {
        qemu_thread_join(&threads[i]);
    }
    n_threads = 0;
}


struct list_element {
    QLIST_ENTRY(list_element) entry;
    struct rcu_head rcu;
    long long val;
};

static void reclaim_list_el(struct rcu_head *prcu)
{
    struct list_element *el = container_of(prcu, struct list_element, rcu);
    g_free(el);
    atomic_add(&n_reclaims, 1);
}

static QLIST_HEAD(q_list_head, list_element) Q_list_head;

static void *rcu_q_reader(void *arg)
{
    long long j, n_reads_local = 0;
    struct list_element *el;

    *(struct rcu_reader_data **)arg = &rcu_reader;
    atomic_inc(&nthreadsrunning);
    while (goflag == GOFLAG_INIT) {
        g_usleep(1000);
    }

    while (goflag == GOFLAG_RUN) {
        rcu_read_lock();
        QLIST_FOREACH_RCU(el, &Q_list_head, entry) {
            j = atomic_read(&el->val);
            (void)j;
            n_reads_local++;
            if (goflag == GOFLAG_STOP) {
                break;
            }
        }
        rcu_read_unlock();

        g_usleep(100);
    }
    atomic_add(&n_reads, n_reads_local);
    return NULL;
}


static void *rcu_q_updater(void *arg)
{
    int j, target_el;
    long long n_updates_local = 0;
    long long n_removed_local = 0;
    struct list_element *el, *prev_el;

    *(struct rcu_reader_data **)arg = &rcu_reader;
    atomic_inc(&nthreadsrunning);
    while (goflag == GOFLAG_INIT) {
        g_usleep(1000);
    }

    while (goflag == GOFLAG_RUN) {
        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) {
            j++;
            if (target_el == j) {
                QLIST_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++;
                break;
            }
        }
        if (goflag == GOFLAG_STOP) {
            break;
        }
        target_el = select_random_el(RCU_Q_LEN);
        j = 0;
        QLIST_FOREACH_RCU(el, &Q_list_head, entry) {
            j++;
            if (target_el == j) {
                prev_el = g_new(struct list_element, 1);
                atomic_add(&n_nodes, 1);
                prev_el->val = atomic_read(&n_nodes);
                QLIST_INSERT_BEFORE_RCU(el, prev_el, entry);
                break;
            }
        }

        n_updates_local += 2;
        synchronize_rcu();
    }
    synchronize_rcu();
    atomic_add(&n_updates, n_updates_local);
    atomic_add(&n_nodes_removed, n_removed_local);
    return NULL;
}

static void rcu_qtest_init(void)
{
    struct list_element *new_el;
    int i;
    nthreadsrunning = 0;
    srand(time(0));
    for (i = 0; i < RCU_Q_LEN; i++) {
        new_el = g_new(struct list_element, 1);
        new_el->val = i;
        QLIST_INSERT_HEAD_RCU(&Q_list_head, new_el, entry);
    }
    atomic_add(&n_nodes, RCU_Q_LEN);
}

static void rcu_qtest_run(int duration, int nreaders)
{
    int nthreads = nreaders + 1;
    while (atomic_read(&nthreadsrunning) < nthreads) {
        g_usleep(1000);
    }

    goflag = GOFLAG_RUN;
    sleep(duration);
    goflag = GOFLAG_STOP;
    wait_all_threads();
}


static void rcu_qtest(const char *test, int duration, int nreaders)
{
    int i;
    long long n_removed_local = 0;

    struct list_element *el, *prev_el;

    rcu_qtest_init();
    for (i = 0; i < nreaders; i++) {
        create_thread(rcu_q_reader);
    }
    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);
        call_rcu1(&prev_el->rcu, reclaim_list_el);
        n_removed_local++;
    }
    atomic_add(&n_nodes_removed, n_removed_local);
    synchronize_rcu();
    while (n_nodes_removed > n_reclaims) {
        g_usleep(100);
        synchronize_rcu();
    }
    if (g_test_in_charge) {
        g_assert_cmpint(n_nodes_removed, ==, n_reclaims);
    } else {
        printf("%s: %d readers; 1 updater; nodes read: "  \
               "%lld, nodes removed: %lld; nodes reclaimed: %lld\n",
               test, nthreadsrunning - 1, n_reads, n_nodes_removed, n_reclaims);
        exit(0);
    }
}

static void usage(int argc, char *argv[])
{
    fprintf(stderr, "Usage: %s duration nreaders\n", argv[0]);
    exit(-1);
}

static int gtest_seconds;

static void gtest_rcuq_one(void)
{
    rcu_qtest("rcuqtest", gtest_seconds / 4, 1);
}

static void gtest_rcuq_few(void)
{
    rcu_qtest("rcuqtest", gtest_seconds / 4, 5);
}

static void gtest_rcuq_many(void)
{
    rcu_qtest("rcuqtest", gtest_seconds / 2, 20);
}


int main(int argc, char *argv[])
{
    int duration = 0, readers = 0;

    if (argc >= 2) {
        if (argv[1][0] == '-') {
            g_test_init(&argc, &argv, NULL);
            if (g_test_quick()) {
                gtest_seconds = 4;
            } 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_in_charge = 1;
            return g_test_run();
        }
        duration = strtoul(argv[1], NULL, 0);
    }
    if (argc >= 3) {
        readers = strtoul(argv[2], NULL, 0);
    }
    if (duration && readers) {
        rcu_qtest(argv[0], duration, readers);
        return 0;
    }

    usage(argc, argv);
    return -1;
}
