Add a callback to cleanup TLS data on Windows.

Add a test to ensure that it works.

BUG: http://code.google.com/p/skia/issues/detail?id=939

Review URL: https://codereview.appspot.com/6785045

git-svn-id: http://skia.googlecode.com/svn/trunk@6126 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
scroggo@google.com 2012-10-25 19:12:40 +00:00
parent 396e61fe44
commit 93897637bc
2 changed files with 68 additions and 7 deletions

View File

@ -93,3 +93,44 @@ void SkTLS::PlatformSetSpecific(void* ptr) {
(void)TlsSetValue(gTlsIndex, ptr);
}
// Call TLS destructors on thread exit. Code based on Chromium's
// base/threading/thread_local_storage_win.cc
#ifdef _WIN64
#pragma comment(linker, "/INCLUDE:_tls_used")
#pragma comment(linker, "/INCLUDE:skia_tls_callback")
#else
#pragma comment(linker, "/INCLUDE:__tls_used")
#pragma comment(linker, "/INCLUDE:_skia_tls_callback")
#endif
void NTAPI onTLSCallback(PVOID unused, DWORD reason, PVOID unused2) {
if ((DLL_THREAD_DETACH == reason || DLL_PROCESS_DETACH == reason) && gOnce) {
void* ptr = TlsGetValue(gTlsIndex);
if (ptr != NULL) {
SkTLS::Destructor(ptr);
TlsSetValue(gTlsIndex, NULL);
}
}
}
extern "C" {
#ifdef _WIN64
#pragma const_seg(".CRT$XLB")
extern const PIMAGE_TLS_CALLBACK skia_tls_callback;
PIMAGE_TLS_CALLBACK skia_tls_callback = onTLSCallback;
#pragma const_seg()
#else
#pragma data_seg(".CRT$XLB")
PIMAGE_TLS_CALLBACK skia_tls_callback = onTLSCallback;
#pragma data_seg()
#endif
}

View File

@ -30,13 +30,13 @@ static void thread_main(void*) {
}
}
static void test_measuretext(skiatest::Reporter* reporter) {
static void test_threads(SkThread::entryPointProc proc) {
SkThread* threads[8];
int N = SK_ARRAY_COUNT(threads);
int i;
for (i = 0; i < N; ++i) {
threads[i] = new SkThread(thread_main);
threads[i] = new SkThread(proc);
}
for (i = 0; i < N; ++i) {
@ -52,12 +52,32 @@ static void test_measuretext(skiatest::Reporter* reporter) {
}
}
static int32_t gCounter;
static void* FakeCreateTLS() {
sk_atomic_inc(&gCounter);
return NULL;
}
static void FakeDeleteTLS(void* unused) {
sk_atomic_dec(&gCounter);
}
static void testTLSDestructor(void* unused) {
SkTLS::Get(FakeCreateTLS, FakeDeleteTLS);
}
static void TestTLS(skiatest::Reporter* reporter) {
test_measuretext(reporter);
// TODO: Disabled for now to work around
// http://code.google.com/p/skia/issues/detail?id=619
// ('flaky segfault in TLS test on Shuttle_Ubuntu12 buildbots')
//test_threads(&thread_main);
// Test to ensure that at thread destruction, TLS destructors
// have been called.
test_threads(&testTLSDestructor);
REPORTER_ASSERT(reporter, 0 == gCounter);
}
#include "TestClassDef.h"
// TODO: Disabled for now to work around
// http://code.google.com/p/skia/issues/detail?id=619
// ('flaky segfault in TLS test on Shuttle_Ubuntu12 buildbots')
// DEFINE_TESTCLASS("TLS", TLSClass, TestTLS)
DEFINE_TESTCLASS("TLS", TLSClass, TestTLS)