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
This commit is contained in:
Konstantin Belousov 2025-06-01 10:00:18 +03:00
parent 2e91875bc2
commit 6b96e7a573
11 changed files with 68 additions and 2 deletions

View file

@ -54,4 +54,6 @@ _thr_resolve_machdep(void)
{
}
#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb)
#endif /* _PTHREAD_MD_H_ */

View file

@ -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

View file

@ -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);
}
}

View file

@ -57,4 +57,6 @@ _thr_resolve_machdep(void)
{
}
void __thr_setup_tsd(struct pthread *thread);
#endif

View file

@ -48,4 +48,6 @@ _get_curthread(void)
return (NULL);
}
#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb)
#endif /* _PTHREAD_MD_H_ */

View file

@ -57,4 +57,6 @@ _thr_resolve_machdep(void)
{
}
#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb)
#endif

View file

@ -54,4 +54,6 @@ _thr_resolve_machdep(void)
{
}
#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb)
#endif /* _PTHREAD_MD_H_ */

View file

@ -61,4 +61,6 @@ _thr_resolve_machdep(void)
{
}
#define __thr_setup_tsd(thread) _tcb_set((thread)->tcb)
#endif /* _PTHREAD_MD_H_ */

View file

@ -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)

View file

@ -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;

View file

@ -779,6 +779,8 @@ extern struct pthread *_single_thread __hidden;
extern bool _thr_after_fork __hidden;
extern int __thr_new_flags;
/*
* Function prototype definitions.
*/