/*
 * 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;

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 = "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]"
		" [--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 '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;
}
