xref: /freebsd/lib/libsys/i386/pdrfork_thread.S (revision 74a2bf1b7a7ff0c872499cb94df24713f61c872c)
1*74a2bf1bSKonstantin Belousov/*-
2*74a2bf1bSKonstantin Belousov * SPDX-License-Identifier: BSD-2-Clause
3*74a2bf1bSKonstantin Belousov *
4*74a2bf1bSKonstantin Belousov * Copyright 2000 Peter Wemm <peter@FreeBSD.org>
5*74a2bf1bSKonstantin Belousov * Copyright 2026 The FreeBSD Foundation
6*74a2bf1bSKonstantin Belousov * All rights reserved.
7*74a2bf1bSKonstantin Belousov *
8*74a2bf1bSKonstantin Belousov * Portions of this software were developed by
9*74a2bf1bSKonstantin Belousov * Konstantin Belousov <kib@FreeBSD.org> under sponsorship from
10*74a2bf1bSKonstantin Belousov * the FreeBSD Foundation.
11*74a2bf1bSKonstantin Belousov */
12*74a2bf1bSKonstantin Belousov
13*74a2bf1bSKonstantin Belousov#include <machine/asm.h>
14*74a2bf1bSKonstantin Belousov/*
15*74a2bf1bSKonstantin Belousov * With thanks to John Dyson for the original version of this.
16*74a2bf1bSKonstantin Belousov */
17*74a2bf1bSKonstantin Belousov
18*74a2bf1bSKonstantin Belousov#include <SYS.h>
19*74a2bf1bSKonstantin Belousov
20*74a2bf1bSKonstantin Belousov/*
21*74a2bf1bSKonstantin Belousov *              8    12      16       20          24         28
22*74a2bf1bSKonstantin Belousov * rfork_thread(fdp, pdflags rfflags, stack_addr, start_fnc, start_arg);
23*74a2bf1bSKonstantin Belousov *
24*74a2bf1bSKonstantin Belousov * fdp			Pointer for the resulting fd location
25*74a2bf1bSKonstantin Belousov * pdflags		Flags as to pdfork.
26*74a2bf1bSKonstantin Belousov * rfflags:		Flags as to rfork.
27*74a2bf1bSKonstantin Belousov * stack_addr:		Top of stack for thread.
28*74a2bf1bSKonstantin Belousov * start_fnc:		Address of thread function to call in child.
29*74a2bf1bSKonstantin Belousov * start_arg:		Argument to pass to the thread function in child.
30*74a2bf1bSKonstantin Belousov */
31*74a2bf1bSKonstantin Belousov
32*74a2bf1bSKonstantin BelousovENTRY(pdrfork_thread)
33*74a2bf1bSKonstantin Belousov	pushl	%ebp
34*74a2bf1bSKonstantin Belousov	movl	%esp, %ebp
35*74a2bf1bSKonstantin Belousov	pushl	%esi
36*74a2bf1bSKonstantin Belousov
37*74a2bf1bSKonstantin Belousov	/*
38*74a2bf1bSKonstantin Belousov	 * Push thread info onto the new thread's stack
39*74a2bf1bSKonstantin Belousov	 */
40*74a2bf1bSKonstantin Belousov	movl	20(%ebp), %esi	# get stack addr
41*74a2bf1bSKonstantin Belousov
42*74a2bf1bSKonstantin Belousov	subl	$4, %esi
43*74a2bf1bSKonstantin Belousov	movl	28(%ebp), %eax	# get start argument
44*74a2bf1bSKonstantin Belousov	movl	%eax, (%esi)
45*74a2bf1bSKonstantin Belousov
46*74a2bf1bSKonstantin Belousov	subl	$4, %esi
47*74a2bf1bSKonstantin Belousov	movl	24(%ebp), %eax	# get start thread address
48*74a2bf1bSKonstantin Belousov	movl	%eax, (%esi)
49*74a2bf1bSKonstantin Belousov
50*74a2bf1bSKonstantin Belousov	/*
51*74a2bf1bSKonstantin Belousov	 * Prepare and execute the thread creation syscall
52*74a2bf1bSKonstantin Belousov	 */
53*74a2bf1bSKonstantin Belousov	pushl	16(%ebp)
54*74a2bf1bSKonstantin Belousov	pushl	12(%ebp)
55*74a2bf1bSKonstantin Belousov	pushl	8(%ebp)
56*74a2bf1bSKonstantin Belousov	pushl	$0
57*74a2bf1bSKonstantin Belousov	_SYSCALL(pdrfork)
58*74a2bf1bSKonstantin Belousov	jb 	2f
59*74a2bf1bSKonstantin Belousov
60*74a2bf1bSKonstantin Belousov	/*
61*74a2bf1bSKonstantin Belousov	 * Check to see if we are in the parent or child
62*74a2bf1bSKonstantin Belousov	 */
63*74a2bf1bSKonstantin Belousov	cmpl	$0, %edx
64*74a2bf1bSKonstantin Belousov	jnz	1f
65*74a2bf1bSKonstantin Belousov	addl	$16, %esp
66*74a2bf1bSKonstantin Belousov	popl	%esi
67*74a2bf1bSKonstantin Belousov	movl	%ebp, %esp
68*74a2bf1bSKonstantin Belousov	popl	%ebp
69*74a2bf1bSKonstantin Belousov	ret
70*74a2bf1bSKonstantin Belousov	.p2align 2
71*74a2bf1bSKonstantin Belousov
72*74a2bf1bSKonstantin Belousov	/*
73*74a2bf1bSKonstantin Belousov	 * If we are in the child (new thread), then
74*74a2bf1bSKonstantin Belousov	 * set-up the call to the internal subroutine.  If it
75*74a2bf1bSKonstantin Belousov	 * returns, then call __exit.
76*74a2bf1bSKonstantin Belousov	 */
77*74a2bf1bSKonstantin Belousov1:
78*74a2bf1bSKonstantin Belousov	movl	%esi,%esp
79*74a2bf1bSKonstantin Belousov	popl	%eax
80*74a2bf1bSKonstantin Belousov	call	*%eax
81*74a2bf1bSKonstantin Belousov	addl	$4, %esp
82*74a2bf1bSKonstantin Belousov
83*74a2bf1bSKonstantin Belousov	/*
84*74a2bf1bSKonstantin Belousov	 * Exit system call
85*74a2bf1bSKonstantin Belousov	 */
86*74a2bf1bSKonstantin Belousov	pushl	%eax
87*74a2bf1bSKonstantin Belousov	pushl	$0
88*74a2bf1bSKonstantin Belousov	_SYSCALL(exit)
89*74a2bf1bSKonstantin Belousov
90*74a2bf1bSKonstantin Belousov	/*
91*74a2bf1bSKonstantin Belousov	 * Branch here if the thread creation fails:
92*74a2bf1bSKonstantin Belousov	 */
93*74a2bf1bSKonstantin Belousov2:
94*74a2bf1bSKonstantin Belousov	addl	$16, %esp
95*74a2bf1bSKonstantin Belousov	popl	%esi
96*74a2bf1bSKonstantin Belousov	movl	%ebp, %esp
97*74a2bf1bSKonstantin Belousov	popl	%ebp
98*74a2bf1bSKonstantin Belousov	jmp	HIDENAME(cerror)
99*74a2bf1bSKonstantin BelousovEND(pdrfork_thread)
100*74a2bf1bSKonstantin Belousov
101*74a2bf1bSKonstantin Belousov	.section .note.GNU-stack,"",%progbits
102