/*
 * Copyright (C) 2016 Red Hat, Inc.
 * Author: Michael S. Tsirkin <mst@redhat.com>
 * This work is licensed under the terms of the GNU GPL, version 2.
 *
 * Command line processing and common functions for ring benchmarking.
 */
#define _GNU_SOURCE
#include <getopt.h>
#include <pthread.h>
#include <assert.h>
#include <sched.h>
#include "main.h"
#include <sys/eventfd.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>

int runcycles = 10000000;
int max_outstanding = INT_MAX;
int batch = 1;
int param = 0;

bool do_sleep = false;
bool do_relax = false;
bool do_exit = true;

unsigned ring_size = 256;

static int kickfd = -1;
static int callfd = -1;

void notify(int fd)
{
	unsigned long long v = 1;
	int r;

	vmexit();
	r = write(fd, &v, sizeof v);
	assert(r == sizeof v);
	vmentry();
}

void wait_for_notify(int fd)
{
	unsigned long long v = 1;
	int r;

	vmexit();
	r = read(fd, &v, sizeof v);
	assert(r == sizeof v);
	vmentry();
}

void kick(void)
{
	notify(kickfd);
}

void wait_for_kick(void)
{
	wait_for_notify(kickfd);
}

void call(void)
{
	notify(callfd);
}

void wait_for_call(void)
{
	wait_for_notify(callfd);
}

void set_affinity(const char *arg)
{
	cpu_set_t cpuset;
	int ret;
	pthread_t self;
	long int cpu;
	char *endptr;

	if (!arg)
		return;

	cpu = strtol(arg, &endptr, 0);
	assert(!*endptr);

	assert(cpu >= 0 && cpu < CPU_SETSIZE);

	self = pthread_self();
	CPU_ZERO(&cpuset);
	CPU_SET(cpu, &cpuset);

	ret = pthread_setaffinity_np(self, sizeof(cpu_set_t), &cpuset);
	assert(!ret);
}

void poll_used(void)
{
	while (used_empty())
		busy_wait();
}

static void __attribute__((__flatten__)) run_guest(void)
{
	int completed_before;
	int completed = 0;
	int started = 0;
	int bufs = runcycles;
	int spurious = 0;
	int r;
	unsigned len;
	void *buf;
	int tokick = batch;

	for (;;) {
		if (do_sleep)
			disable_call();
		completed_before = completed;
		do {
			if (started < bufs &&
			    started - completed < max_outstanding) {
				r = add_inbuf(0, "Buffer\n", "Hello, world!");
				if (__builtin_expect(r == 0, true)) {
					++started;
					if (!--tokick) {
						tokick = batch;
						if (do_sleep)
							kick_available();
					}

				}
			} else
				r = -1;

			/* Flush out completed bufs if any */
			if (get_buf(&len, &buf)) {
				++completed;
				if (__builtin_expect(completed == bufs, false))
					return;
				r = 0;
			}
		} while (r == 0);
		if (completed == completed_before)
			++spurious;
		assert(completed <= bufs);
		assert(started <= bufs);
		if (do_sleep) {
			if (used_empty() && enable_call())
				wait_for_call();
		} else {
			poll_used();
		}
	}
}

void poll_avail(void)
{
	while (avail_empty())
		busy_wait();
}

static void __attribute__((__flatten__)) run_host(void)
{
	int completed_before;
	int completed = 0;
	int spurious = 0;
	int bufs = runcycles;
	unsigned len;
	void *buf;

	for (;;) {
		if (do_sleep) {
			if (avail_empty() && enable_kick())
				wait_for_kick();
		} else {
			poll_avail();
		}
		if (do_sleep)
			disable_kick();
		completed_before = completed;
		while (__builtin_expect(use_buf(&len, &buf), true)) {
			if (do_sleep)
				call_used();
			++completed;
			if (__builtin_expect(completed == bufs, false))
				return;
		}
		if (completed == completed_before)
			++spurious;
		assert(completed <= bufs);
		if (completed == bufs)
			break;
	}
}

void *start_guest(void *arg)
{
	set_affinity(arg);
	run_guest();
	pthread_exit(NULL);
}

