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