/*
 * Copyright (c) 2018 Google, Inc.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * A task alternates between being big and small. Max up and down migration
 * latencies and task placement are verified.
 */

#define _GNU_SOURCE
#include <errno.h>
#include <pthread.h>
#include <sched.h>
#include <time.h>

#include "tst_test.h"
#include "tst_safe_file_ops.h"
#include "tst_safe_pthread.h"

#include "trace_parse.h"
#include "util.h"

#define TRACE_EVENTS "sched_switch"

static int task_tid;

#define MAX_UPMIGRATE_LATENCY_US 100000
#define MAX_DOWNMIGRATE_LATENCY_US 100000
#define MAX_INCORRECT_CLUSTER_PCT 10
#define BURN_SEC 1
#define NUM_LOOPS 10
static void *task_fn(void *arg LTP_ATTRIBUTE_UNUSED)
{
	int loops = NUM_LOOPS;

	task_tid = gettid();

	while (loops--) {
		tracefs_write("trace_marker", "SMALL TASK");
		burn(BURN_SEC * USEC_PER_SEC, 1);

		tracefs_write("trace_marker", "CPU HOG");
		burn(BURN_SEC * USEC_PER_SEC, 0);
	}

	return NULL;
}

static int parse_results(void)
{
	int i, pct, rv = 0;
	unsigned long long exec_start_us = 0;
	unsigned long long too_big_cpu_us = 0;
	unsigned long long too_small_cpu_us = 0;
	unsigned long long small_task_us = 0;
	unsigned long long big_task_us = 0;
	unsigned long long smalltask_ts_usec = 0;
	unsigned long long cpuhog_ts_usec = 0;
	unsigned long long upmigrate_ts_usec = 0;
	unsigned long long downmigrate_ts_usec = 0;
	unsigned long long max_upmigrate_latency_usec = 0;
	unsigned long long max_downmigrate_latency_usec = 0;
	cpu_set_t cpuset;

	if (find_cpus_with_capacity(0, &cpuset)) {
		printf("Failed to find the CPUs in the little cluster.\n");
		return -1;
	}

	for (i = 0; i < num_trace_records; i++) {
		unsigned long long segment_us;
		struct trace_sched_switch *t = trace[i].event_data;

		if (trace[i].event_type == TRACE_RECORD_TRACING_MARK_WRITE) {
			if (!strcmp(trace[i].event_data, "CPU HOG")) {
				/* Task is transitioning to cpu hog. */
				cpuhog_ts_usec = TS_TO_USEC(trace[i].ts);
				if (downmigrate_ts_usec) {
					unsigned long long temp_latency;
					temp_latency = downmigrate_ts_usec -
						smalltask_ts_usec;
					if (temp_latency >
					    max_downmigrate_latency_usec)
						max_downmigrate_latency_usec =
							temp_latency;
				} else if (smalltask_ts_usec) {
					printf("Warning: small task never "
					       "downmigrated.\n");
					rv = 1;
				}
				downmigrate_ts_usec = 0;
				smalltask_ts_usec = 0;
			} else if (!strcmp(trace[i].event_data, "SMALL TASK")) {
				smalltask_ts_usec = TS_TO_USEC(trace[i].ts);
				if (upmigrate_ts_usec) {
					unsigned long long temp_latency;
					temp_latency = upmigrate_ts_usec -
						cpuhog_ts_usec;
					if (temp_latency >
					    max_upmigrate_latency_usec)
						max_upmigrate_latency_usec =
							temp_latency;
				} else if (cpuhog_ts_usec) {
					printf("Warning: big task never "
					       "upmigrated.\n");
					rv = 1;
				}
				upmigrate_ts_usec = 0;
				cpuhog_ts_usec = 0;
			}
			continue;
		}

		if (trace[i].event_type != TRACE_RECORD_SCHED_SWITCH)
			continue;
		if (t->next_pid == task_tid) {
			/* Start of task execution segment. */
			if (exec_start_us) {
				printf("Trace parse fail: double exec start\n");
				return -1;
			}
			exec_start_us = TS_TO_USEC(trace[i].ts);
			if (cpuhog_ts_usec && !upmigrate_ts_usec &&
			    !CPU_ISSET(trace[i].cpu, &cpuset))
				upmigrate_ts_usec = exec_start_us;
			if (smalltask_ts_usec && !downmigrate_ts_usec &&
			    CPU_ISSET(trace[i].cpu, &cpuset))
				downmigrate_ts_usec = exec_start_us;
			continue;
		}
		if (t->prev_pid != task_tid)
			continue;
		/* End of task execution segment. */
		segment_us = TS_TO_USEC(trace[i].ts);
		segment_us -= exec_start_us;
		exec_start_us = 0;
		if (CPU_ISSET(trace[i].cpu, &cpuset)) {
			/* Task is running on little CPUs. */
			if (cpuhog_ts_usec) {
				/*
				 * Upmigration is accounted separately, so only
				 * record mis-scheduled time here if it happened
				 * after upmigration.
				 */
				if (upmigrate_ts_usec)
					too_small_cpu_us += segment_us;
			}
		} else {
			/* Task is running on big CPUs. */
			if (smalltask_ts_usec) {
				/*
				 * Downmigration is accounted separately, so
				 * only record mis-scheduled time here if it
				 * happened after downmigration.
				 */
				if (downmigrate_ts_usec)
					too_big_cpu_us += segment_us;
			}
		}
		if (cpuhog_ts_usec)
			big_task_us += segment_us;
		if (smalltask_ts_usec)
			small_task_us += segment_us;
	}

	pct = (too_big_cpu_us * 100) / small_task_us;
	rv |= (pct > MAX_INCORRECT_CLUSTER_PCT);
	printf("Time incorrectly scheduled on big when task was small, "
	       "after downmigration: "
	       "%lld usec (%d%% of small task CPU time)\n", too_big_cpu_us,
	       pct);
	pct = (too_small_cpu_us * 100) / big_task_us;
	rv |= (pct > MAX_INCORRECT_CLUSTER_PCT);
	printf("Time incorrectly scheduled on small when task was big, "
	       "after upmigration: "
	       "%lld usec (%d%% of big task CPU time)\n", too_small_cpu_us,
	       pct);

	printf("small task time: %lld\nbig task time: %lld\n",
	       small_task_us, big_task_us);

	printf("Maximum upmigration time: %lld\n",
	       max_upmigrate_latency_usec);
	printf("Maximum downmigration time: %lld\n",
	       max_downmigrate_latency_usec);

	return (rv ||
		max_upmigrate_latency_usec > MAX_UPMIGRATE_LATENCY_US ||
		max_downmigrate_latency_usec > MAX_DOWNMIGRATE_LATENCY_US);
}

