diff options
author | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-25 19:12:40 +0000 |
---|---|---|
committer | scroggo@google.com <scroggo@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-10-25 19:12:40 +0000 |
commit | 93897637bc65eab919be40ec4b1b2c3242179b24 (patch) | |
tree | a00e488f282d7eb61618cf5887122674f9987609 | |
parent | 396e61fe440590744345e0c56970b26ab464591d (diff) |
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
-rw-r--r-- | src/ports/SkThread_win.cpp | 41 | ||||
-rw-r--r-- | tests/TLSTest.cpp | 34 |
2 files changed, 68 insertions, 7 deletions
diff --git a/src/ports/SkThread_win.cpp b/src/ports/SkThread_win.cpp index 91a5ceb7ec..07a67ef689 100644 --- a/src/ports/SkThread_win.cpp +++ b/src/ports/SkThread_win.cpp @@ -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 +} diff --git a/tests/TLSTest.cpp b/tests/TLSTest.cpp index 5fa0903ca8..17f7dcba25 100644 --- a/tests/TLSTest.cpp +++ b/tests/TLSTest.cpp @@ -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) |