1121074Salc/*-
2121074Salc * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
3121074Salc * Copyright (c) 2003 Alan L. Cox <alc@cs.rice.edu>
4121074Salc * All rights reserved.
5121074Salc *
6121074Salc * Redistribution and use in source and binary forms, with or without
7121074Salc * modification, are permitted provided that the following conditions
8121074Salc * are met:
9121074Salc * 1. Redistributions of source code must retain the above copyright
10121074Salc *    notice, this list of conditions and the following disclaimer.
11121074Salc * 2. Redistributions in binary form must reproduce the above copyright
12121074Salc *    notice, this list of conditions and the following disclaimer in the
13121074Salc *    documentation and/or other materials provided with the distribution.
14121074Salc *
15121074Salc * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16121074Salc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17121074Salc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18121074Salc * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19121074Salc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20121074Salc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21121074Salc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22121074Salc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23121074Salc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24121074Salc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25121074Salc * SUCH DAMAGE.
26121074Salc */
27121074Salc
28121074Salc#include <machine/asm.h>
29121074Salc__FBSDID("$FreeBSD: releng/10.2/lib/libc/amd64/gen/rfork_thread.S 240178 2012-09-06 20:59:49Z jilles $");
30121074Salc
31121074Salc/*
32121074Salc * With thanks to John Dyson for the original version of this.
33121074Salc */
34121074Salc
35121074Salc#include <SYS.h>
36121074Salc
37121074Salc/*
38121074Salc *              %edi   %rsi        %rdx       %rcx
39121074Salc * rfork_thread(flags, stack_addr, start_fnc, start_arg);
40121074Salc *
41121074Salc * flags:		Flags to rfork system call.  See rfork(2).
42121074Salc * stack_addr:		Top of stack for thread.
43121074Salc * start_fnc:		Address of thread function to call in child.
44121074Salc * start_arg:		Argument to pass to the thread function in child.
45121074Salc */
46121074Salc
47121074SalcENTRY(rfork_thread)
48121074Salc	pushq	%rbx
49121074Salc	pushq	%r12
50121074Salc	movq	%rdx, %rbx
51121074Salc	movq	%rcx, %r12
52121074Salc
53121074Salc	/*
54121074Salc	 * Prepare and execute the thread creation syscall
55121074Salc	 */
56121074Salc	movq	$SYS_rfork, %rax
57121074Salc	KERNCALL
58121074Salc	jb 	2f
59121074Salc
60121074Salc	/*
61121074Salc	 * Check to see if we are in the parent or child
62121074Salc	 */
63121074Salc	cmpl	$0, %edx
64121074Salc	jnz	1f
65121074Salc	popq	%r12
66121074Salc	popq	%rbx
67121074Salc	ret
68121074Salc
69121074Salc	/*
70121074Salc	 * If we are in the child (new thread), then
71121074Salc	 * set-up the call to the internal subroutine.  If it
72121074Salc	 * returns, then call __exit.
73121074Salc	 */
74121074Salc1:
75121074Salc	movq	%rsi, %rsp
76121074Salc	movq	%r12, %rdi
77121074Salc	call	*%rbx
78121074Salc	movl	%eax, %edi
79121074Salc
80121074Salc	/*
81121074Salc	 * Exit system call
82121074Salc	 */
83121074Salc#ifdef SYS_exit
84121074Salc	movq	$SYS_exit, %rax
85121074Salc#else
86121074Salc	movq	$SYS_sys_exit, %rax
87121074Salc#endif
88121074Salc	KERNCALL
89121074Salc
90121074Salc	/*
91121074Salc	 * Branch here if the thread creation fails:
92121074Salc	 */
93121074Salc2:
94121074Salc	popq	%r12
95121074Salc	popq	%rbx
96121074Salc	jmp	HIDENAME(cerror)
97184547SpeterEND(rfork_thread)
98217106Skib
99217106Skib	.section .note.GNU-stack,"",%progbits
100