git: 7db7118976b5 - stable/14 - libthr/amd64: do not set THR_C_RUNTIME for thr_new() if the main thread did used AMD64_SET_TLSBASE

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Sun, 29 Jun 2025 00:30:01 UTC
The branch stable/14 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=7db7118976b5d8a8d981a801c0e5e5fcbccad462

commit 7db7118976b5d8a8d981a801c0e5e5fcbccad462
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-06-01 07:00:18 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-06-29 00:29:12 +0000

    libthr/amd64: do not set THR_C_RUNTIME for thr_new() if the main thread did used AMD64_SET_TLSBASE
    
    (cherry picked from commit 6b96e7a5731795e76fe33df5a23edfb136f2e508)
---
 lib/libthr/arch/aarch64/include/pthread_md.h |  2 ++
 lib/libthr/arch/amd64/Makefile.inc           |  2 ++
 lib/libthr/arch/amd64/amd64/thr_machdep.c    | 48 ++++++++++++++++++++++++++++
 lib/libthr/arch/amd64/include/pthread_md.h   |  2 ++
 lib/libthr/arch/arm/include/pthread_md.h     |  2 ++
 lib/libthr/arch/i386/include/pthread_md.h    |  2 ++
 lib/libthr/arch/powerpc/include/pthread_md.h |  2 ++
 lib/libthr/arch/riscv/include/pthread_md.h   |  2 ++
 lib/libthr/thread/thr_create.c               |  4 ++-
 lib/libthr/thread/thr_init.c                 |  2 +-
 lib/libthr/thread/thr_private.h              |  2 ++
 11 files changed, 68 insertions(+), 2 deletions(-)

diff --git a/lib/libthr/arch/aarch64/include/pthread_md.h b/lib/libthr/arch/aarch64/include/pthread_md.h
index 305abed55d3c..4316955f1d3d 100644
--- a/lib/libthr/arch/aarch64/include/pthread_md.h
+++ b/lib/libthr/arch/aarch64/include/pthread_md.h
@@ -54,4 +54,6 @@ _thr_resolve_machdep(void)
 {
 }
 
+#define	__thr_setup_tsd(thread)		_tcb_set((thread)->tcb)
+
 #endif /* _PTHREAD_MD_H_ */
diff --git a/lib/libthr/arch/amd64/Makefile.inc b/lib/libthr/arch/amd64/Makefile.inc
index 24e5dd7c9b03..9b8d21e5f880 100644
--- a/lib/libthr/arch/amd64/Makefile.inc
+++ b/lib/libthr/arch/amd64/Makefile.inc
@@ -6,3 +6,5 @@ SRCS+=	_umtx_op_err.S
 # the extra context switch cost.  This can measurably impact
 # performance when the application also does not use enough SSE.
 CFLAGS+=${CFLAGS_NO_SIMD}
+
+SRCS+= thr_machdep.c
diff --git a/lib/libthr/arch/amd64/amd64/thr_machdep.c b/lib/libthr/arch/amd64/amd64/thr_machdep.c
new file mode 100644
index 000000000000..d23e1689779c
--- /dev/null
+++ b/lib/libthr/arch/amd64/amd64/thr_machdep.c
@@ -0,0 +1,48 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2025 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ */
+
+#define _WANT_P_OSREL
+#include <sys/param.h>
+#include <errno.h>
+#include <machine/sysarch.h>
+
+#include "libc_private.h"
+#include "thr_private.h"
+
+void
+__thr_setup_tsd(struct pthread *thread)
+{
+	void *base;
+	int error;
+
+	if (__getosreldate() < P_OSREL_TLSBASE) {
+		amd64_set_tlsbase(thread->tcb);
+		return;
+	}
+
+	/*
+	 * Make tlsbase handling more compatible with code, like Go
+	 * runtime, which wants to manage fsbase itself, and which do
+	 * not need assistance in setting fsbase for signal handlers.
+	 *
+	 * If the main thread did not used amd64_set_tlsbase(), which
+	 * means that rtld/libc was not utilized, do not use
+	 * amd64_set_tlsbase() either.  Also do not mark new threads
+	 * as using C runtime with the THR_C_RUNTIME flag.
+	 */
+	error = sysarch(AMD64_GET_TLSBASE, &base);
+	if (error != 0 && errno == ESRCH) {
+		__thr_new_flags &= ~THR_C_RUNTIME;
+		amd64_set_fsbase(thread->tcb);
+	} else {
+		amd64_set_tlsbase(thread->tcb);
+	}
+}
diff --git a/lib/libthr/arch/amd64/include/pthread_md.h b/lib/libthr/arch/amd64/include/pthread_md.h
index 5b1486b151c0..ff0dd218516f 100644
--- a/lib/libthr/arch/amd64/include/pthread_md.h
+++ b/lib/libthr/arch/amd64/include/pthread_md.h
@@ -59,4 +59,6 @@ _thr_resolve_machdep(void)
 {
 }
 
