From 6b96e7a5731795e76fe33df5a23edfb136f2e508 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Sun, 1 Jun 2025 10:00:18 +0300 Subject: [PATCH] libthr/amd64: do not set THR_C_RUNTIME for thr_new() if the main thread did used AMD64_SET_TLSBASE It is up to the code that organizes the runtime to properly set the signal handler, and to set %fsbase if libthr signal handler is to be called. The change should leave the CPU state on the signal handler entry identical to what it was before introduction of TLSBASE, for code that provides its own startup and thread pointer, but still calls into libthr as a hack. Sponsored by: The FreeBSD Foundation MFC after: 1 week --- 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(-) create mode 100644 lib/libthr/arch/amd64/amd64/thr_machdep.c diff --git a/lib/libthr/arch/aarch64/include/pthread_md.h b/lib/libthr/arch/aarch64/include/pthread_md.h index 305abed55d3..4316955f1d3 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 f8013ea914e..fe80e1a73cc 100644 --- a/lib/libthr/arch/amd64/Makefile.inc +++ b/lib/libthr/arch/amd64/Makefile.inc @@ -3,3 +3,5 @@ # 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 00000000000..d23e1689779 --- /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 +#include +#include + +#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 85517c1aee7..02b73d90f00 100644 --- a/lib/libthr/arch/amd64/include/pthread_md.h +++ b/lib/libthr/arch/amd64/include/pthread_md.h @@ -57,4 +57,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 d616868bdee..b90568e249e 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 7e2c8d7330f..43f84c3d039 100644 --- a/lib/libthr/arch/i386/include/pthread_md.h +++ b/lib/libthr/arch/i386/include/pthread_md.h @@ -57,4 +57,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 a5bc0265ed3..291f2d9350d 100644 --- a/lib/libthr/arch/powerpc/include/pthread_md.h +++ b/lib/libthr/arch/powerpc/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/riscv/include/pthread_md.h b/lib/libthr/arch/riscv/include/pthread_md.h index baddfe3ecb2..01dcc9c02b8 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 c66a5bb3bd2..e56dbcfe30e 100644 --- a/lib/libthr/thread/thr_create.c +++ b/lib/libthr/thread/thr_create.c @@ -50,6 +50,8 @@ int __getosreldate(void); 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 @@ -164,7 +166,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 bd1474a7c6e..64cf7d00407 100644 --- a/lib/libthr/thread/thr_init.c +++ b/lib/libthr/thread/thr_init.c @@ -354,7 +354,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 11afd74eea1..bca89082905 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -779,6 +779,8 @@ extern struct pthread *_single_thread __hidden; extern bool _thr_after_fork __hidden; +extern int __thr_new_flags; + /* * Function prototype definitions. */