/* Copyright (c) 2015 Google, Inc.
 * Barret Rhoden <brho@cs.berkeley.edu>
 * See LICENSE for details. */

#include <parlib/parlib.h>
#include <parlib/core_set.h>
#include <parlib/ros_debug.h>
#include <parlib/event.h>
#include <stdlib.h>
#include <sys/wait.h>

/* Control variables */
bool parlib_wants_to_be_mcp = TRUE;
bool parlib_never_yield = FALSE;
bool parlib_never_vc_request = FALSE;

/* Creates a child process for program @exe, with args and envs.  Will attempt
 * to look in /bin/ if the initial lookup fails, and will invoke sh to handle
 * non-elfs.  Returns the child's PID on success, -1 o/w. */
pid_t create_child(const char *exe, int argc, char *const argv[],
                   char *const envp[])
{
	pid_t kid;
	char *path_exe;
	char **sh_argv;
	const char *sh_path = "/bin/sh";

	kid = sys_proc_create(exe, strlen(exe), argv, envp, 0);
	if (kid > 0)
		return kid;

	/* Here's how we avoid infinite recursion.  We can only have ENOENT the
	 * first time through without bailing out, since all errno paths set exe
	 * to begin with '/'.  That includes calls from ENOEXEC, since sh_path
	 * begins with /.  To avoid repeated calls to ENOEXEC, we just look for
	 * sh_path as the exe, so if we have consecutive ENOEXECs, we'll bail
	 * out. */
	switch (errno) {
	case ENOENT:
		if (exe[0] == '/')
			return -1;
		path_exe = malloc(MAX_PATH_LEN);
		if (!path_exe)
			return -1;
		/* Our 'PATH' is only /bin. */
		snprintf(path_exe, MAX_PATH_LEN, "/bin/%s", exe);
		path_exe[MAX_PATH_LEN - 1] = 0;
		kid = create_child(path_exe, argc, argv, envp);
		free(path_exe);
		break;
	case ENOEXEC:
		/* In case someone replaces /bin/sh with a non-elf. */
		if (!strcmp(sh_path, exe))
			return -1;
		/* We want enough space for the original argv, plus one entry at
		 * the front for sh_path.  When we grab the original argv, we
		 * also need the trailing NULL, which is at argv[argc].  That
		 * means we really want argc + 1 entries from argv. */
		sh_argv = malloc(sizeof(char *) * (argc + 2));
		if (!sh_argv)
			return -1;
		memcpy(&sh_argv[1], argv, sizeof(char *) * (argc + 1));
		sh_argv[0] = (char*)sh_path;
		/* Replace the original argv[0] with the path to exe, which
		 * might have been edited to include /bin/ */
		sh_argv[1] = (char*)exe;
		kid = create_child(sh_path, argc + 1, sh_argv, envp);
		free(sh_argv);
		break;
	default:
		return -1;
	}
	return kid;
}

/* Creates a child process for exe, and shares the parent's standard FDs (stdin,
 * stdout, stderr) with the child.  Returns the child's PID on success, -1 o/w.
 */
pid_t create_child_with_stdfds(const char *exe, int argc, char *const argv[],
                               char *const envp[])
{
	struct childfdmap fd_dups[3] = { {0, 0}, {1, 1}, {2, 2} };
	pid_t kid;
	int ret;

	kid = create_child(exe, argc, argv, envp);
	if (kid < 0)
		return -1;
	ret = syscall(SYS_dup_fds_to, kid, fd_dups, COUNT_OF(fd_dups));
	if (ret != COUNT_OF(fd_dups)) {
		sys_proc_destroy(kid, -1);
		return -1;
	}
	return kid;
}

/* Helper for kicking off a process, but with little specific error handling */
int run_and_wait(const char *exe, int argc, char *const argv[])
{
	extern char **environ;

	pid_t kid;

	kid = create_child_with_stdfds(exe, argc, argv, environ);
	if (kid < 0)
		return -1;
	if (sys_proc_run(kid) < 0)
		return -1;
	if (waitpid(kid, NULL, 0) != kid)
		return -1;
	return 0;
}

/* Provisions the CG cores to PID.  Returns -1 if any of them fail. */
int provision_core_set(pid_t pid, const struct core_set *cores)
{
	struct core_set pvcores;
	size_t max_cores = parlib_nr_total_cores();

	parlib_get_ll_core_set(&pvcores);
	parlib_not_core_set(&pvcores);
	parlib_and_core_sets(&pvcores, cores);
	for (size_t i = 0; i < max_cores; i++) {
		if (parlib_get_core(&pvcores, i)) {
			if (sys_provision(pid, RES_CORES, i))
				return -1;
		}
	}
	return 0;
}

/* This sets up 'handler' to be run when the process receives EV_FREE_APPLE_PIE
 * (9).  You can send this event with the notify utility:
 *
 *	notify PID 9 [Arg1 Arg2 0xArg3 Arg4]
 *
 * A simple debug handler can switch on an arg:

	static void notify_ipi(struct event_msg *ev_msg, unsigned int ev_type,
	                       void *data)
	{
		switch (ev_msg->ev_arg1) {
		case 1:
			// do something
			break;
		case 2:
			// do something else
			break;
		default:
			printf("Unknown arg %d\n", ev_msg->ev_arg1);
			break;
		}
	}

 */
void set_notify_9(void (*handler)(struct event_msg *ev_msg,
				  unsigned int ev_type, void *data),
		  void *data)
{
	struct event_queue *evq;

	register_ev_handler(EV_FREE_APPLE_PIE, handler, data);
	evq = get_eventq(EV_MBOX_UCQ);
	evq->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_SPAM_INDIR |
		        EVENT_WAKEUP;
	register_kevent_q(evq, EV_FREE_APPLE_PIE);
}
