int copy_thread()

in kernel/process.c [103:146]


int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
		struct task_struct *p, unsigned long tls)
{
	struct pt_regs *childregs = task_pt_regs(p);
	struct pt_regs *regs;
	struct switch_stack *stack;
	struct switch_stack *childstack =
		((struct switch_stack *)childregs) - 1;

	if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) {
		memset(childstack, 0,
			sizeof(struct switch_stack) + sizeof(struct pt_regs));

		childstack->r16 = usp;		/* fn */
		childstack->r17 = arg;
		childstack->ra = (unsigned long) ret_from_kernel_thread;
		childregs->estatus = STATUS_PIE;
		childregs->sp = (unsigned long) childstack;

		p->thread.ksp = (unsigned long) childstack;
		p->thread.kregs = childregs;
		return 0;
	}

	regs = current_pt_regs();
	*childregs = *regs;
	childregs->r2 = 0;	/* Set the return value for the child. */
	childregs->r7 = 0;

	stack = ((struct switch_stack *) regs) - 1;
	*childstack = *stack;
	childstack->ra = (unsigned long)ret_from_fork;
	p->thread.kregs = childregs;
	p->thread.ksp = (unsigned long) childstack;

	if (usp)
		childregs->sp = usp;

	/* Initialize tls register. */
	if (clone_flags & CLONE_SETTLS)
		childstack->r23 = tls;

	return 0;
}