// SPDX-License-Identifier: GPL-2.0

#include <subcmd/parse-options.h>
#include <linux/hw_breakpoint.h>
#include <linux/perf_event.h>
#include <linux/time64.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <pthread.h>
#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include "bench.h"
#include "futex.h"

static struct {
	unsigned int nbreakpoints;
	unsigned int nparallel;
	unsigned int nthreads;
} thread_params = {
	.nbreakpoints = 1,
	.nparallel = 1,
	.nthreads = 1,
};

static const struct option thread_options[] = {
	OPT_UINTEGER('b', "breakpoints", &thread_params.nbreakpoints,
		"Specify amount of breakpoints"),
	OPT_UINTEGER('p', "parallelism", &thread_params.nparallel, "Specify amount of parallelism"),
	OPT_UINTEGER('t', "threads", &thread_params.nthreads, "Specify amount of threads"),
	OPT_END()
};

static const char * const thread_usage[] = {
	"perf bench breakpoint thread <options>",
	NULL
};

struct breakpoint {
	int fd;
	char watched;
};

static int breakpoint_setup(void *addr)
{
	struct perf_event_attr attr = { .size = 0, };
	int fd;

	attr.type = PERF_TYPE_BREAKPOINT;
	attr.size = sizeof(attr);
	attr.inherit = 1;
	attr.exclude_kernel = 1;
	attr.exclude_hv = 1;
	attr.bp_addr = (unsigned long)addr;
	attr.bp_type = HW_BREAKPOINT_RW;
	attr.bp_len = HW_BREAKPOINT_LEN_1;
	fd = syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0);

	if (fd < 0)
		fd = -errno;

	return fd;
}

static void *passive_thread(void *arg)
{
	unsigned int *done = (unsigned int *)arg;

	while (!__atomic_load_n(done, __ATOMIC_RELAXED))
		futex_wait(done, 0, NULL, 0);
	return NULL;
}

static void *active_thread(void *arg)
{
	unsigned int *done = (unsigned int *)arg;

	while (!__atomic_load_n(done, __ATOMIC_RELAXED));
	return NULL;
}

static void *breakpoint_thread(void *arg)
{
	unsigned int i, done;
	int *repeat = (int *)arg;
	pthread_t *threads;

	threads = calloc(thread_params.nthreads, sizeof(threads[0]));
	if (!threads)
		exit((perror("calloc"), EXIT_FAILURE));

	while (__atomic_fetch_sub(repeat, 1, __ATOMIC_RELAXED) > 0) {
		done = 0;
		for (i = 0; i < thread_params.nthreads; i++) {
			if (pthread_create(&threads[i], NULL, passive_thread, &done))
				exit((perror("pthread_create"), EXIT_FAILURE));
		}
		__atomic_store_n(&done, 1, __ATOMIC_RELAXED);
		futex_wake(&done, thread_params.nthreads, 0);
		for (i = 0; i < thread_params.nthreads; i++)
			pthread_join(threads[i], NULL);
	}
	free(threads);
	return NULL;
}

// The benchmark creates nbreakpoints inheritable breakpoints,
// then starts nparallel threads which create and join bench_repeat batches of nthreads threads.
int bench_breakpoint_thread(int argc, const char **argv)
{
	unsigned int i, result_usec;
	int repeat = bench_repeat;
	struct breakpoint *breakpoints;
	pthread_t *parallel;
	struct timeval start, stop, diff;

	if (parse_options(argc, argv, thread_options, thread_usage, 0)) {
		usage_with_options(thread_usage, thread_options);
		exit(EXIT_FAILURE);
	}
	breakpoints = calloc(thread_params.nbreakpoints, sizeof(breakpoints[0]));
	parallel = calloc(thread_params.nparallel, sizeof(parallel[0]));
	if (!breakpoints || !parallel)
		exit((perror("calloc"), EXIT_FAILURE));

	for (i = 0; i < thread_params.nbreakpoints; i++) {
		breakpoints[i].fd = breakpoint_setup(&breakpoints[i].watched);

		if (breakpoints[i].fd < 0) {
			if (breakpoints[i].fd == -ENODEV) {
				printf("Skipping perf bench breakpoint thread: No hardware support\n");
				return 0;
			}
			exit((perror("perf_event_open"), EXIT_FAILURE));
		}
	}
	gettimeofday(&start, NULL);
	for (i = 0; i < thread_params.nparallel; i++) {
		if (pthread_create(&parallel[i], NULL, breakpoint_thread, &repeat))
			exit((perror("pthread_create"), EXIT_FAILURE));
	}
	for (i = 0; i < thread_params.nparallel; i++)
		pthread_join(parallel[i], NULL);
	gettimeofday(&stop, NULL);
	timersub(&stop, &start, &diff);
	for (i = 0; i < thread_params.nbreakpoints; i++)
		close(breakpoints[i].fd);
	free(parallel);
	free(breakpoints);
	switch (bench_format) {
	case BENCH_FORMAT_DEFAULT:
		printf("# Created/joined %d threads with %d breakpoints and %d parallelism\n",
			bench_repeat, thread_params.nbreakpoints, thread_params.nparallel);
		printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
			(long)diff.tv_sec, (long)(diff.tv_usec / USEC_PER_MSEC));
		result_usec = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
		printf(" %14lf usecs/op\n",
			(double)result_usec / bench_repeat / thread_params.nthreads);
		printf(" %14lf usecs/op/cpu\n",
			(double)result_usec / bench_repeat /
			thread_params.nthreads * thread_params.nparallel);
		break;
	case BENCH_FORMAT_SIMPLE:
		printf("%lu.%03lu\n", (long)diff.tv_sec, (long)(diff.tv_usec / USEC_PER_MSEC));
		break;
	default:
		fprintf(stderr, "Unknown format: %d\n", bench_format);
		exit(EXIT_FAILURE);
	}
	return 0;
}

