// SPDX-License-Identifier: GPL-2.0
/*
 * Intel Speed Select -- Allow speed select to daemonize
 * Copyright (c) 2022 Intel Corporation.
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <time.h>

#include "isst.h"

static int per_package_levels_info[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];
static time_t per_package_levels_tm[MAX_PACKAGE_COUNT][MAX_DIE_PER_PACKAGE][MAX_PUNIT_PER_DIE];

static void init_levels(void)
{
	int i, j, k;

	for (i = 0; i < MAX_PACKAGE_COUNT; ++i)
		for (j = 0; j < MAX_DIE_PER_PACKAGE; ++j)
			for (k = 0; k < MAX_PUNIT_PER_DIE; ++k)
				per_package_levels_info[i][j][k] = -1;
}

void process_level_change(struct isst_id *id)
{
	struct isst_pkg_ctdp_level_info ctdp_level;
	struct isst_pkg_ctdp pkg_dev;
	time_t tm;
	int ret;

	if (id->pkg < 0 || id->die < 0 || id->punit < 0) {
		debug_printf("Invalid package/die info for cpu:%d\n", id->cpu);
		return;
	}

	tm = time(NULL);
	if (tm - per_package_levels_tm[id->pkg][id->die][id->punit] < 2)
		return;

	per_package_levels_tm[id->pkg][id->die][id->punit] = tm;

	ret = isst_get_ctdp_levels(id, &pkg_dev);
	if (ret) {
		debug_printf("Can't get tdp levels for cpu:%d\n", id->cpu);
		return;
	}

	debug_printf("Get Config level %d pkg:%d die:%d current_level:%d\n", id->cpu,
		      id->pkg, id->die, pkg_dev.current_level);

	if (pkg_dev.locked) {
		debug_printf("config TDP s locked \n");
		return;
	}

	if (per_package_levels_info[id->pkg][id->die][id->punit] == pkg_dev.current_level)
		return;

	debug_printf("**Config level change for cpu:%d pkg:%d die:%d from %d to %d\n",
		      id->cpu, id->pkg, id->die, per_package_levels_info[id->pkg][id->die][id->punit],
		      pkg_dev.current_level);

	per_package_levels_info[id->pkg][id->die][id->punit] = pkg_dev.current_level;

	ctdp_level.core_cpumask_size =
		alloc_cpu_set(&ctdp_level.core_cpumask);
	ret = isst_get_coremask_info(id, pkg_dev.current_level, &ctdp_level);
	if (ret) {
		free_cpu_set(ctdp_level.core_cpumask);
		debug_printf("Can't get core_mask:%d\n", id->cpu);
		return;
	}

	if (use_cgroupv2()) {
		int ret;

		ret = enable_cpuset_controller();
		if (ret)
			goto use_offline;

		isolate_cpus(id, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask, pkg_dev.current_level);

		goto free_mask;
	}

use_offline:
	if (ctdp_level.cpu_count) {
		int i, max_cpus = get_topo_max_cpus();
		for (i = 0; i < max_cpus; ++i) {
			if (!is_cpu_in_power_domain(i, id))
				continue;
			if (CPU_ISSET_S(i, ctdp_level.core_cpumask_size, ctdp_level.core_cpumask)) {
				fprintf(stderr, "online cpu %d\n", i);
				set_cpu_online_offline(i, 1);
			} else {
				fprintf(stderr, "offline cpu %d\n", i);
				set_cpu_online_offline(i, 0);
			}
		}
	}
free_mask:
	free_cpu_set(ctdp_level.core_cpumask);
}

static void _poll_for_config_change(struct isst_id *id, void *arg1, void *arg2,
				    void *arg3, void *arg4)
{
	process_level_change(id);
}

static void poll_for_config_change(void)
{
	for_each_online_power_domain_in_set(_poll_for_config_change, NULL, NULL,
				       NULL, NULL);
}

static int done = 0;
static int pid_file_handle;

static void signal_handler(int sig)
{
	switch (sig) {
	case SIGINT:
	case SIGTERM:
		done = 1;
		hfi_exit();
		exit(0);
		break;
	default:
		break;
	}
}

static void daemonize(char *rundir, char *pidfile)
{
	int pid, sid, i;
	char str[10];
	struct sigaction sig_actions;
	sigset_t sig_set;
	int ret;

	if (getppid() == 1)
		return;

	sigemptyset(&sig_set);
	sigaddset(&sig_set, SIGCHLD);
	sigaddset(&sig_set, SIGTSTP);
	sigaddset(&sig_set, SIGTTOU);
	sigaddset(&sig_set, SIGTTIN);
	sigprocmask(SIG_BLOCK, &sig_set, NULL);

	sig_actions.sa_handler = signal_handler;
	sigemptyset(&sig_actions.sa_mask);
	sig_actions.sa_flags = 0;

	sigaction(SIGHUP, &sig_actions, NULL);
	sigaction(SIGTERM, &sig_actions, NULL);
	sigaction(SIGINT, &sig_actions, NULL);

	pid = fork();
	if (pid < 0) {
		/* Could not fork */
		exit(EXIT_FAILURE);
	}
	if (pid > 0)
		exit(EXIT_SUCCESS);

	umask(027);

	sid = setsid();
	if (sid < 0)
		exit(EXIT_FAILURE);

	/* close all descriptors */
	for (i = getdtablesize(); i >= 0; --i)
		close(i);

	i = open("/dev/null", O_RDWR);
	if (i < 0)
		exit(EXIT_FAILURE);

	ret = dup(i);
	if (ret == -1)
		exit(EXIT_FAILURE);

	ret = chdir(rundir);
	if (ret == -1)
		exit(EXIT_FAILURE);

	pid_file_handle = open(pidfile, O_RDWR | O_CREAT, 0600);
	if (pid_file_handle == -1) {
		/* Couldn't open lock file */
		exit(1);
	}
	/* Try to lock file */
#ifdef LOCKF_SUPPORT
	if (lockf(pid_file_handle, F_TLOCK, 0) == -1) {
#else
	if (flock(pid_file_handle, LOCK_EX|LOCK_NB) < 0) {
#endif
		/* Couldn't get lock on lock file */
		fprintf(stderr, "Couldn't get lock file %d\n", getpid());
		exit(1);
	}
	snprintf(str, sizeof(str), "%d\n", getpid());
	ret = write(pid_file_handle, str, strlen(str));
	if (ret == -1)
		exit(EXIT_FAILURE);

	close(i);
}

int isst_daemon(int debug_mode, int poll_interval, int no_daemon)
{
	int ret;

	if (!no_daemon && poll_interval < 0 && !debug_mode) {
		fprintf(stderr, "OOB mode is enabled and will run as daemon\n");
		daemonize((char *) "/tmp/",
				(char *)"/tmp/hfi-events.pid");
	} else {
		signal(SIGINT, signal_handler);
	}

	init_levels();

	if (poll_interval < 0) {
		ret = hfi_main();
		if (ret) {
			fprintf(stderr, "HFI initialization failed\n");
		}
		fprintf(stderr, "Must specify poll-interval\n");
		return ret;
	}

	debug_printf("Starting loop\n");
	while (!done) {
		sleep(poll_interval);
		poll_for_config_change();
	}

	return 0;
}
