From 75a9cb1033a954a5a160335405a7627ae7c4aa66 Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Fri, 21 May 2021 13:23:07 -0700 Subject: [PATCH] util: Add a helper macro for defining initial-exec variables. I'm going to add another case for Android shortly, and then we can keep the logic all in one spot. Reviewed-by: Roman Stratiienko Reviewed-by: Emil Velikov Part-of: --- src/egl/main/eglcurrent.c | 4 ++-- src/glx/glxclient.h | 4 ++-- src/glx/glxcurrent.c | 3 +-- src/mapi/glapi/glapi.h | 7 +++---- src/mapi/u_current.c | 12 ++---------- src/mapi/u_current.h | 7 ++----- src/util/u_thread.h | 16 ++++++++++++++++ 7 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c index 29be4268025..11277d3e4c0 100644 --- a/src/egl/main/eglcurrent.c +++ b/src/egl/main/eglcurrent.c @@ -32,6 +32,7 @@ #include #include "c99_compat.h" #include "c11/threads.h" +#include "util/u_thread.h" #include "egllog.h" #include "eglcurrent.h" @@ -45,8 +46,7 @@ static tss_t _egl_TSD; static void _eglDestroyThreadInfo(_EGLThreadInfo *t); #ifdef USE_ELF_TLS -static __thread const _EGLThreadInfo *_egl_TLS - __attribute__ ((tls_model("initial-exec"))); +static __THREAD_INITIAL_EXEC const _EGLThreadInfo *_egl_TLS; #endif static inline void _eglSetTSD(const _EGLThreadInfo *t) diff --git a/src/glx/glxclient.h b/src/glx/glxclient.h index e335571b918..68df42f53b0 100644 --- a/src/glx/glxclient.h +++ b/src/glx/glxclient.h @@ -53,6 +53,7 @@ #include "glxconfig.h" #include "glxhash.h" #include "util/macros.h" +#include "util/u_thread.h" #include "loader.h" #include "glxextensions.h" @@ -645,8 +646,7 @@ extern void __glXSetCurrentContext(struct glx_context * c); # if defined( USE_ELF_TLS ) -extern __thread void *__glX_tls_Context - __attribute__ ((tls_model("initial-exec"))); +extern __THREAD_INITIAL_EXEC void *__glX_tls_Context; # define __glXGetCurrentContext() __glX_tls_Context diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c index ee93114161c..ffc7c3c7687 100644 --- a/src/glx/glxcurrent.c +++ b/src/glx/glxcurrent.c @@ -76,8 +76,7 @@ _X_HIDDEN pthread_mutex_t __glXmutex = PTHREAD_MUTEX_INITIALIZER; * \b never be \c NULL. This is important! Because of this * \c __glXGetCurrentContext can be implemented as trivial macro. */ -__thread void *__glX_tls_Context __attribute__ ((tls_model("initial-exec"))) - = &dummyContext; +__THREAD_INITIAL_EXEC void *__glX_tls_Context = &dummyContext; _X_HIDDEN void __glXSetCurrentContext(struct glx_context * c) diff --git a/src/mapi/glapi/glapi.h b/src/mapi/glapi/glapi.h index d6a0ebfcf8a..275bc1f3ddc 100644 --- a/src/mapi/glapi/glapi.h +++ b/src/mapi/glapi/glapi.h @@ -45,6 +45,7 @@ #define _GLAPI_H #include "util/macros.h" +#include "util/u_thread.h" #ifdef __cplusplus @@ -82,11 +83,9 @@ struct _glapi_table; extern __declspec(thread) struct _glapi_table * _glapi_tls_Dispatch; extern __declspec(thread) void * _glapi_tls_Context; #else -_GLAPI_EXPORT extern __thread struct _glapi_table * _glapi_tls_Dispatch - __attribute__((tls_model("initial-exec"))); +_GLAPI_EXPORT extern __THREAD_INITIAL_EXEC struct _glapi_table * _glapi_tls_Dispatch; -_GLAPI_EXPORT extern __thread void * _glapi_tls_Context - __attribute__((tls_model("initial-exec"))); +_GLAPI_EXPORT extern __THREAD_INITIAL_EXEC void * _glapi_tls_Context; #endif _GLAPI_EXPORT extern const struct _glapi_table *_glapi_Dispatch; diff --git a/src/mapi/u_current.c b/src/mapi/u_current.c index 7a95e96f509..cd09140592e 100644 --- a/src/mapi/u_current.c +++ b/src/mapi/u_current.c @@ -100,18 +100,10 @@ extern void (*__glapi_noop_table[])(void); /*@{*/ #if defined(USE_ELF_TLS) -#ifdef _MSC_VER -__declspec(thread) struct _glapi_table *u_current_table - = (struct _glapi_table *) table_noop_array; -__declspec(thread) void *u_current_context; -#else -__thread struct _glapi_table *u_current_table - __attribute__((tls_model("initial-exec"))) +__THREAD_INITIAL_EXEC struct _glapi_table *u_current_table = (struct _glapi_table *) table_noop_array; -__thread void *u_current_context - __attribute__((tls_model("initial-exec"))); -#endif +__THREAD_INITIAL_EXEC void *u_current_context; #else diff --git a/src/mapi/u_current.h b/src/mapi/u_current.h index e7faa878ed1..52da534797a 100644 --- a/src/mapi/u_current.h +++ b/src/mapi/u_current.h @@ -29,11 +29,8 @@ struct _glapi_table; #ifdef USE_ELF_TLS -extern __thread struct _glapi_table *u_current_table - __attribute__((tls_model("initial-exec"))); - -extern __thread void *u_current_context - __attribute__((tls_model("initial-exec"))); +extern __THREAD_INITIAL_EXEC struct _glapi_table *u_current_table; +extern __THREAD_INITIAL_EXEC void *u_current_context; #else /* USE_ELF_TLS */ diff --git a/src/util/u_thread.h b/src/util/u_thread.h index 5fd2fe502ee..e79d91ddff8 100644 --- a/src/util/u_thread.h +++ b/src/util/u_thread.h @@ -65,6 +65,22 @@ #define UTIL_MAX_CPUS 1024 /* this should be enough */ #define UTIL_MAX_L3_CACHES UTIL_MAX_CPUS +/* Some highly performance-sensitive thread-local variables like the current GL + * context are declared with the initial-exec model on Linux. glibc allocates a + * fixed number of extra slots for initial-exec TLS variables at startup, and + * Mesa relies on (even if it's dlopen()ed after init) being able to fit into + * those. This model saves the call to look up the address of the TLS variable. + * + * However, if we don't have this TLS model available on the platform, then we + * still want to use normal TLS (which involves a function call, but not the + * expensive pthread_getspecific() or its equivalent). + */ +#ifdef _MSC_VER +#define __THREAD_INITIAL_EXEC __declspec(thread) +#else +#define __THREAD_INITIAL_EXEC __thread __attribute__((tls_model("initial-exec"))) +#endif + static inline int util_get_current_cpu(void) {