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:
parent
396e61fe44
commit
93897637bc
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user