From 8570a2a280587a1e43ac11ad46ad62dfdd6c7b39 Mon Sep 17 00:00:00 2001 From: "Alex Xu (Hello71)" Date: Thu, 2 Sep 2021 11:58:32 -0400 Subject: [PATCH] Use initial-exec TLS for glibc only, enable TLS elsewhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is not portable to use initial-exec TLS in dlopened libraries. glibc and FreeBSD allocate extra memory for extra initial-exec variables specifically for libGL, but other libcs including musl do not. Keep initial-exec disabled on FreeBSD since it is apparently broken for some reason: https://gitlab.freedesktop.org/mesa/mesa/-/issues/966#note_394512 https://github.com/jbeich/mesa/commit/81dbdb15d55054242eded0eb2f32621d583c1aaf Enable TLS on OpenBSD and Haiku based on the u_thread.h comment that emutls is better than pthread_getspecific, which seems plausible given that emutls has strictly more information to work with. Fixes #966. Acked-by: Tapani Pälli Acked-by: Jesse Natalie Part-of: --- meson.build | 7 ++----- src/mapi/entry.c | 28 ++++++++++++++-------------- src/util/u_thread.h | 16 ++++++---------- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/meson.build b/meson.build index cf2b5f4b939..a7ace23677c 100644 --- a/meson.build +++ b/meson.build @@ -508,15 +508,12 @@ foreach platform : _platforms pre_args += '-DHAVE_@0@_PLATFORM'.format(platform.to_upper()) endforeach -# Android uses emutls for versions <= P/28. For USE_ELF_TLS we need ELF TLS. use_elf_tls = false -if (not ['freebsd', 'openbsd', 'haiku'].contains(host_machine.system()) and - (not with_platform_android or get_option('platform-sdk-version') >= 29) and - (not with_platform_windows or not with_shared_glapi)) +if not with_platform_windows or not with_shared_glapi pre_args += '-DUSE_ELF_TLS' use_elf_tls = true - if with_platform_android + if with_platform_android and get_option('platform-sdk-version') >= 29 # By default the NDK compiler, at least, emits emutls references instead of # ELF TLS, even when building targeting newer API levels. Make it actually do # ELF TLS instead. diff --git a/src/mapi/entry.c b/src/mapi/entry.c index 7ff3c8f8c8c..b120eae31a1 100644 --- a/src/mapi/entry.c +++ b/src/mapi/entry.c @@ -31,6 +31,7 @@ #include "entry.h" #include "u_current.h" #include "util/u_endian.h" +#include "util/u_thread.h" #define _U_STRINGIFY(x) #x #define U_STRINGIFY(x) _U_STRINGIFY(x) @@ -45,20 +46,19 @@ #define ENTRY_CURRENT_TABLE_GET U_STRINGIFY(u_current_get_table_internal) #endif -#if defined(USE_X86_ASM) && defined(__GNUC__) -# ifdef USE_ELF_TLS -# include "entry_x86_tls.h" -# else -# include "entry_x86_tsd.h" -# endif -#elif defined(USE_X86_64_ASM) && defined(__GNUC__) && defined(USE_ELF_TLS) -# include "entry_x86-64_tls.h" -#elif defined(USE_PPC64LE_ASM) && defined(__GNUC__) && UTIL_ARCH_LITTLE_ENDIAN -# ifdef USE_ELF_TLS -# include "entry_ppc64le_tls.h" -# else -# include "entry_ppc64le_tsd.h" -# endif +/* REALLY_INITIAL_EXEC implies USE_ELF_TLS and __GNUC__ */ +/* Use TSD stubs for non-IE ELF TLS even though first access is slower because + * future accesses will be patched */ +#if defined(USE_X86_ASM) && defined(REALLY_INITIAL_EXEC) +#include "entry_x86_tls.h" +#elif defined(USE_X86_ASM) && !defined(GLX_X86_READONLY_TEXT) && defined(__GNUC__) +#include "entry_x86_tsd.h" +#elif defined(USE_X86_64_ASM) && defined(REALLY_INITIAL_EXEC) +#include "entry_x86-64_tls.h" +#elif defined(USE_PPC64LE_ASM) && UTIL_ARCH_LITTLE_ENDIAN && defined(REALLY_INITIAL_EXEC) +#include "entry_ppc64le_tls.h" +#elif defined(USE_PPC64LE_ASM) && UTIL_ARCH_LITTLE_ENDIAN && defined(__GNUC__) +#include "entry_ppc64le_tsd.h" #else static inline const struct _glapi_table * diff --git a/src/util/u_thread.h b/src/util/u_thread.h index 0fb474f32ba..a4215452d35 100644 --- a/src/util/u_thread.h +++ b/src/util/u_thread.h @@ -75,19 +75,15 @@ * still want to use normal TLS (which involves a function call, but not the * expensive pthread_getspecific() or its equivalent). */ +#ifdef USE_ELF_TLS #ifdef _MSC_VER #define __THREAD_INITIAL_EXEC __declspec(thread) -#elif defined(ANDROID) -/* Android 29 gained ELF TLS support, but it doesn't support initial-exec and - * it will throw: - * - * dlopen failed: TLS symbol "(null)" in dlopened - * "/vendor/lib64/egl/libEGL_mesa.so" referenced from - * "/vendor/lib64/egl/libEGL_mesa.so" using IE access model. - */ -#define __THREAD_INITIAL_EXEC __thread -#else +#elif defined(__GLIBC__) #define __THREAD_INITIAL_EXEC __thread __attribute__((tls_model("initial-exec"))) +#define REALLY_INITIAL_EXEC +#else +#define __THREAD_INITIAL_EXEC __thread +#endif #endif static inline int