static void run(void)
{
	pthread_t task_thread;

	tst_res(TINFO, "Maximum incorrect cluster time percentage: %d%%",
		MAX_INCORRECT_CLUSTER_PCT);
	tst_res(TINFO, "Maximum downmigration latency: %d usec",
		MAX_DOWNMIGRATE_LATENCY_US);
	tst_res(TINFO, "Maximum upmigration latency: %d usec",
		MAX_UPMIGRATE_LATENCY_US);

	printf("Task alternating between big and small for %d sec\n",
	       BURN_SEC * NUM_LOOPS * 2);

	/* configure and enable tracing */
	tracefs_write("tracing_on", "0");
	tracefs_write("buffer_size_kb", "16384");
	tracefs_write("set_event", TRACE_EVENTS);
	tracefs_write("trace", "\n");
	tracefs_write("tracing_on", "1");

	SAFE_PTHREAD_CREATE(&task_thread, NULL, task_fn, NULL);
	SAFE_PTHREAD_JOIN(task_thread, NULL);

	/* disable tracing */
	tracefs_write("tracing_on", "0");
	LOAD_TRACE();

	if (parse_results())
		tst_res(TFAIL, "Task placement and migration latency goals "
			"were not met.\n");
	else
		tst_res(TPASS, "Task placement and migration latency goals "
			"were met.\n");
}

static struct tst_test test = {
	.test_all = run,
	.setup = trace_setup,
	.cleanup = trace_cleanup,
};
