Commit a4e68d43 by Jamie Madill

Fix initialization of thread local storage in libEGL.

When an app would load libEGL.dll via LoadModule, then would call methods on a thread that was already created, we could creash because of uninitialized thread local storage. BUG=angle:488 Change-Id: If3f73fb59dcc5f0713f5b6fb9ca9f8535ee23c73 Reviewed-on: https://chromium-review.googlesource.com/179131Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent a738f085
...@@ -12,6 +12,43 @@ ...@@ -12,6 +12,43 @@
static DWORD currentTLS = TLS_OUT_OF_INDEXES; static DWORD currentTLS = TLS_OUT_OF_INDEXES;
namespace egl
{
Current *AllocateCurrent()
{
Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current));
if (!current)
{
ERR("Could not allocate thread local storage.");
return NULL;
}
ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
TlsSetValue(currentTLS, current);
current->error = EGL_SUCCESS;
current->API = EGL_OPENGL_ES_API;
current->display = EGL_NO_DISPLAY;
current->drawSurface = EGL_NO_SURFACE;
current->readSurface = EGL_NO_SURFACE;
return current;
}
void DeallocateCurrent()
{
void *current = TlsGetValue(currentTLS);
if (current)
{
LocalFree((HLOCAL)current);
}
}
}
extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved) extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{ {
switch (reason) switch (reason)
...@@ -43,39 +80,17 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved ...@@ -43,39 +80,17 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
// Fall throught to initialize index // Fall throught to initialize index
case DLL_THREAD_ATTACH: case DLL_THREAD_ATTACH:
{ {
egl::Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); egl::AllocateCurrent();
if (current)
{
TlsSetValue(currentTLS, current);
current->error = EGL_SUCCESS;
current->API = EGL_OPENGL_ES_API;
current->display = EGL_NO_DISPLAY;
current->drawSurface = EGL_NO_SURFACE;
current->readSurface = EGL_NO_SURFACE;
}
} }
break; break;
case DLL_THREAD_DETACH: case DLL_THREAD_DETACH:
{ {
void *current = TlsGetValue(currentTLS); egl::DeallocateCurrent();
if (current)
{
LocalFree((HLOCAL)current);
}
} }
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
{ {
void *current = TlsGetValue(currentTLS); egl::DeallocateCurrent();
if (current)
{
LocalFree((HLOCAL)current);
}
TlsFree(currentTLS); TlsFree(currentTLS);
} }
break; break;
...@@ -88,72 +103,82 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved ...@@ -88,72 +103,82 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
namespace egl namespace egl
{ {
void setCurrentError(EGLint error)
Current *GetCurrentData()
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = (Current*)TlsGetValue(currentTLS);
// ANGLE issue 488: when the dll is loaded after thread initialization,
// thread local storage (current) might not exist yet.
return (current ? current : AllocateCurrent());
}
void setCurrentError(EGLint error)
{
Current *current = GetCurrentData();
current->error = error; current->error = error;
} }
EGLint getCurrentError() EGLint getCurrentError()
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = GetCurrentData();
return current->error; return current->error;
} }
void setCurrentAPI(EGLenum API) void setCurrentAPI(EGLenum API)
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = GetCurrentData();
current->API = API; current->API = API;
} }
EGLenum getCurrentAPI() EGLenum getCurrentAPI()
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = GetCurrentData();
return current->API; return current->API;
} }
void setCurrentDisplay(EGLDisplay dpy) void setCurrentDisplay(EGLDisplay dpy)
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = GetCurrentData();
current->display = dpy; current->display = dpy;
} }
EGLDisplay getCurrentDisplay() EGLDisplay getCurrentDisplay()
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = GetCurrentData();
return current->display; return current->display;
} }
void setCurrentDrawSurface(EGLSurface surface) void setCurrentDrawSurface(EGLSurface surface)
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = GetCurrentData();
current->drawSurface = surface; current->drawSurface = surface;
} }
EGLSurface getCurrentDrawSurface() EGLSurface getCurrentDrawSurface()
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = GetCurrentData();
return current->drawSurface; return current->drawSurface;
} }
void setCurrentReadSurface(EGLSurface surface) void setCurrentReadSurface(EGLSurface surface)
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = GetCurrentData();
current->readSurface = surface; current->readSurface = surface;
} }
EGLSurface getCurrentReadSurface() EGLSurface getCurrentReadSurface()
{ {
Current *current = (Current*)TlsGetValue(currentTLS); Current *current = GetCurrentData();
return current->readSurface; return current->readSurface;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment