<commit_before>/**
 * @file
 * @brief
 *
 * @author  <NAME>
 * @date    14.05.2014
 */

#include <mem/sysmalloc.h>
#include <hal/ptrace.h>
#include <hal/vfork.h>
#include <kernel/panic.h>
#include <kernel/sched.h>
#include <kernel/task.h>

#define VFORK_CTX_STACK_LEN 0x1000
struct vfork_ctx {
	struct pt_regs ptregs;
	struct context original_ctx;
	struct context waiting_ctx;
	bool parent_holded;
	char stack[VFORK_CTX_STACK_LEN];
};

static struct vfork_ctx *vfork_current_context;

static void vfork_parent_signal_handler(int sig, siginfo_t *siginfo, void *context) {
	struct vfork_ctx *vfctx = vfork_current_context;

	vfctx->parent_holded = false;
}

static void *vfork_child_task(void *arg) {
	struct pt_regs *ptregs = arg;

	ptregs_retcode(ptregs, 0);
	ptregs_jmp(ptregs);

	panic("vfork_child_task returning");
}

static void vfork_wait_signal_store(struct sigaction *ochildsa,
	       	struct sigaction *ocontsa) {
	struct sigaction sa;

	sa.sa_flags = SA_SIGINFO;
	sa.sa_sigaction = vfork_parent_signal_handler;
	sigemptyset(&sa.sa_mask);

	sigaction(SIGCHLD, &sa, ochildsa);
	sigaction(SIGCONT, &sa, ocontsa);
}

static void vfork_wait_signal_restore(const struct sigaction *ochildsa,
	       	const struct sigaction *ocontsa) {
	sigaction(SIGCHLD, ochildsa, NULL);
	sigaction(SIGCONT, ocontsa, NULL);
}

static void vfork_waiting(void) {
	struct sigaction ochildsa, ocontsa;
	struct vfork_ctx *vfctx;
	pid_t child;

	vfctx = vfork_current_context;

	vfork_wait_signal_store(&ochildsa, &ocontsa);

	vfctx->parent_holded = true;
	child = new_task("", vfork_child_task, &vfctx->ptregs);
	if (child > 0) {
		SCHED_WAIT(!vfctx->parent_holded);
	} else {
		/* child already have error code */
	}

	vfork_wait_signal_restore(&ochildsa, &ocontsa);

	ptregs_retcode(&vfctx->ptregs, child);
	context_switch(&vfctx->waiting_ctx, &vfctx->original_ctx);

	panic("vfork_waiting returning");
}

void __attribute__((noreturn)) vfork_body(struct pt_regs *ptregs) {
	struct pt_regs ptbuf;
	struct vfork_ctx *vfctx;

	vfctx = sysmalloc(sizeof(*vfctx));
	if (!vfctx) {
		ptregs_retcode(ptregs, -EAGAIN);
		ptregs_jmp(&ptbuf);
	}

	memcpy(&vfctx->ptregs, ptregs, sizeof(vfctx->ptregs));

	context_init(&vfctx->waiting_ctx, true);
	context_set_entry(&vfctx->waiting_ctx, vfork_waiting);
	context_set_stack(&vfctx->waiting_ctx, vfctx->stack + sizeof(vfctx->stack));

	vfork_current_context = vfctx;
	context_switch(&vfctx->original_ctx, &vfctx->waiting_ctx);

	/* current stack is broken, can't reach any old data */

	vfctx = vfork_current_context;
	memcpy(&ptbuf, &vfctx->ptregs, sizeof(*ptregs));
	sysfree(vfctx);

	ptregs_jmp(&ptbuf);

	panic("vfork_body returning");
}

void vfork_release_parent(void) {
	kill(task_get_id(task_get_parent(task_self())), SIGCONT);
}

//FIXME
void vfork_child_done(struct task *child, void * (*run)(void *), void *arg) {

}
<commit_msg>vfork_stop_parent exception fixed on ti816x<commit_after>/**
 * @file
 * @brief
 *
 * @author  <NAME>
 * @date    14.05.2014
 */

#include <mem/sysmalloc.h>
#include <hal/ptrace.h>
#include <hal/vfork.h>
#include <kernel/panic.h>
#include <kernel/sched.h>
#include <kernel/task.h>

#define VFORK_CTX_STACK_LEN 0x1000
struct vfork_ctx {
	struct pt_regs ptregs;
	struct context original_ctx;
	struct context waiting_ctx;
	char stack[VFORK_CTX_STACK_LEN] __attribute__((aligned(4)));
	bool parent_holded;
};

static struct vfork_ctx *vfork_current_context;

static void vfork_parent_signal_handler(int sig, siginfo_t *siginfo, void *context) {
	struct vfork_ctx *vfctx = vfork_current_context;

	vfctx->parent_holded = false;
}

static void *vfork_child_task(void *arg) {
	struct pt_regs *ptregs = arg;

	ptregs_retcode(ptregs, 0);
	ptregs_jmp(ptregs);

	panic("vfork_child_task returning");
}

static void vfork_wait_signal_store(struct sigaction *ochildsa,
	       	struct sigaction *ocontsa) {
	struct sigaction sa;

	sa.sa_flags = SA_SIGINFO;
	sa.sa_sigaction = vfork_parent_signal_handler;
	sigemptyset(&sa.sa_mask);

	sigaction(SIGCHLD, &sa, ochildsa);
	sigaction(SIGCONT, &sa, ocontsa);
}

static void vfork_wait_signal_restore(const struct sigaction *ochildsa,
	       	const struct sigaction *ocontsa) {
	sigaction(SIGCHLD, ochildsa, NULL);
	sigaction(SIGCONT, ocontsa, NULL);
}

static void vfork_waiting(void) {
	struct sigaction ochildsa, ocontsa;
	struct vfork_ctx *vfctx;
	pid_t child;

	vfctx = vfork_current_context;

	vfork_wait_signal_store(&ochildsa, &ocontsa);

	vfctx->parent_holded = true;
	child = new_task("", vfork_child_task, &vfctx->ptregs);
	if (child > 0) {
		SCHED_WAIT(!vfctx->parent_holded);
	} else {
		/* child already have error code */
	}

	vfork_wait_signal_restore(&ochildsa, &ocontsa);

	ptregs_retcode(&vfctx->ptregs, child);
	context_switch(&vfctx->waiting_ctx, &vfctx->original_ctx);

	panic("vfork_waiting returning");
}

void __attribute__((noreturn)) vfork_body(struct pt_regs *ptregs) {
	struct pt_regs ptbuf;
	struct vfork_ctx *vfctx;

	vfctx = sysmalloc(sizeof(*vfctx));
	if (!vfctx) {
		ptregs_retcode(ptregs, -EAGAIN);
		ptregs_jmp(&ptbuf);
	}

	memcpy(&vfctx->ptregs, ptregs, sizeof(vfctx->ptregs));

	context_init(&vfctx->waiting_ctx, true);
	context_set_entry(&vfctx->waiting_ctx, vfork_waiting);
	context_set_stack(&vfctx->waiting_ctx, vfctx->stack + sizeof(vfctx->stack));

	vfork_current_context = vfctx;
	context_switch(&vfctx->original_ctx, &vfctx->waiting_ctx);

	/* current stack is broken, can't reach any old data */

	vfctx = vfork_current_context;
	memcpy(&ptbuf, &vfctx->ptregs, sizeof(*ptregs));
	sysfree(vfctx);

	ptregs_jmp(&ptbuf);

	panic("vfork_body returning");
}

void vfork_release_parent(void) {
	kill(task_get_id(task_get_parent(task_self())), SIGCONT);
}

//FIXME
void vfork_child_done(struct task *child, void * (*run)(void *), void *arg) {

}

{'fraction_non_alphanumeric': 0.1301038062283737, 'fraction_numerical': 0.0058823529411764705, 'mean_word_length': 5.849526066350711, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3301026', 'n_tokens_mistral': 2334, 'n_tokens_neox': 2219, 'n_words': 423}