git: 74a2bf1b7a7f - main - libsys: add pdrfork_thread() on x86
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 26 Jan 2026 19:30:57 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=74a2bf1b7a7ff0c872499cb94df24713f61c872c
commit 74a2bf1b7a7ff0c872499cb94df24713f61c872c
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-01-25 17:33:05 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
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 <peter@FreeBSD.org>
+ * Copyright 2003 Alan L. Cox <alc@cs.rice.edu>
+ * Copyright 2026 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by
+ * Konstantin Belousov <kib@FreeBSD.org> 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 <peter@FreeBSD.org>
+ * Copyright 2026 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * Portions of this software were developed by
+ * Konstantin Belousov <kib@FreeBSD.org> 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 */