// SPDX-License-Identifier: GPL-2.0
#include <inttypes.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include "debug.h"
#include "tests.h"
#include "machine.h"
#include "thread_map.h"
#include "symbol.h"
#include "thread.h"
#include "util.h"

#define THREADS 4

static int go_away;

struct thread_data {
	pthread_t	pt;
	pid_t		tid;
	void		*map;
	int		ready[2];
};

static struct thread_data threads[THREADS];

static int thread_init(struct thread_data *td)
{
	void *map;

	map = mmap(NULL, page_size,
		   PROT_READ|PROT_WRITE|PROT_EXEC,
		   MAP_SHARED|MAP_ANONYMOUS, -1, 0);

	if (map == MAP_FAILED) {
		perror("mmap failed");
		return -1;
	}

	td->map = map;
	td->tid = syscall(SYS_gettid);

	pr_debug("tid = %d, map = %p\n", td->tid, map);
	return 0;
}

static void *thread_fn(void *arg)
{
	struct thread_data *td = arg;
	ssize_t ret;
	int go;

	if (thread_init(td))
		return NULL;

	/* Signal thread_create thread is initialized. */
	ret = write(td->ready[1], &go, sizeof(int));
	if (ret != sizeof(int)) {
		pr_err("failed to notify\n");
		return NULL;
	}

	while (!go_away) {
		/* Waiting for main thread to kill us. */
		usleep(100);
	}

	munmap(td->map, page_size);
	return NULL;
}

static int thread_create(int i)
{
	struct thread_data *td = &threads[i];
	int err, go;

	if (pipe(td->ready))
		return -1;

	err = pthread_create(&td->pt, NULL, thread_fn, td);
	if (!err) {
		/* Wait for thread initialization. */
		ssize_t ret = read(td->ready[0], &go, sizeof(int));
		err = ret != sizeof(int);
	}

	close(td->ready[0]);
	close(td->ready[1]);
	return err;
}

static int threads_create(void)
{
	struct thread_data *td0 = &threads[0];
	int i, err = 0;

	go_away = 0;

	/* 0 is main thread */
	if (thread_init(td0))
		return -1;

	for (i = 1; !err && i < THREADS; i++)
		err = thread_create(i);

	return err;
}

static int threads_destroy(void)
{
	struct thread_data *td0 = &threads[0];
	int i, err = 0;

	/* cleanup the main thread */
	munmap(td0->map, page_size);

	go_away = 1;

	for (i = 1; !err && i < THREADS; i++)
		err = pthread_join(threads[i].pt, NULL);

	return err;
}

typedef int (*synth_cb)(struct machine *machine);

static int synth_all(struct machine *machine)
{
	return perf_event__synthesize_threads(NULL,
					      perf_event__process,
					      machine, 0, 1);
}

static int synth_process(struct machine *machine)
{
	struct thread_map *map;
	int err;

	map = thread_map__new_by_pid(getpid());

	err = perf_event__synthesize_thread_map(NULL, map,
						perf_event__process,
						machine, 0);

	thread_map__put(map);
	return err;
}

static int mmap_events(synth_cb synth)
{
	struct machine *machine;
	int err, i;

	/*
	 * The threads_create will not return before all threads
	 * are spawned and all created memory map.
	 *
	 * They will loop until threads_destroy is called, so we
	 * can safely run synthesizing function.
	 */
	TEST_ASSERT_VAL("failed to create threads", !threads_create());

	machine = machine__new_host();

	dump_trace = verbose > 1 ? 1 : 0;

	err = synth(machine);

	dump_trace = 0;

	TEST_ASSERT_VAL("failed to destroy threads", !threads_destroy());
	TEST_ASSERT_VAL("failed to synthesize maps", !err);

	/*
	 * All data is synthesized, try to find map for each
	 * thread object.
	 */
	for (i = 0; i < THREADS; i++) {
		struct thread_data *td = &threads[i];
		struct addr_location al;
		struct thread *thread;

		thread = machine__findnew_thread(machine, getpid(), td->tid);

		pr_debug("looking for map %p\n", td->map);

		thread__find_map(thread, PERF_RECORD_MISC_USER,
				 (unsigned long) (td->map + 1), &al);

		thread__put(thread);

		if (!al.map) {
			pr_debug("failed, couldn't find map\n");
			err = -1;
			break;
		}

		pr_debug("map %p, addr %" PRIx64 "\n", al.map, al.map->start);
	}

	machine__delete_threads(machine);
	machine__delete(machine);
	return err;
}

/*
 * This test creates 'THREADS' number of threads (including
 * main thread) and each thread creates memory map.
 *
 * When threads are created, we synthesize them with both
 * (separate tests):
 *   perf_event__synthesize_thread_map (process based)
 *   perf_event__synthesize_threads    (global)
 *
 * We test we can find all memory maps via:
 *   thread__find_map
 *
 * by using all thread objects.
 */
int test__mmap_thread_lookup(struct test *test __maybe_unused, int subtest __maybe_unused)
{
	/* perf_event__synthesize_threads synthesize */
	TEST_ASSERT_VAL("failed with sythesizing all",
			!mmap_events(synth_all));

	/* perf_event__synthesize_thread_map synthesize */
	TEST_ASSERT_VAL("failed with sythesizing process",
			!mmap_events(synth_process));

	return 0;
}
