// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
 */
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sched.h>

#include <linux/compiler.h>

#include "timerlat.h"
#include "timerlat_aa.h"
#include "timerlat_bpf.h"

#define DEFAULT_TIMERLAT_PERIOD	1000			/* 1ms */

static int dma_latency_fd = -1;

/*
 * timerlat_apply_config - apply common configs to the initialized tool
 */
int
timerlat_apply_config(struct osnoise_tool *tool, struct timerlat_params *params)
{
	int retval;
	const char *const rtla_no_bpf = getenv("RTLA_NO_BPF");

	/*
	 * Try to enable BPF, unless disabled explicitly.
	 * If BPF enablement fails, fall back to tracefs mode.
	 */
	if (rtla_no_bpf && strncmp_static(rtla_no_bpf, "1") == 0) {
		debug_msg("RTLA_NO_BPF set, disabling BPF\n");
		params->mode = TRACING_MODE_TRACEFS;
	} else if (!tep_find_event_by_name(tool->trace.tep, "osnoise", "timerlat_sample")) {
		debug_msg("osnoise:timerlat_sample missing, disabling BPF\n");
		params->mode = TRACING_MODE_TRACEFS;
	} else {
		retval = timerlat_bpf_init(params);
		if (retval) {
			debug_msg("Could not enable BPF\n");
			params->mode = TRACING_MODE_TRACEFS;
		}
	}

	/* Check if BPF action program is requested but BPF is not available */
	if (params->bpf_action_program) {
		if (params->mode == TRACING_MODE_TRACEFS) {
			err_msg("BPF actions are not supported in tracefs-only mode\n");
			goto out_err;
		}

		if (timerlat_load_bpf_action_program(params->bpf_action_program))
			goto out_err;
	}

	retval = osnoise_set_timerlat_period_us(tool->context,
						params->timerlat_period_us ?
						params->timerlat_period_us :
						DEFAULT_TIMERLAT_PERIOD);
	if (retval) {
		err_msg("Failed to set timerlat period\n");
		goto out_err;
	}


	retval = osnoise_set_print_stack(tool->context, params->print_stack);
	if (retval) {
		err_msg("Failed to set print stack\n");
		goto out_err;
	}

	retval = osnoise_set_timerlat_align(tool->context, params->timerlat_align);
	if (retval && params->timerlat_align) {
		/*
		 * We might be running on a kernel that does not support timerlat align.
		 * Unless user requested it explicitly, ignore the error.
		 */
		err_msg("Failed to enable timerlat align\n");
		goto out_err;
	}

	if (params->timerlat_align) {
		retval = osnoise_set_timerlat_align_us(tool->context, params->timerlat_align_us);
		if (retval) {
			err_msg("Failed to set timerlat align us\n");
			goto out_err;
		}
	}

	/*
	 * If the user did not specify a type of thread, try user-threads first.
	 * Fall back to kernel threads otherwise.
	 */
	if (!params->common.kernel_workload && !params->common.user_data) {
		retval = tracefs_file_exists(NULL, "osnoise/per_cpu/cpu0/timerlat_fd");
		if (retval) {
			debug_msg("User-space interface detected, setting user-threads\n");
			params->common.user_workload = 1;
			params->common.user_data = 1;
		} else {
			debug_msg("User-space interface not detected, setting kernel-threads\n");
			params->common.kernel_workload = 1;
		}
	}

	return common_apply_config(tool, &params->common);

out_err:
	return -1;
}

