1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
10 #include "base/threading/simple_thread.h"
11 #include "base/threading/thread_local_storage.h"
12 #include "testing/gtest/include/gtest/gtest.h"
15 // Ignore warnings about ptr->int conversions that we use when
16 // storing ints into ThreadLocalStorage.
17 #pragma warning(disable : 4311 4312)
24 const int kInitialTlsValue
= 0x5555;
25 const int kFinalTlsValue
= 0x7777;
26 // How many times must a destructor be called before we really are done.
27 const int kNumberDestructorCallRepetitions
= 3;
29 static ThreadLocalStorage::StaticSlot tls_slot
= TLS_INITIALIZER
;
31 class ThreadLocalStorageRunner
: public DelegateSimpleThread::Delegate
{
33 explicit ThreadLocalStorageRunner(int* tls_value_ptr
)
34 : tls_value_ptr_(tls_value_ptr
) {}
36 virtual ~ThreadLocalStorageRunner() {}
38 virtual void Run() OVERRIDE
{
39 *tls_value_ptr_
= kInitialTlsValue
;
40 tls_slot
.Set(tls_value_ptr_
);
42 int *ptr
= static_cast<int*>(tls_slot
.Get());
43 EXPECT_EQ(ptr
, tls_value_ptr_
);
44 EXPECT_EQ(*ptr
, kInitialTlsValue
);
47 ptr
= static_cast<int*>(tls_slot
.Get());
48 EXPECT_EQ(ptr
, tls_value_ptr_
);
51 *ptr
= kFinalTlsValue
+ kNumberDestructorCallRepetitions
;
56 DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorageRunner
);
60 void ThreadLocalStorageCleanup(void *value
) {
61 int *ptr
= reinterpret_cast<int*>(value
);
62 // Destructors should never be called with a NULL.
63 ASSERT_NE(reinterpret_cast<int*>(NULL
), ptr
);
64 if (*ptr
== kFinalTlsValue
)
65 return; // We've been called enough times.
66 ASSERT_LT(kFinalTlsValue
, *ptr
);
67 ASSERT_GE(kFinalTlsValue
+ kNumberDestructorCallRepetitions
, *ptr
);
68 --*ptr
; // Move closer to our target.
69 // Tell tls that we're not done with this thread, and still need destruction.
75 TEST(ThreadLocalStorageTest
, Basics
) {
76 ThreadLocalStorage::Slot slot
;
77 slot
.Set(reinterpret_cast<void*>(123));
78 int value
= reinterpret_cast<intptr_t>(slot
.Get());
79 EXPECT_EQ(value
, 123);
82 #if defined(THREAD_SANITIZER)
83 // Do not run the test under ThreadSanitizer. Because this test iterates its
84 // own TSD destructor for the maximum possible number of times, TSan can't jump
85 // in after the last destructor invocation, therefore the destructor remains
86 // unsynchronized with the following users of the same TSD slot. This results
87 // in race reports between the destructor and functions in other tests.
88 #define MAYBE_TLSDestructors DISABLED_TLSDestructors
90 #define MAYBE_TLSDestructors TLSDestructors
92 TEST(ThreadLocalStorageTest
, MAYBE_TLSDestructors
) {
93 // Create a TLS index with a destructor. Create a set of
94 // threads that set the TLS, while the destructor cleans it up.
95 // After the threads finish, verify that the value is cleaned up.
96 const int kNumThreads
= 5;
97 int values
[kNumThreads
];
98 ThreadLocalStorageRunner
* thread_delegates
[kNumThreads
];
99 DelegateSimpleThread
* threads
[kNumThreads
];
101 tls_slot
.Initialize(ThreadLocalStorageCleanup
);
103 // Spawn the threads.
104 for (int index
= 0; index
< kNumThreads
; index
++) {
105 values
[index
] = kInitialTlsValue
;
106 thread_delegates
[index
] = new ThreadLocalStorageRunner(&values
[index
]);
107 threads
[index
] = new DelegateSimpleThread(thread_delegates
[index
],
109 threads
[index
]->Start();
112 // Wait for the threads to finish.
113 for (int index
= 0; index
< kNumThreads
; index
++) {
114 threads
[index
]->Join();
115 delete threads
[index
];
116 delete thread_delegates
[index
];
118 // Verify that the destructor was called and that we reset.
119 EXPECT_EQ(values
[index
], kFinalTlsValue
);
121 tls_slot
.Free(); // Stop doing callbacks to cleanup threads.