void *start_host(void *arg)
{
	set_affinity(arg);
	run_host();
	pthread_exit(NULL);
}

static const char optstring[] = "";
static const struct option longopts[] = {
	{
		.name = "help",
		.has_arg = no_argument,
		.val = 'h',
	},
	{
		.name = "host-affinity",
		.has_arg = required_argument,
		.val = 'H',
	},
	{
		.name = "guest-affinity",
		.has_arg = required_argument,
		.val = 'G',
	},
	{
		.name = "ring-size",
		.has_arg = required_argument,
		.val = 'R',
	},
	{
		.name = "run-cycles",
		.has_arg = required_argument,
		.val = 'C',
	},
	{
		.name = "outstanding",
		.has_arg = required_argument,
		.val = 'o',
	},
	{
		.name = "batch",
		.has_arg = required_argument,
		.val = 'b',
	},
	{
		.name = "param",
		.has_arg = required_argument,
		.val = 'p',
	},
	{
		.name = "sleep",
		.has_arg = no_argument,
		.val = 's',
	},
	{
		.name = "relax",
		.has_arg = no_argument,
		.val = 'x',
	},
	{
		.name = "exit",
		.has_arg = no_argument,
		.val = 'e',
	},
	{
	}
};

static void help(void)
{
	fprintf(stderr, "Usage: <test> [--help]"
		" [--host-affinity H]"
		" [--guest-affinity G]"
		" [--ring-size R (default: %d)]"
		" [--run-cycles C (default: %d)]"
		" [--batch b]"
		" [--outstanding o]"
		" [--param p]"
		" [--sleep]"
		" [--relax]"
		" [--exit]"
		"\n",
		ring_size,
		runcycles);
}

int main(int argc, char **argv)
{
	int ret;
	pthread_t host, guest;
	void *tret;
	char *host_arg = NULL;
	char *guest_arg = NULL;
	char *endptr;
	long int c;

	kickfd = eventfd(0, 0);
	assert(kickfd >= 0);
	callfd = eventfd(0, 0);
	assert(callfd >= 0);

	for (;;) {
		int o = getopt_long(argc, argv, optstring, longopts, NULL);
		switch (o) {
		case -1:
			goto done;
		case '?':
			help();
			exit(2);
		case 'H':
			host_arg = optarg;
			break;
		case 'G':
			guest_arg = optarg;
			break;
		case 'R':
			ring_size = strtol(optarg, &endptr, 0);
			assert(ring_size && !(ring_size & (ring_size - 1)));
			assert(!*endptr);
			break;
		case 'C':
			c = strtol(optarg, &endptr, 0);
			assert(!*endptr);
			assert(c > 0 && c < INT_MAX);
			runcycles = c;
			break;
		case 'o':
			c = strtol(optarg, &endptr, 0);
			assert(!*endptr);
			assert(c > 0 && c < INT_MAX);
			max_outstanding = c;
			break;
		case 'p':
			c = strtol(optarg, &endptr, 0);
			assert(!*endptr);
			assert(c > 0 && c < INT_MAX);
			param = c;
			break;
		case 'b':
			c = strtol(optarg, &endptr, 0);
			assert(!*endptr);
			assert(c > 0 && c < INT_MAX);
			batch = c;
			break;
		case 's':
			do_sleep = true;
			break;
		case 'x':
			do_relax = true;
			break;
		case 'e':
			do_exit = true;
			break;
		default:
			help();
			exit(4);
			break;
		}
	}

	/* does nothing here, used to make sure all smp APIs compile */
	smp_acquire();
	smp_release();
	smp_mb();
done:

	if (batch > max_outstanding)
		batch = max_outstanding;

	if (optind < argc) {
		help();
		exit(4);
	}
	alloc_ring();

	ret = pthread_create(&host, NULL, start_host, host_arg);
	assert(!ret);
	ret = pthread_create(&guest, NULL, start_guest, guest_arg);
	assert(!ret);

	ret = pthread_join(guest, &tret);
	assert(!ret);
	ret = pthread_join(host, &tret);
	assert(!ret);
	return 0;
}