int timerlat_enable(struct osnoise_tool *tool)
{
	struct timerlat_params *params = to_timerlat_params(tool->params);
	int retval, i;

	if (params->dma_latency >= 0) {
		dma_latency_fd = set_cpu_dma_latency(params->dma_latency);
		if (dma_latency_fd < 0) {
			err_msg("Could not set /dev/cpu_dma_latency.\n");
			return -1;
		}
	}

	if (params->deepest_idle_state >= -1) {
		if (!have_libcpupower_support()) {
			err_msg("rtla built without libcpupower, --deepest-idle-state is not supported\n");
			return -1;
		}

		for_each_monitored_cpu(i, &params->common) {
			if (save_cpu_idle_disable_state(i) < 0) {
				err_msg("Could not save cpu idle state.\n");
				return -1;
			}
			if (set_deepest_cpu_idle_state(i, params->deepest_idle_state) < 0) {
				err_msg("Could not set deepest cpu idle state.\n");
				return -1;
			}
		}
	}

	if (!params->no_aa) {
		tool->aa = osnoise_init_tool("timerlat_aa");
		if (!tool->aa)
			return -1;

		retval = timerlat_aa_init(tool->aa, params->dump_tasks, params->stack_format);
		if (retval) {
			err_msg("Failed to enable the auto analysis instance\n");
			return retval;
		}

		retval = enable_tracer_by_name(tool->aa->trace.inst, "timerlat");
		if (retval) {
			err_msg("Failed to enable aa tracer\n");
			return retval;
		}
	}

	if (params->common.warmup > 0) {
		debug_msg("Warming up for %d seconds\n", params->common.warmup);
		sleep(params->common.warmup);
		if (stop_tracing)
			return -1;
	}

	/*
	 * Start the tracers here, after having set all instances.
	 *
	 * Let the trace instance start first for the case of hitting a stop
	 * tracing while enabling other instances. The trace instance is the
	 * one with most valuable information.
	 */
	if (tool->record)
		trace_instance_start(&tool->record->trace);
	if (!params->no_aa)
		trace_instance_start(&tool->aa->trace);
	if (params->mode == TRACING_MODE_TRACEFS) {
		trace_instance_start(&tool->trace);
	} else {
		retval = timerlat_bpf_attach();
		if (retval) {
			err_msg("Error attaching BPF program\n");
			return retval;
		}
	}

	/*
	 * In tracefs and mixed mode, timerlat tracer handles stopping
	 * on threshold
	 */
	if (params->mode != TRACING_MODE_BPF) {
		retval = osn_set_stop(tool);
		if (retval)
			return retval;
	}

	return 0;
}

void timerlat_analyze(struct osnoise_tool *tool, bool stopped)
{
	struct timerlat_params *params = to_timerlat_params(tool->params);

	if (stopped) {
		if (!params->no_aa)
			timerlat_auto_analysis(params->common.stop_us,
					       params->common.stop_total_us);
	} else if (params->common.aa_only) {
		char *max_lat;

		/*
		 * If the trace did not stop with --aa-only, at least print
		 * the max known latency.
		 */
		max_lat = tracefs_instance_file_read(tool->trace.inst, "tracing_max_latency", NULL);
		if (max_lat) {
			printf("  Max latency was %s\n", max_lat);
			free(max_lat);
		}
	}
}

void timerlat_free(struct osnoise_tool *tool)
{
	struct timerlat_params *params = to_timerlat_params(tool->params);
	int i;

	timerlat_aa_destroy();
	if (dma_latency_fd >= 0)
		close(dma_latency_fd);
	if (params->deepest_idle_state >= -1) {
		for_each_monitored_cpu(i, &params->common) {
			restore_cpu_idle_disable_state(i);
		}
	}

	osnoise_destroy_tool(tool->aa);

	if (params->mode != TRACING_MODE_TRACEFS)
		timerlat_bpf_destroy();
	free_cpu_idle_disable_states();
}

__noreturn static void timerlat_usage(int err)
{
	int i;

	static const char * const msg[] = {
		"",
		"timerlat version " VERSION,
		"",
		"  usage: [rtla] timerlat [MODE] ...",
		"",
		"  modes:",
		"     top   - prints the summary from timerlat tracer",
		"     hist  - prints a histogram of timer latencies",
		"",
		"if no MODE is given, the top mode is called, passing the arguments",
		NULL,
	};

	for (i = 0; msg[i]; i++)
		fprintf(stderr, "%s\n", msg[i]);
	exit(err);
}

int timerlat_main(int argc, char *argv[])
{
	if (argc == 0)
		goto usage;

	/*
	 * if timerlat was called without any argument, run the
	 * default cmdline.
	 */
	if (argc == 1) {
		run_tool(&timerlat_top_ops, argc, argv);
		exit(0);
	}

	if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
		timerlat_usage(129);
	} else if (str_has_prefix(argv[1], "-")) {
		/* the user skipped the tool, call the default one */
		run_tool(&timerlat_top_ops, argc, argv);
		exit(0);
	} else if (strcmp(argv[1], "top") == 0) {
		run_tool(&timerlat_top_ops, argc-1, &argv[1]);
		exit(0);
	} else if (strcmp(argv[1], "hist") == 0) {
		run_tool(&timerlat_hist_ops, argc-1, &argv[1]);
		exit(0);
	}

usage:
	timerlat_usage(129);
}
