The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=74a2bf1b7a7ff0c872499cb94df24713f61c872c

commit 74a2bf1b7a7ff0c872499cb94df24713f61c872c
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-01-25 17:33:05 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-01-26 19:30:05 +0000

    libsys: add pdrfork_thread() on x86
    
    Reviewed by:    asomers
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D54879
---
 lib/libsys/amd64/Makefile.sys     |   3 +-
 lib/libsys/amd64/Symbol.sys.map   |   4 ++
 lib/libsys/amd64/pdrfork_thread.S |  83 +++++++++++++++++++++++++++++++
 lib/libsys/i386/Makefile.sys      |   2 +-
 lib/libsys/i386/Symbol.sys.map    |   4 ++
 lib/libsys/i386/pdrfork_thread.S  | 101 ++++++++++++++++++++++++++++++++++++++
 sys/sys/procdesc.h                |   1 +
 7 files changed, 196 insertions(+), 2 deletions(-)

diff --git a/lib/libsys/amd64/Makefile.sys b/lib/libsys/amd64/Makefile.sys
index 8134bdc422a6..fc8ebe796081 100644
--- a/lib/libsys/amd64/Makefile.sys
+++ b/lib/libsys/amd64/Makefile.sys
@@ -4,6 +4,7 @@ SRCS+=  \
        amd64_set_fsbase.c \
        amd64_set_gsbase.c \
        amd64_set_tlsbase.c \
-       rfork_thread.S
+       rfork_thread.S \
+       pdrfork_thread.S
 
 MDASM= vfork.S cerror.S getcontext.S
diff --git a/lib/libsys/amd64/Symbol.sys.map b/lib/libsys/amd64/Symbol.sys.map
index 11e0507b6613..b037e12d45f5 100644
--- a/lib/libsys/amd64/Symbol.sys.map
+++ b/lib/libsys/amd64/Symbol.sys.map
@@ -17,6 +17,10 @@ FBSD_1.8 {
        amd64_set_tlsbase;
 };
 
+FBSD_1.9 {
+       pdrfork_thread;
+};
+
 FBSDprivate_1.0 {
        _vfork;
 };
diff --git a/lib/libsys/amd64/pdrfork_thread.S 
b/lib/libsys/amd64/pdrfork_thread.S
new file mode 100644
index 000000000000..cd187ae456ae
--- /dev/null
+++ b/lib/libsys/amd64/pdrfork_thread.S
@@ -0,0 +1,83 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2000 Peter Wemm <[email protected]>
+ * Copyright 2003 Alan L. Cox <[email protected]>
+ * Copyright 2026 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by
+ * Konstantin Belousov <[email protected]> under sponsorship from
+ * the FreeBSD Foundation.
+ */
+
+#include <machine/asm.h>
+/*
+ * With thanks to John Dyson for the original version of this.
+ */
+
+#include <SYS.h>
+
+/*
+ *                %rdi %esi     %rdx     %rcx        %r8        %r9
+ * pdrfork_thread(fdp, pdflags, rfflags, stack_addr, start_fnc, start_arg);
+ *
+ * fdp                 Pointer for the resulting fd location
+ * pdflags             Flags as to pdfork.
+ * rfflags:            Flags as to rfork.
+ * stack_addr:         Top of stack for thread.
+ * start_fnc:          Address of thread function to call in child.
+ * start_arg:          Argument to pass to the thread function in child.
+ */
+
+ENTRY(pdrfork_thread)
+       pushq   %rbx
+       pushq   %r12
+       pushq   %r13
+       movq    %r8, %rbx
+       movq    %r9, %r12
+       movq    %rcx, %r13
+
+       /*
+        * Prepare and execute the thread creation syscall
+        */
+       _SYSCALL(pdrfork)
+       jb      2f
+
+       /*
+        * Check to see if we are in the parent or child
+        */
+       cmpl    $0, %edx
+       jnz     1f
+       popq    %r13
+       popq    %r12
+       popq    %rbx
+       ret
+
+       /*
+        * If we are in the child (new thread), then
+        * set-up the call to the internal subroutine.  If it
+        * returns, then call __exit.
+        */
+1:
+       movq    %r13, %rsp
+       movq    %r12, %rdi
+       call    *%rbx
+       movl    %eax, %edi
+
+       /*
+        * Exit system call
+        */
+       _SYSCALL(exit)
+
+       /*
+        * Branch here if the thread creation fails:
+        */
+2:
+       popq    %r13
+       popq    %r12
+       popq    %rbx
+       jmp     HIDENAME(cerror)
+END(pdrfork_thread)
+
+       .section .note.GNU-stack,"",%progbits
diff --git a/lib/libsys/i386/Makefile.sys b/lib/libsys/i386/Makefile.sys
index 2957dc548cf8..69507d930f25 100644
--- a/lib/libsys/i386/Makefile.sys
+++ b/lib/libsys/i386/Makefile.sys
@@ -1,7 +1,7 @@
 SRCS+= i386_get_fsbase.c i386_get_gsbase.c i386_get_ioperm.c i386_get_ldt.c \
        i386_set_fsbase.c i386_set_gsbase.c i386_set_ioperm.c i386_set_ldt.c \
        i386_clr_watch.c i386_set_watch.c i386_vm86.c \
-       rfork_thread.S
+       rfork_thread.S pdrfork_thread.S
 
 MDASM= vfork.S cerror.S getcontext.S syscall.S
 
diff --git a/lib/libsys/i386/Symbol.sys.map b/lib/libsys/i386/Symbol.sys.map
index 6b3169336a3f..a35349e4953b 100644
--- a/lib/libsys/i386/Symbol.sys.map
+++ b/lib/libsys/i386/Symbol.sys.map
@@ -20,6 +20,10 @@ FBSD_1.6 {
         x86_pkru_unprotect_range;
 };
 
+FBSD_1.9 {
+       pdrfork_thread;
+};
+
 FBSDprivate_1.0 {
        _vfork;
 };
diff --git a/lib/libsys/i386/pdrfork_thread.S b/lib/libsys/i386/pdrfork_thread.S
new file mode 100644
index 000000000000..92a45fc4783f
--- /dev/null
+++ b/lib/libsys/i386/pdrfork_thread.S
@@ -0,0 +1,101 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2000 Peter Wemm <[email protected]>
+ * Copyright 2026 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by
+ * Konstantin Belousov <[email protected]> under sponsorship from
+ * the FreeBSD Foundation.
+ */
+
+#include <machine/asm.h>
+/*
+ * With thanks to John Dyson for the original version of this.
+ */
+
+#include <SYS.h>
+
+/*
+ *              8    12      16       20          24         28
+ * rfork_thread(fdp, pdflags rfflags, stack_addr, start_fnc, start_arg);
+ *
+ * fdp                 Pointer for the resulting fd location
+ * pdflags             Flags as to pdfork.
+ * rfflags:            Flags as to rfork.
+ * stack_addr:         Top of stack for thread.
+ * start_fnc:          Address of thread function to call in child.
+ * start_arg:          Argument to pass to the thread function in child.
+ */
+
+ENTRY(pdrfork_thread)
+       pushl   %ebp
+       movl    %esp, %ebp
+       pushl   %esi
+
+       /*
+        * Push thread info onto the new thread's stack
+        */
+       movl    20(%ebp), %esi  # get stack addr
+
+       subl    $4, %esi
+       movl    28(%ebp), %eax  # get start argument
+       movl    %eax, (%esi)
+
+       subl    $4, %esi
+       movl    24(%ebp), %eax  # get start thread address
+       movl    %eax, (%esi)
+
+       /*
+        * Prepare and execute the thread creation syscall
+        */
+       pushl   16(%ebp)
+       pushl   12(%ebp)
+       pushl   8(%ebp)
+       pushl   $0
+       _SYSCALL(pdrfork)
+       jb      2f
+
+       /*
+        * Check to see if we are in the parent or child
+        */
+       cmpl    $0, %edx
+       jnz     1f
+       addl    $16, %esp
+       popl    %esi
+       movl    %ebp, %esp
+       popl    %ebp
+       ret
+       .p2align 2
+
+       /*
+        * If we are in the child (new thread), then
+        * set-up the call to the internal subroutine.  If it
+        * returns, then call __exit.
+        */
+1:
+       movl    %esi,%esp
+       popl    %eax
+       call    *%eax
+       addl    $4, %esp
+
+       /*
+        * Exit system call
+        */
+       pushl   %eax
+       pushl   $0
+       _SYSCALL(exit)
+
+       /*
+        * Branch here if the thread creation fails:
+        */
+2:
+       addl    $16, %esp
+       popl    %esi
+       movl    %ebp, %esp
+       popl    %ebp
+       jmp     HIDENAME(cerror)
+END(pdrfork_thread)
+
+       .section .note.GNU-stack,"",%progbits
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
index 6a9168b04a68..b477903f8053 100644
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -130,6 +130,7 @@ pid_t        pdrfork(int *, int, int);
 int     pdkill(int, int);
 int     pdgetpid(int, pid_t *);
 int     pdwait(int, int *, int, struct __wrusage *, struct __siginfo *);
+pid_t   pdrfork_thread(int *, int, int, void *, int (*)(void *), void *);
 __END_DECLS
 
 #endif /* _KERNEL */

Reply via email to