diff --git a/src/cocoa_init.m b/src/cocoa_init.m index 0913c476..ba5ddb62 100644 --- a/src/cocoa_init.m +++ b/src/cocoa_init.m @@ -311,9 +311,6 @@ int _glfwPlatformInit(void) if (!initializeTIS()) return GLFW_FALSE; - if (!_glfwInitThreadLocalStoragePOSIX()) - return GLFW_FALSE; - _glfwInitTimerNS(); _glfwInitJoysticksNS(); @@ -362,7 +359,6 @@ void _glfwPlatformTerminate(void) _glfwTerminateNSGL(); _glfwTerminateJoysticksNS(); - _glfwTerminateThreadLocalStoragePOSIX(); [_glfw.ns.autoreleasePool release]; _glfw.ns.autoreleasePool = nil; diff --git a/src/context.c b/src/context.c index ed921a4b..498e0e16 100644 --- a/src/context.c +++ b/src/context.c @@ -331,7 +331,7 @@ GLFWbool _glfwRefreshContextAttribs(const _GLFWctxconfig* ctxconfig) NULL }; - window = _glfwPlatformGetCurrentContext(); + window = _glfwPlatformGetTls(&_glfw.context); window->context.source = ctxconfig->source; window->context.client = GLFW_OPENGL_API; @@ -578,7 +578,7 @@ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; - _GLFWwindow* previous = _glfwPlatformGetCurrentContext(); + _GLFWwindow* previous = _glfwPlatformGetTls(&_glfw.context); _GLFW_REQUIRE_INIT(); @@ -601,7 +601,7 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow* handle) GLFWAPI GLFWwindow* glfwGetCurrentContext(void) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - return (GLFWwindow*) _glfwPlatformGetCurrentContext(); + return _glfwPlatformGetTls(&_glfw.context); } GLFWAPI void glfwSwapBuffers(GLFWwindow* handle) @@ -626,7 +626,7 @@ GLFWAPI void glfwSwapInterval(int interval) _GLFW_REQUIRE_INIT(); - window = _glfwPlatformGetCurrentContext(); + window = _glfwPlatformGetTls(&_glfw.context); if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); @@ -643,7 +643,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension) _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); - window = _glfwPlatformGetCurrentContext(); + window = _glfwPlatformGetTls(&_glfw.context); if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); @@ -708,7 +708,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) _GLFW_REQUIRE_INIT_OR_RETURN(NULL); - window = _glfwPlatformGetCurrentContext(); + window = _glfwPlatformGetTls(&_glfw.context); if (!window) { _glfwInputError(GLFW_NO_CURRENT_CONTEXT, NULL); diff --git a/src/egl_context.c b/src/egl_context.c index e73fc0b4..328a0457 100644 --- a/src/egl_context.c +++ b/src/egl_context.c @@ -199,12 +199,12 @@ static void makeContextCurrentEGL(_GLFWwindow* window) } } - _glfwPlatformSetCurrentContext(window); + _glfwPlatformSetTls(&_glfw.context, window); } static void swapBuffersEGL(_GLFWwindow* window) { - if (window != _glfwPlatformGetCurrentContext()) + if (window != _glfwPlatformGetTls(&_glfw.context)) { _glfwInputError(GLFW_PLATFORM_ERROR, "EGL: The context must be current on the calling thread when swapping buffers"); @@ -233,7 +233,7 @@ static int extensionSupportedEGL(const char* extension) static GLFWglproc getProcAddressEGL(const char* procname) { - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); + _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context); if (window->context.egl.client) { diff --git a/src/glx_context.c b/src/glx_context.c index 2faf599c..9c2ccb12 100644 --- a/src/glx_context.c +++ b/src/glx_context.c @@ -165,7 +165,7 @@ static void makeContextCurrentGLX(_GLFWwindow* window) } } - _glfwPlatformSetCurrentContext(window); + _glfwPlatformSetTls(&_glfw.context, window); } static void swapBuffersGLX(_GLFWwindow* window) @@ -175,7 +175,7 @@ static void swapBuffersGLX(_GLFWwindow* window) static void swapIntervalGLX(int interval) { - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); + _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context); if (_glfw.glx.EXT_swap_control) { diff --git a/src/init.c b/src/init.c index b2da9a77..92450b59 100644 --- a/src/init.c +++ b/src/init.c @@ -113,6 +113,8 @@ static void terminate(void) _glfwTerminateVulkan(); _glfwPlatformTerminate(); + _glfwPlatformDestroyTls(&_glfw.context); + memset(&_glfw, 0, sizeof(_glfw)); } @@ -162,6 +164,9 @@ GLFWAPI int glfwInit(void) memset(&_glfw, 0, sizeof(_glfw)); _glfw.hints.init = _glfwInitHints; + if (!_glfwPlatformCreateTls(&_glfw.context)) + return GLFW_FALSE; + if (!_glfwPlatformInit()) { terminate(); diff --git a/src/internal.h b/src/internal.h index 13214b07..d3a4f687 100644 --- a/src/internal.h +++ b/src/internal.h @@ -69,6 +69,7 @@ typedef struct _GLFWlibrary _GLFWlibrary; typedef struct _GLFWmonitor _GLFWmonitor; typedef struct _GLFWcursor _GLFWcursor; typedef struct _GLFWjoystick _GLFWjoystick; +typedef struct _GLFWtls _GLFWtls; typedef void (* _GLFWmakecontextcurrentfun)(_GLFWwindow*); typedef void (* _GLFWswapbuffersfun)(_GLFWwindow*); @@ -485,6 +486,14 @@ struct _GLFWjoystick _GLFW_PLATFORM_JOYSTICK_STATE; }; +/*! @brief Thread local storage structure. + */ +struct _GLFWtls +{ + // This is defined in the platform's tls.h + _GLFW_PLATFORM_TLS_STATE; +}; + /*! @brief Library global data. */ struct _GLFWlibrary @@ -510,6 +519,8 @@ struct _GLFWlibrary uint64_t timerOffset; + _GLFWtls context; + struct { GLFWbool available; void* handle; @@ -546,8 +557,6 @@ struct _GLFWlibrary _GLFW_PLATFORM_LIBRARY_TIME_STATE; // This is defined in the platform's joystick.h _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE; - // This is defined in the platform's tls.h - _GLFW_PLATFORM_LIBRARY_TLS_STATE; // This is defined in egl_context.h _GLFW_EGL_LIBRARY_CONTEXT_STATE; // This is defined in osmesa_context.h @@ -634,13 +643,15 @@ void _glfwPlatformWaitEvents(void); void _glfwPlatformWaitEventsTimeout(double timeout); void _glfwPlatformPostEmptyEvent(void); -void _glfwPlatformSetCurrentContext(_GLFWwindow* context); -_GLFWwindow* _glfwPlatformGetCurrentContext(void); - void _glfwPlatformGetRequiredInstanceExtensions(char** extensions); int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); +GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls); +void _glfwPlatformDestroyTls(_GLFWtls* tls); +void* _glfwPlatformGetTls(_GLFWtls* tls); +void _glfwPlatformSetTls(_GLFWtls* tls, void* value); + /*! @} */ diff --git a/src/mir_init.c b/src/mir_init.c index 5df5d981..3a96c78a 100644 --- a/src/mir_init.c +++ b/src/mir_init.c @@ -190,9 +190,6 @@ int _glfwPlatformInit(void) createKeyTables(); - if (!_glfwInitThreadLocalStoragePOSIX()) - return GLFW_FALSE; - if (!_glfwInitJoysticksLinux()) return GLFW_FALSE; @@ -222,7 +219,6 @@ void _glfwPlatformTerminate(void) { _glfwTerminateEGL(); _glfwTerminateJoysticksLinux(); - _glfwTerminateThreadLocalStoragePOSIX(); _glfwDeleteEventQueueMir(_glfw.mir.eventQueue); diff --git a/src/nsgl_context.m b/src/nsgl_context.m index 97663644..f2902d7f 100644 --- a/src/nsgl_context.m +++ b/src/nsgl_context.m @@ -34,7 +34,7 @@ static void makeContextCurrentNSGL(_GLFWwindow* window) else [NSOpenGLContext clearCurrentContext]; - _glfwPlatformSetCurrentContext(window); + _glfwPlatformSetTls(&_glfw.context, window); } static void swapBuffersNSGL(_GLFWwindow* window) @@ -45,7 +45,7 @@ static void swapBuffersNSGL(_GLFWwindow* window) static void swapIntervalNSGL(int interval) { - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); + _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context); GLint sync = interval; [window->context.nsgl.object setValues:&sync diff --git a/src/null_init.c b/src/null_init.c index e2c9c74b..34147388 100644 --- a/src/null_init.c +++ b/src/null_init.c @@ -34,9 +34,6 @@ int _glfwPlatformInit(void) { - if (!_glfwInitThreadLocalStoragePOSIX()) - return GLFW_FALSE; - _glfwInitTimerPOSIX(); return GLFW_TRUE; } @@ -44,7 +41,6 @@ int _glfwPlatformInit(void) void _glfwPlatformTerminate(void) { _glfwTerminateOSMesa(); - _glfwTerminateThreadLocalStoragePOSIX(); } const char* _glfwPlatformGetVersionString(void) diff --git a/src/osmesa_context.c b/src/osmesa_context.c index 579dc391..7ea65627 100644 --- a/src/osmesa_context.c +++ b/src/osmesa_context.c @@ -63,7 +63,7 @@ static void makeContextCurrentOSMesa(_GLFWwindow* window) } } - _glfwPlatformSetCurrentContext(window); + _glfwPlatformSetTls(&_glfw.context, window); } static GLFWglproc getProcAddressOSMesa(const char* procname) diff --git a/src/posix_tls.c b/src/posix_tls.c index 1b913a0f..980ff23b 100644 --- a/src/posix_tls.c +++ b/src/posix_tls.c @@ -27,42 +27,46 @@ #include "internal.h" - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -GLFWbool _glfwInitThreadLocalStoragePOSIX(void) -{ - if (pthread_key_create(&_glfw.posix_tls.context, NULL) != 0) - { - _glfwInputError(GLFW_PLATFORM_ERROR, - "POSIX: Failed to create context TLS"); - return GLFW_FALSE; - } - - _glfw.posix_tls.allocated = GLFW_TRUE; - return GLFW_TRUE; -} - -void _glfwTerminateThreadLocalStoragePOSIX(void) -{ - if (_glfw.posix_tls.allocated) - pthread_key_delete(_glfw.posix_tls.context); -} +#include +#include ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformSetCurrentContext(_GLFWwindow* context) +GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls) { - pthread_setspecific(_glfw.posix_tls.context, context); + assert(tls->posix.allocated == GLFW_FALSE); + + if (pthread_key_create(&tls->posix.key, NULL) != 0) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "POSIX: Failed to create context TLS"); + return GLFW_FALSE; + } + + tls->posix.allocated = GLFW_TRUE; + return GLFW_TRUE; } -_GLFWwindow* _glfwPlatformGetCurrentContext(void) +void _glfwPlatformDestroyTls(_GLFWtls* tls) { - return pthread_getspecific(_glfw.posix_tls.context); + assert(tls->posix.allocated == GLFW_TRUE); + if (tls->posix.allocated) + pthread_key_delete(tls->posix.key); + memset(tls, 0, sizeof(_GLFWtls)); +} + +void* _glfwPlatformGetTls(_GLFWtls* tls) +{ + assert(tls->posix.allocated == GLFW_TRUE); + return pthread_getspecific(tls->posix.key); +} + +void _glfwPlatformSetTls(_GLFWtls* tls, void* value) +{ + assert(tls->posix.allocated == GLFW_TRUE); + pthread_setspecific(tls->posix.key, value); } diff --git a/src/posix_tls.h b/src/posix_tls.h index 8d033fba..5d0e7c36 100644 --- a/src/posix_tls.h +++ b/src/posix_tls.h @@ -30,20 +30,17 @@ #include -#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsPOSIX posix_tls +#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsPOSIX posix -// POSIX-specific global TLS data +// POSIX-specific thread local storage data // typedef struct _GLFWtlsPOSIX { GLFWbool allocated; - pthread_key_t context; + pthread_key_t key; } _GLFWtlsPOSIX; -GLFWbool _glfwInitThreadLocalStoragePOSIX(void); -void _glfwTerminateThreadLocalStoragePOSIX(void); - #endif // _glfw3_posix_tls_h_ diff --git a/src/wgl_context.c b/src/wgl_context.c index 0cbb68f5..c59997fc 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -233,12 +233,12 @@ static void makeContextCurrentWGL(_GLFWwindow* window) if (window) { if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle)) - _glfwPlatformSetCurrentContext(window); + _glfwPlatformSetTls(&_glfw.context, window); else { _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "WGL: Failed to make context current"); - _glfwPlatformSetCurrentContext(NULL); + _glfwPlatformSetTls(&_glfw.context, NULL); } } else @@ -249,7 +249,7 @@ static void makeContextCurrentWGL(_GLFWwindow* window) "WGL: Failed to clear current context"); } - _glfwPlatformSetCurrentContext(NULL); + _glfwPlatformSetTls(&_glfw.context, NULL); } } @@ -268,7 +268,7 @@ static void swapBuffersWGL(_GLFWwindow* window) static void swapIntervalWGL(int interval) { - _GLFWwindow* window = _glfwPlatformGetCurrentContext(); + _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.context); window->context.wgl.interval = interval; diff --git a/src/win32_init.c b/src/win32_init.c index 785d75d3..63685128 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -435,9 +435,6 @@ void _glfwInputErrorWin32(int error, const char* description) int _glfwPlatformInit(void) { - if (!_glfwInitThreadLocalStorageWin32()) - return GLFW_FALSE; - // To make SetForegroundWindow work as we want, we need to fiddle // with the FOREGROUNDLOCKTIMEOUT system setting (we do this as early // as possible in the hope of still being the foreground process) @@ -489,7 +486,6 @@ void _glfwPlatformTerminate(void) _glfwTerminateEGL(); _glfwTerminateJoysticksWin32(); - _glfwTerminateThreadLocalStorageWin32(); freeLibraries(); } diff --git a/src/win32_platform.h b/src/win32_platform.h index 8cf2b5a4..c77358e2 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -221,9 +221,9 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)( #define _GLFW_PLATFORM_WINDOW_STATE _GLFWwindowWin32 win32 #define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryWin32 win32 #define _GLFW_PLATFORM_LIBRARY_TIME_STATE _GLFWtimeWin32 win32_time -#define _GLFW_PLATFORM_LIBRARY_TLS_STATE _GLFWtlsWin32 win32_tls #define _GLFW_PLATFORM_MONITOR_STATE _GLFWmonitorWin32 win32 #define _GLFW_PLATFORM_CURSOR_STATE _GLFWcursorWin32 win32 +#define _GLFW_PLATFORM_TLS_STATE _GLFWtlsWin32 win32 // Win32-specific per-window data @@ -328,12 +328,12 @@ typedef struct _GLFWtimeWin32 } _GLFWtimeWin32; -// Win32-specific global TLS data +// Win32-specific thread local storage data // typedef struct _GLFWtlsWin32 { GLFWbool allocated; - DWORD context; + DWORD index; } _GLFWtlsWin32; @@ -341,9 +341,6 @@ typedef struct _GLFWtlsWin32 GLFWbool _glfwRegisterWindowClassWin32(void); void _glfwUnregisterWindowClassWin32(void); -GLFWbool _glfwInitThreadLocalStorageWin32(void); -void _glfwTerminateThreadLocalStorageWin32(void); - WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source); char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source); void _glfwInputErrorWin32(int error, const char* description); diff --git a/src/win32_tls.c b/src/win32_tls.c index 2bcb68a5..944f7e5e 100644 --- a/src/win32_tls.c +++ b/src/win32_tls.c @@ -27,43 +27,46 @@ #include "internal.h" - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -GLFWbool _glfwInitThreadLocalStorageWin32(void) -{ - _glfw.win32_tls.context = TlsAlloc(); - if (_glfw.win32_tls.context == TLS_OUT_OF_INDEXES) - { - _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, - "Win32: Failed to allocate TLS index"); - return GLFW_FALSE; - } - - _glfw.win32_tls.allocated = GLFW_TRUE; - return GLFW_TRUE; -} - -void _glfwTerminateThreadLocalStorageWin32(void) -{ - if (_glfw.win32_tls.allocated) - TlsFree(_glfw.win32_tls.context); -} +#include ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -void _glfwPlatformSetCurrentContext(_GLFWwindow* context) +GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls) { - TlsSetValue(_glfw.win32_tls.context, context); + assert(tls->win32.allocated == GLFW_FALSE); + + tls->win32.index = TlsAlloc(); + if (tls->win32.index == TLS_OUT_OF_INDEXES) + { + _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, + "Win32: Failed to allocate TLS index"); + return GLFW_FALSE; + } + + tls->win32.allocated = GLFW_TRUE; + return GLFW_TRUE; } -_GLFWwindow* _glfwPlatformGetCurrentContext(void) +void _glfwPlatformDestroyTls(_GLFWtls* tls) { - return TlsGetValue(_glfw.win32_tls.context); + assert(tls->win32.allocated == GLFW_TRUE); + if (tls->win32.allocated) + TlsFree(tls->win32.index); + memset(tls, 0, sizeof(_GLFWtls)); +} + +void* _glfwPlatformGetTls(_GLFWtls* tls) +{ + assert(tls->win32.allocated == GLFW_TRUE); + return TlsGetValue(tls->win32.index); +} + +void _glfwPlatformSetTls(_GLFWtls* tls, void* value) +{ + assert(tls->win32.allocated == GLFW_TRUE); + TlsSetValue(tls->win32.index, value); } diff --git a/src/window.c b/src/window.c index d16f75c5..bf98723e 100644 --- a/src/window.c +++ b/src/window.c @@ -192,7 +192,7 @@ GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, window->denom = GLFW_DONT_CARE; // Save the currently current context so it can be restored later - previous = _glfwPlatformGetCurrentContext(); + previous = _glfwPlatformGetTls(&_glfw.context); if (ctxconfig.client != GLFW_NO_API) glfwMakeContextCurrent(NULL); @@ -408,7 +408,7 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow* handle) // The window's context must not be current on another thread when the // window is destroyed - if (window == _glfwPlatformGetCurrentContext()) + if (window == _glfwPlatformGetTls(&_glfw.context)) glfwMakeContextCurrent(NULL); _glfwPlatformDestroyWindow(window); diff --git a/src/wl_init.c b/src/wl_init.c index ecc94f2a..8e12bafa 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -667,9 +667,6 @@ int _glfwPlatformInit(void) // Sync so we got all initial output events wl_display_roundtrip(_glfw.wl.display); - if (!_glfwInitThreadLocalStoragePOSIX()) - return GLFW_FALSE; - if (!_glfwInitJoysticksLinux()) return GLFW_FALSE; @@ -695,7 +692,6 @@ void _glfwPlatformTerminate(void) { _glfwTerminateEGL(); _glfwTerminateJoysticksLinux(); - _glfwTerminateThreadLocalStoragePOSIX(); xkb_compose_state_unref(_glfw.wl.xkb.composeState); xkb_keymap_unref(_glfw.wl.xkb.keymap); diff --git a/src/x11_init.c b/src/x11_init.c index 734c89cc..ca271546 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -822,9 +822,6 @@ int _glfwPlatformInit(void) } } - if (!_glfwInitThreadLocalStoragePOSIX()) - return GLFW_FALSE; - #if defined(__linux__) if (!_glfwInitJoysticksLinux()) return GLFW_FALSE; @@ -885,7 +882,6 @@ void _glfwPlatformTerminate(void) #if defined(__linux__) _glfwTerminateJoysticksLinux(); #endif - _glfwTerminateThreadLocalStoragePOSIX(); } const char* _glfwPlatformGetVersionString(void)