xref: /openbsd-src/lib/libc/arch/i386/sys/tfork_thread.S (revision 83762a71f74848f4d09174ce350838b4204957c5)
1*83762a71Sderaadt/*	$OpenBSD: tfork_thread.S,v 1.11 2023/12/10 16:45:51 deraadt Exp $ */
2c6f64c6fSguenther/*-
3c6f64c6fSguenther * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
4c6f64c6fSguenther * All rights reserved.
5c6f64c6fSguenther *
6c6f64c6fSguenther * Redistribution and use in source and binary forms, with or without
7c6f64c6fSguenther * modification, are permitted provided that the following conditions
8c6f64c6fSguenther * are met:
9c6f64c6fSguenther * 1. Redistributions of source code must retain the above copyright
10c6f64c6fSguenther *    notice, this list of conditions and the following disclaimer.
11c6f64c6fSguenther * 2. Redistributions in binary form must reproduce the above copyright
12c6f64c6fSguenther *    notice, this list of conditions and the following disclaimer in the
13c6f64c6fSguenther *    documentation and/or other materials provided with the distribution.
14c6f64c6fSguenther *
15c6f64c6fSguenther * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16c6f64c6fSguenther * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17c6f64c6fSguenther * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18c6f64c6fSguenther * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19c6f64c6fSguenther * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20c6f64c6fSguenther * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21c6f64c6fSguenther * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22c6f64c6fSguenther * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23c6f64c6fSguenther * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24c6f64c6fSguenther * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25c6f64c6fSguenther * SUCH DAMAGE.
26c6f64c6fSguenther */
27c6f64c6fSguenther
28c6f64c6fSguenther#include <machine/asm.h>
29c6f64c6fSguenther
30c6f64c6fSguenther/*
31c6f64c6fSguenther * With thanks to John Dyson for the original version of this.
32c6f64c6fSguenther */
33c6f64c6fSguenther
34c6f64c6fSguenther#include "SYS.h"
35c6f64c6fSguenther
36c6f64c6fSguenther/*
37c6f64c6fSguenther *                8      12     16         20
3816b62b6aSguenther * __tfork_thread(param, psize, start_fnc, start_arg);
39c6f64c6fSguenther *
40c6f64c6fSguenther * param:		Arguments to actual system call.
4116b62b6aSguenther * psize:		Other argument to pass to the actual kernel call.
42c6f64c6fSguenther * start_fnc:		Address of thread function to call in child.
43c6f64c6fSguenther * start_arg:		Argument to pass to the thread function in child.
44c6f64c6fSguenther */
45c6f64c6fSguenther
46c6f64c6fSguentherENTRY(__tfork_thread)
47c6f64c6fSguenther	pushl	%ebp
48c6f64c6fSguenther	movl	%esp, %ebp
49c6f64c6fSguenther	pushl	%esi
5016b62b6aSguenther	pushl	%edi
51c6f64c6fSguenther
52c6f64c6fSguenther	/*
5316b62b6aSguenther	 * Save the thread info in esi and ebx
54c6f64c6fSguenther	 */
5516b62b6aSguenther	movl	16(%ebp), %esi	# get start thread address
5616b62b6aSguenther	movl	20(%ebp), %edi	# get start argument
57c6f64c6fSguenther
58c6f64c6fSguenther	/*
59c6f64c6fSguenther	 * Prepare and execute the thread creation syscall
60c6f64c6fSguenther	 */
6116b62b6aSguenther	pushl	12(%ebp)	# push psize
6216b62b6aSguenther	pushl	8(%ebp)		# push param
6316b62b6aSguenther	pushl	$0		# slot for return address, ignored by kernel
64c6f64c6fSguenther	movl	$SYS___tfork, %eax
65*83762a71Sderaadt99:	int	$0x80
66*83762a71Sderaadt	PINSYSCALL(SYS___tfork, 99b)
67c6f64c6fSguenther	jb 	2f
68c6f64c6fSguenther
69c6f64c6fSguenther	/*
70c6f64c6fSguenther	 * Check to see if we are in the parent or child
71c6f64c6fSguenther	 */
7211225f07Sguenther	cmpl	$0, %eax
7311225f07Sguenther	jz	1f
7416b62b6aSguenther	addl	$12, %esp
7516b62b6aSguenther	popl	%edi
76c6f64c6fSguenther	popl	%esi
77c6f64c6fSguenther	movl	%ebp, %esp
78c6f64c6fSguenther	popl	%ebp
79c6f64c6fSguenther	ret
80c6f64c6fSguenther	.p2align 2
81c6f64c6fSguenther
82c6f64c6fSguenther	/*
83c6f64c6fSguenther	 * If we are in the child (new thread), then
84c6f64c6fSguenther	 * set-up the call to the internal subroutine.  If it
8516b62b6aSguenther	 * returns, then call __threxit.
86c6f64c6fSguenther	 */
87c6f64c6fSguenther1:
886df0f8ceSkettenis	xorl	%ebp, %ebp	# mark outermost frame
8989245e66Skettenis	subl	$4, %esp	# align stack
9089245e66Skettenis	andl	$~15, %esp
9189245e66Skettenis	addl	$4, %esp
9216b62b6aSguenther	pushl	%edi		# push start argument
9316b62b6aSguenther	call	*%esi
94c6f64c6fSguenther	addl	$4, %esp
95c6f64c6fSguenther
96c6f64c6fSguenther	/*
97c6f64c6fSguenther	 * Exit system call
98c6f64c6fSguenther	 */
9916b62b6aSguenther	pushl	$0		# NULL pointer argument to __threxit
10016b62b6aSguenther	pushl	$0		# slot for return address, ignored by kernel
101c6f64c6fSguenther	movl	$SYS___threxit, %eax
102*83762a71Sderaadt98:	int	$0x80
103*83762a71Sderaadt	PINSYSCALL(SYS___threxit, 98b)
10413df6982Sderaadt	int3
105c6f64c6fSguenther
106c6f64c6fSguenther	/*
107c6f64c6fSguenther	 * Branch here if the thread creation fails:
108c6f64c6fSguenther	 */
109c6f64c6fSguenther2:
11016b62b6aSguenther	addl	$12, %esp
11116b62b6aSguenther	popl	%edi
112c6f64c6fSguenther	popl	%esi
113c6f64c6fSguenther	movl	%ebp, %esp
114c6f64c6fSguenther	popl	%ebp
115fe38b55cSguenther	HANDLE_ERRNO()
116fe38b55cSguenther	ret
117aa797096SguentherEND(__tfork_thread)
118