164000Speter/*-
264000Speter * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
364000Speter * All rights reserved.
464000Speter *
564000Speter * Redistribution and use in source and binary forms, with or without
664000Speter * modification, are permitted provided that the following conditions
764000Speter * are met:
864000Speter * 1. Redistributions of source code must retain the above copyright
964000Speter *    notice, this list of conditions and the following disclaimer.
1064000Speter * 2. Redistributions in binary form must reproduce the above copyright
1164000Speter *    notice, this list of conditions and the following disclaimer in the
1264000Speter *    documentation and/or other materials provided with the distribution.
1364000Speter *
1464000Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1564000Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1664000Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1764000Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1864000Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1964000Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2064000Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2164000Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2264000Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2364000Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2464000Speter * SUCH DAMAGE.
2564000Speter */
2664000Speter
2793000Sobrien#include <machine/asm.h>
2893000Sobrien__FBSDID("$FreeBSD$");
2993000Sobrien
3064000Speter/*
3164000Speter * With thanks to John Dyson for the original version of this.
3264000Speter */
3364000Speter
3464000Speter#include <SYS.h>
3564000Speter
3664000Speter/*
3764000Speter *                8      12          16         20
3864000Speter * rfork_thread(flags, stack_addr, start_fnc, start_arg);
3964000Speter *
4064000Speter * flags:		Flags to rfork system call.  See rfork(2).
4164000Speter * stack_addr:		Top of stack for thread.
4264000Speter * start_fnc:		Address of thread function to call in child.
4364000Speter * start_arg:		Argument to pass to the thread function in child.
4464000Speter */
4564000Speter
4664000SpeterENTRY(rfork_thread)
4764000Speter	pushl	%ebp
4864000Speter	movl	%esp, %ebp
4964000Speter	pushl	%esi
5064000Speter
5164000Speter	/*
5264000Speter	 * Push thread info onto the new thread's stack
5364000Speter	 */
5464000Speter	movl	12(%ebp), %esi	# get stack addr
5564000Speter
5664000Speter	subl	$4, %esi
5764000Speter	movl	20(%ebp), %eax	# get start argument
5864000Speter	movl	%eax, (%esi)
5964000Speter
6064000Speter	subl	$4, %esi
6164000Speter	movl	16(%ebp), %eax	# get start thread address
6264000Speter	movl	%eax, (%esi)
6364000Speter
6464000Speter	/*
6564000Speter	 * Prepare and execute the thread creation syscall
6664000Speter	 */
6764000Speter	pushl	8(%ebp)
6864003Speter	pushl	$0
6987006Sjhb	movl	$SYS_rfork, %eax
7064000Speter	KERNCALL
7164000Speter	jb 	2f
7264000Speter
7364000Speter	/*
7464000Speter	 * Check to see if we are in the parent or child
7564000Speter	 */
7664000Speter	cmpl	$0, %edx
7764000Speter	jnz	1f
7864000Speter	addl	$8, %esp
7964000Speter	popl	%esi
8064000Speter	movl	%ebp, %esp
8164000Speter	popl	%ebp
8264000Speter	ret
8364000Speter	.p2align 2
8464000Speter
8564000Speter	/*
8664000Speter	 * If we are in the child (new thread), then
8764000Speter	 * set-up the call to the internal subroutine.  If it
8864000Speter	 * returns, then call __exit.
8964000Speter	 */
9064000Speter1:
9164000Speter	movl	%esi,%esp
9264000Speter	popl	%eax
9364000Speter	call	*%eax
9464003Speter	addl	$4, %esp
9564000Speter
9664000Speter	/*
9764000Speter	 * Exit system call
9864000Speter	 */
9964000Speter	pushl	%eax
10064003Speter	pushl	$0
10164000Speter#ifdef SYS_exit
10287006Sjhb	movl	$SYS_exit, %eax
10364000Speter#else
10487006Sjhb	movl	$SYS_sys_exit, %eax
10564000Speter#endif
10664000Speter	KERNCALL
10764000Speter
10864000Speter	/*
10964000Speter	 * Branch here if the thread creation fails:
11064000Speter	 */
11164000Speter2:
112114804Sjhb	addl	$8, %esp
113114804Sjhb	popl	%esi
114114804Sjhb	movl	%ebp, %esp
115114804Sjhb	popl	%ebp
11664000Speter	PIC_PROLOGUE
11764000Speter	jmp	PIC_PLT(HIDENAME(cerror))
118184548SpeterEND(rfork_thread)
119217106Skib
120217106Skib	.section .note.GNU-stack,"",%progbits
121