+void __thr_setup_tsd(struct pthread *thread);
+
 #endif
diff --git a/lib/libthr/arch/arm/include/pthread_md.h b/lib/libthr/arch/arm/include/pthread_md.h
index d616868bdee4..b90568e249ee 100644
--- a/lib/libthr/arch/arm/include/pthread_md.h
+++ b/lib/libthr/arch/arm/include/pthread_md.h
@@ -48,4 +48,6 @@ _get_curthread(void)
 	return (NULL);
 }
 
+#define	__thr_setup_tsd(thread)		_tcb_set((thread)->tcb)
+
 #endif /* _PTHREAD_MD_H_ */
diff --git a/lib/libthr/arch/i386/include/pthread_md.h b/lib/libthr/arch/i386/include/pthread_md.h
index cb9af559db32..2bddea3d7f16 100644
--- a/lib/libthr/arch/i386/include/pthread_md.h
+++ b/lib/libthr/arch/i386/include/pthread_md.h
@@ -59,4 +59,6 @@ _thr_resolve_machdep(void)
 {
 }
 
+#define	__thr_setup_tsd(thread)		_tcb_set((thread)->tcb)
+
 #endif
diff --git a/lib/libthr/arch/powerpc/include/pthread_md.h b/lib/libthr/arch/powerpc/include/pthread_md.h
index 31fa9820b26a..262c27858beb 100644
--- a/lib/libthr/arch/powerpc/include/pthread_md.h
+++ b/lib/libthr/arch/powerpc/include/pthread_md.h
@@ -56,4 +56,6 @@ _thr_resolve_machdep(void)
 {
 }
 
+#define	__thr_setup_tsd(thread)		_tcb_set((thread)->tcb)
+
 #endif /* _PTHREAD_MD_H_ */
diff --git a/lib/libthr/arch/riscv/include/pthread_md.h b/lib/libthr/arch/riscv/include/pthread_md.h
index baddfe3ecb22..01dcc9c02b8c 100644
--- a/lib/libthr/arch/riscv/include/pthread_md.h
+++ b/lib/libthr/arch/riscv/include/pthread_md.h
@@ -61,4 +61,6 @@ _thr_resolve_machdep(void)
 {
 }
 
+#define	__thr_setup_tsd(thread)		_tcb_set((thread)->tcb)
+
 #endif /* _PTHREAD_MD_H_ */
diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c
index 84bbd36ed28d..d8d590ed02b7 100644
--- a/lib/libthr/thread/thr_create.c
+++ b/lib/libthr/thread/thr_create.c
@@ -46,6 +46,8 @@
 static int  create_stack(struct pthread_attr *pattr);
 static void thread_start(struct pthread *curthread);
 
+int __thr_new_flags = THR_C_RUNTIME;
+
 __weak_reference(_pthread_create, pthread_create);
 
 int
@@ -160,7 +162,7 @@ _pthread_create(pthread_t * __restrict thread,
 	param.tls_size = sizeof(struct tcb);
 	param.child_tid = &new_thread->tid;
 	param.parent_tid = &new_thread->tid;
-	param.flags = THR_C_RUNTIME;
+	param.flags = __thr_new_flags;
 	if (new_thread->attr.flags & PTHREAD_SCOPE_SYSTEM)
 		param.flags |= THR_SYSTEM_SCOPE;
 	if (new_thread->attr.sched_inherit == PTHREAD_INHERIT_SCHED)
diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index 80f7c05ee5ce..13a2e403af3b 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -350,7 +350,7 @@ _libpthread_init(struct pthread *curthread)
 	_thread_active_threads = 1;
 
 	/* Setup the thread specific data */
-	_tcb_set(curthread->tcb);
+	__thr_setup_tsd(curthread);
 
 	if (first) {
 		_thr_initial = curthread;
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index a81452e2a251..508328482f80 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -776,6 +776,8 @@ extern struct pthread	*_single_thread __hidden;
 
 extern bool		_thr_after_fork __hidden;
 
+extern int	__thr_new_flags;
+
 /*
  * Function prototype definitions.
  */