static struct {
	unsigned int npassive;
	unsigned int nactive;
} enable_params = {
	.nactive = 0,
	.npassive = 0,
};

static const struct option enable_options[] = {
	OPT_UINTEGER('p', "passive", &enable_params.npassive, "Specify amount of passive threads"),
	OPT_UINTEGER('a', "active", &enable_params.nactive, "Specify amount of active threads"),
	OPT_END()
};

static const char * const enable_usage[] = {
	"perf bench breakpoint enable <options>",
	NULL
};

// The benchmark creates an inheritable breakpoint,
// then starts npassive threads that block and nactive threads that actively spin
// and then disables and enables the breakpoint bench_repeat times.
int bench_breakpoint_enable(int argc, const char **argv)
{
	unsigned int i, nthreads, result_usec, done = 0;
	char watched;
	int fd;
	pthread_t *threads;
	struct timeval start, stop, diff;

	if (parse_options(argc, argv, enable_options, enable_usage, 0)) {
		usage_with_options(enable_usage, enable_options);
		exit(EXIT_FAILURE);
	}
	fd = breakpoint_setup(&watched);

	if (fd < 0) {
		if (fd == -ENODEV) {
			printf("Skipping perf bench breakpoint enable: No hardware support\n");
			return 0;
		}
		exit((perror("perf_event_open"), EXIT_FAILURE));
	}
	nthreads = enable_params.npassive + enable_params.nactive;
	threads = calloc(nthreads, sizeof(threads[0]));
	if (!threads)
		exit((perror("calloc"), EXIT_FAILURE));

	for (i = 0; i < nthreads; i++) {
		if (pthread_create(&threads[i], NULL,
			i < enable_params.npassive ? passive_thread : active_thread, &done))
			exit((perror("pthread_create"), EXIT_FAILURE));
	}
	usleep(10000);  // let the threads block
	gettimeofday(&start, NULL);
	for (i = 0; i < bench_repeat; i++) {
		if (ioctl(fd, PERF_EVENT_IOC_DISABLE, 0))
			exit((perror("ioctl(PERF_EVENT_IOC_DISABLE)"), EXIT_FAILURE));
		if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0))
			exit((perror("ioctl(PERF_EVENT_IOC_ENABLE)"), EXIT_FAILURE));
	}
	gettimeofday(&stop, NULL);
	timersub(&stop, &start, &diff);
	__atomic_store_n(&done, 1, __ATOMIC_RELAXED);
	futex_wake(&done, enable_params.npassive, 0);
	for (i = 0; i < nthreads; i++)
		pthread_join(threads[i], NULL);
	free(threads);
	close(fd);
	switch (bench_format) {
	case BENCH_FORMAT_DEFAULT:
		printf("# Enabled/disabled breakpoint %d time with %d passive and %d active threads\n",
			bench_repeat, enable_params.npassive, enable_params.nactive);
		printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
			(long)diff.tv_sec, (long)(diff.tv_usec / USEC_PER_MSEC));
		result_usec = diff.tv_sec * USEC_PER_SEC + diff.tv_usec;
		printf(" %14lf usecs/op\n", (double)result_usec / bench_repeat);
		break;
	case BENCH_FORMAT_SIMPLE:
		printf("%lu.%03lu\n", (long)diff.tv_sec, (long)(diff.tv_usec / USEC_PER_MSEC));
		break;
	default:
		fprintf(stderr, "Unknown format: %d\n", bench_format);
		exit(EXIT_FAILURE);
	}
	return 0;
}
