Add internal TLS support

Related to #970.
This commit is contained in:
Camilla Löwy 2017-03-08 13:58:09 +01:00
parent 62414bff6e
commit aaf2800c9c
19 changed files with 109 additions and 116 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -63,7 +63,7 @@ static void makeContextCurrentOSMesa(_GLFWwindow* window)
}
}
_glfwPlatformSetCurrentContext(window);
_glfwPlatformSetTls(&_glfw.context, window);
}
static GLFWglproc getProcAddressOSMesa(const char* procname)

View File

@ -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 <assert.h>
#include <string.h>
//////////////////////////////////////////////////////////////////////////
////// 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);
}

View File

@ -30,20 +30,17 @@
#include <pthread.h>
#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_

View File

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

View File

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

View File

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

View File

@ -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 <assert.h>
//////////////////////////////////////////////////////////////////////////
////// 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);
}

View File

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

View File

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

View File

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