OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple Inc. All rights reserved. |
3 * Copyright (C) 2009 Jian Li <jianli@chromium.org> | 3 * Copyright (C) 2009 Jian Li <jianli@chromium.org> |
4 * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com> | 4 * Copyright (C) 2012 Patrick Gansterer <paroga@paroga.com> |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * | 9 * |
10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
(...skipping 24 matching lines...) Expand all Loading... |
35 * repeatedly if there is still non-NULL value associated with the function. | 35 * repeatedly if there is still non-NULL value associated with the function. |
36 * @ In Windows native implementation, the destructor function will be called | 36 * @ In Windows native implementation, the destructor function will be called |
37 * only once. | 37 * only once. |
38 * This semantic discrepancy does not impose any problem because nowhere in | 38 * This semantic discrepancy does not impose any problem because nowhere in |
39 * WebKit the repeated call bahavior is utilized. | 39 * WebKit the repeated call bahavior is utilized. |
40 */ | 40 */ |
41 | 41 |
42 #ifndef WTF_ThreadSpecific_h | 42 #ifndef WTF_ThreadSpecific_h |
43 #define WTF_ThreadSpecific_h | 43 #define WTF_ThreadSpecific_h |
44 | 44 |
| 45 #include "wtf/AddressSanitizer.h" |
45 #include "wtf/Allocator.h" | 46 #include "wtf/Allocator.h" |
46 #include "wtf/Noncopyable.h" | 47 #include "wtf/Noncopyable.h" |
47 #include "wtf/StdLibExtras.h" | 48 #include "wtf/StdLibExtras.h" |
48 #include "wtf/WTF.h" | 49 #include "wtf/WTF.h" |
49 #include "wtf/WTFExport.h" | 50 #include "wtf/WTFExport.h" |
50 #include "wtf/allocator/Partitions.h" | 51 #include "wtf/allocator/Partitions.h" |
51 | 52 |
52 #if OS(POSIX) | 53 #if OS(POSIX) |
53 #include <pthread.h> | 54 #include <pthread.h> |
54 #elif OS(WIN) | 55 #elif OS(WIN) |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 { | 149 { |
149 Data* data = static_cast<Data*>(pthread_getspecific(m_key)); | 150 Data* data = static_cast<Data*>(pthread_getspecific(m_key)); |
150 return data ? data->value : 0; | 151 return data ? data->value : 0; |
151 } | 152 } |
152 | 153 |
153 template<typename T> | 154 template<typename T> |
154 inline void ThreadSpecific<T>::set(T* ptr) | 155 inline void ThreadSpecific<T>::set(T* ptr) |
155 { | 156 { |
156 ASSERT(!get()); | 157 ASSERT(!get()); |
157 pthread_setspecific(m_key, new Data(ptr, this)); | 158 pthread_setspecific(m_key, new Data(ptr, this)); |
| 159 __lsan_register_root_region(ptr, sizeof(Data)); |
158 } | 160 } |
159 | 161 |
160 #elif OS(WIN) | 162 #elif OS(WIN) |
161 | 163 |
162 // TLS_OUT_OF_INDEXES is not defined on WinCE. | 164 // TLS_OUT_OF_INDEXES is not defined on WinCE. |
163 #ifndef TLS_OUT_OF_INDEXES | 165 #ifndef TLS_OUT_OF_INDEXES |
164 #define TLS_OUT_OF_INDEXES 0xffffffff | 166 #define TLS_OUT_OF_INDEXES 0xffffffff |
165 #endif | 167 #endif |
166 | 168 |
167 // The maximum number of TLS keys that can be created. For simplification, we as
sume that: | 169 // The maximum number of TLS keys that can be created. For simplification, we as
sume that: |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 { | 208 { |
207 Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index])); | 209 Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index])); |
208 return data ? data->value : 0; | 210 return data ? data->value : 0; |
209 } | 211 } |
210 | 212 |
211 template<typename T> | 213 template<typename T> |
212 inline void ThreadSpecific<T>::set(T* ptr) | 214 inline void ThreadSpecific<T>::set(T* ptr) |
213 { | 215 { |
214 ASSERT(!get()); | 216 ASSERT(!get()); |
215 Data* data = new Data(ptr, this); | 217 Data* data = new Data(ptr, this); |
| 218 __lsan_register_root_region(ptr, sizeof(Data)); |
216 data->destructor = &ThreadSpecific<T>::destroy; | 219 data->destructor = &ThreadSpecific<T>::destroy; |
217 TlsSetValue(tlsKeys()[m_index], data); | 220 TlsSetValue(tlsKeys()[m_index], data); |
218 } | 221 } |
219 | 222 |
220 #else | 223 #else |
221 #error ThreadSpecific is not implemented for this platform. | 224 #error ThreadSpecific is not implemented for this platform. |
222 #endif | 225 #endif |
223 | 226 |
224 template<typename T> | 227 template<typename T> |
225 inline void ThreadSpecific<T>::destroy(void* ptr) | 228 inline void ThreadSpecific<T>::destroy(void* ptr) |
226 { | 229 { |
227 if (isShutdown()) | 230 // Never call destructors on the main thread. |
| 231 // This is fine because Blink no longer has a graceful shutdown sequence. |
| 232 if (isMainThread()) |
228 return; | 233 return; |
229 | 234 |
230 Data* data = static_cast<Data*>(ptr); | 235 Data* data = static_cast<Data*>(ptr); |
231 | 236 |
232 #if OS(POSIX) | 237 #if OS(POSIX) |
233 // We want get() to keep working while data destructor works, because it can
be called indirectly by the destructor. | 238 // We want get() to keep working while data destructor works, because it can
be called indirectly by the destructor. |
234 // Some pthreads implementations zero out the pointer before calling destroy
(), so we temporarily reset it. | 239 // Some pthreads implementations zero out the pointer before calling destroy
(), so we temporarily reset it. |
235 pthread_setspecific(data->owner->m_key, ptr); | 240 pthread_setspecific(data->owner->m_key, ptr); |
236 #endif | 241 #endif |
237 | 242 |
(...skipping 20 matching lines...) Expand all Loading... |
258 template<typename T> | 263 template<typename T> |
259 inline ThreadSpecific<T>::operator T*() | 264 inline ThreadSpecific<T>::operator T*() |
260 { | 265 { |
261 T* ptr = static_cast<T*>(get()); | 266 T* ptr = static_cast<T*>(get()); |
262 if (!ptr) { | 267 if (!ptr) { |
263 // Set up thread-specific value's memory pointer before invoking constru
ctor, in case any function it calls | 268 // Set up thread-specific value's memory pointer before invoking constru
ctor, in case any function it calls |
264 // needs to access the value, to avoid recursion. | 269 // needs to access the value, to avoid recursion. |
265 ptr = static_cast<T*>(Partitions::fastZeroedMalloc(sizeof(T), WTF_HEAP_P
ROFILER_TYPE_NAME(T))); | 270 ptr = static_cast<T*>(Partitions::fastZeroedMalloc(sizeof(T), WTF_HEAP_P
ROFILER_TYPE_NAME(T))); |
266 set(ptr); | 271 set(ptr); |
267 new (NotNull, ptr) T; | 272 new (NotNull, ptr) T; |
| 273 __lsan_register_root_region(ptr, sizeof(T)); |
268 } | 274 } |
269 return ptr; | 275 return ptr; |
270 } | 276 } |
271 | 277 |
272 template<typename T> | 278 template<typename T> |
273 inline T* ThreadSpecific<T>::operator->() | 279 inline T* ThreadSpecific<T>::operator->() |
274 { | 280 { |
275 return operator T*(); | 281 return operator T*(); |
276 } | 282 } |
277 | 283 |
278 template<typename T> | 284 template<typename T> |
279 inline T& ThreadSpecific<T>::operator*() | 285 inline T& ThreadSpecific<T>::operator*() |
280 { | 286 { |
281 return *operator T*(); | 287 return *operator T*(); |
282 } | 288 } |
283 | 289 |
284 } // namespace WTF | 290 } // namespace WTF |
285 | 291 |
286 using WTF::ThreadSpecific; | 292 using WTF::ThreadSpecific; |
287 | 293 |
288 #endif // WTF_ThreadSpecific_h | 294 #endif // WTF_ThreadSpecific_h |
OLD | NEW |