Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: base/threading/thread_local_storage.cc

Issue 2667513003: Remove some LazyInstance use in base/ (Closed)
Patch Set: no message_window Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/threading/thread_local_storage.h" 5 #include "base/threading/thread_local_storage.h"
6 6
7 #include "base/atomicops.h" 7 #include "base/atomicops.h"
8 #include "base/lazy_instance.h"
9 #include "base/logging.h" 8 #include "base/logging.h"
10 #include "base/synchronization/lock.h" 9 #include "base/synchronization/lock.h"
11 #include "build/build_config.h" 10 #include "build/build_config.h"
12 11
13 using base::internal::PlatformThreadLocalStorage; 12 using base::internal::PlatformThreadLocalStorage;
14 13
15 // Chrome Thread Local Storage (TLS) 14 // Chrome Thread Local Storage (TLS)
16 // 15 //
17 // This TLS system allows Chrome to use a single OS level TLS slot process-wide, 16 // This TLS system allows Chrome to use a single OS level TLS slot process-wide,
18 // and allows us to control the slot limits instead of being at the mercy of the 17 // and allows us to control the slot limits instead of being at the mercy of the
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 TlsStatus status; 82 TlsStatus status;
84 base::ThreadLocalStorage::TLSDestructorFunc destructor; 83 base::ThreadLocalStorage::TLSDestructorFunc destructor;
85 uint32_t version; 84 uint32_t version;
86 }; 85 };
87 86
88 struct TlsVectorEntry { 87 struct TlsVectorEntry {
89 void* data; 88 void* data;
90 uint32_t version; 89 uint32_t version;
91 }; 90 };
92 91
93 // This LazyInstance isn't needed until after we've constructed the per-thread 92 // This lock isn't needed until after we've constructed the per-thread TLS
94 // TLS vector, so it's safe to use. 93 // vector, so it's safe to use.
95 base::LazyInstance<base::Lock>::Leaky g_tls_metadata_lock; 94 base::Lock* GetTLSMetadataLock() {
95 static auto lock = new base::Lock();
96 return lock;
97 }
96 TlsMetadata g_tls_metadata[kThreadLocalStorageSize]; 98 TlsMetadata g_tls_metadata[kThreadLocalStorageSize];
97 size_t g_last_assigned_slot = 0; 99 size_t g_last_assigned_slot = 0;
98 100
99 // The maximum number of times to try to clear slots by calling destructors. 101 // The maximum number of times to try to clear slots by calling destructors.
100 // Use pthread naming convention for clarity. 102 // Use pthread naming convention for clarity.
101 constexpr int kMaxDestructorIterations = kThreadLocalStorageSize; 103 constexpr int kMaxDestructorIterations = kThreadLocalStorageSize;
102 104
103 // This function is called to initialize our entire Chromium TLS system. 105 // This function is called to initialize our entire Chromium TLS system.
104 // It may be called very early, and we need to complete most all of the setup 106 // It may be called very early, and we need to complete most all of the setup
105 // (initialization) before calling *any* memory allocator functions, which may 107 // (initialization) before calling *any* memory allocator functions, which may
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 memcpy(stack_allocated_tls_data, tls_data, sizeof(stack_allocated_tls_data)); 177 memcpy(stack_allocated_tls_data, tls_data, sizeof(stack_allocated_tls_data));
176 // Ensure that any re-entrant calls change the temp version. 178 // Ensure that any re-entrant calls change the temp version.
177 PlatformThreadLocalStorage::TLSKey key = 179 PlatformThreadLocalStorage::TLSKey key =
178 base::subtle::NoBarrier_Load(&g_native_tls_key); 180 base::subtle::NoBarrier_Load(&g_native_tls_key);
179 PlatformThreadLocalStorage::SetTLSValue(key, stack_allocated_tls_data); 181 PlatformThreadLocalStorage::SetTLSValue(key, stack_allocated_tls_data);
180 delete[] tls_data; // Our last dependence on an allocator. 182 delete[] tls_data; // Our last dependence on an allocator.
181 183
182 // Snapshot the TLS Metadata so we don't have to lock on every access. 184 // Snapshot the TLS Metadata so we don't have to lock on every access.
183 TlsMetadata tls_metadata[kThreadLocalStorageSize]; 185 TlsMetadata tls_metadata[kThreadLocalStorageSize];
184 { 186 {
185 base::AutoLock auto_lock(g_tls_metadata_lock.Get()); 187 base::AutoLock auto_lock(*GetTLSMetadataLock());
186 memcpy(tls_metadata, g_tls_metadata, sizeof(g_tls_metadata)); 188 memcpy(tls_metadata, g_tls_metadata, sizeof(g_tls_metadata));
187 } 189 }
188 190
189 int remaining_attempts = kMaxDestructorIterations; 191 int remaining_attempts = kMaxDestructorIterations;
190 bool need_to_scan_destructors = true; 192 bool need_to_scan_destructors = true;
191 while (need_to_scan_destructors) { 193 while (need_to_scan_destructors) {
192 need_to_scan_destructors = false; 194 need_to_scan_destructors = false;
193 // Try to destroy the first-created-slot (which is slot 1) in our last 195 // Try to destroy the first-created-slot (which is slot 1) in our last
194 // destructor call. That user was able to function, and define a slot with 196 // destructor call. That user was able to function, and define a slot with
195 // no other services running, so perhaps it is a basic service (like an 197 // no other services running, so perhaps it is a basic service (like an
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 base::subtle::NoBarrier_Load(&g_native_tls_key); 256 base::subtle::NoBarrier_Load(&g_native_tls_key);
255 if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES || 257 if (key == PlatformThreadLocalStorage::TLS_KEY_OUT_OF_INDEXES ||
256 !PlatformThreadLocalStorage::GetTLSValue(key)) { 258 !PlatformThreadLocalStorage::GetTLSValue(key)) {
257 ConstructTlsVector(); 259 ConstructTlsVector();
258 } 260 }
259 261
260 // Grab a new slot. 262 // Grab a new slot.
261 slot_ = kInvalidSlotValue; 263 slot_ = kInvalidSlotValue;
262 version_ = 0; 264 version_ = 0;
263 { 265 {
264 base::AutoLock auto_lock(g_tls_metadata_lock.Get()); 266 base::AutoLock auto_lock(*GetTLSMetadataLock());
265 for (int i = 0; i < kThreadLocalStorageSize; ++i) { 267 for (int i = 0; i < kThreadLocalStorageSize; ++i) {
266 // Tracking the last assigned slot is an attempt to find the next 268 // Tracking the last assigned slot is an attempt to find the next
267 // available slot within one iteration. Under normal usage, slots remain 269 // available slot within one iteration. Under normal usage, slots remain
268 // in use for the lifetime of the process (otherwise before we reclaimed 270 // in use for the lifetime of the process (otherwise before we reclaimed
269 // slots, we would have run out of slots). This makes it highly likely the 271 // slots, we would have run out of slots). This makes it highly likely the
270 // next slot is going to be a free slot. 272 // next slot is going to be a free slot.
271 size_t slot_candidate = 273 size_t slot_candidate =
272 (g_last_assigned_slot + 1 + i) % kThreadLocalStorageSize; 274 (g_last_assigned_slot + 1 + i) % kThreadLocalStorageSize;
273 if (g_tls_metadata[slot_candidate].status == TlsStatus::FREE) { 275 if (g_tls_metadata[slot_candidate].status == TlsStatus::FREE) {
274 g_tls_metadata[slot_candidate].status = TlsStatus::IN_USE; 276 g_tls_metadata[slot_candidate].status = TlsStatus::IN_USE;
275 g_tls_metadata[slot_candidate].destructor = destructor; 277 g_tls_metadata[slot_candidate].destructor = destructor;
276 g_last_assigned_slot = slot_candidate; 278 g_last_assigned_slot = slot_candidate;
277 slot_ = slot_candidate; 279 slot_ = slot_candidate;
278 version_ = g_tls_metadata[slot_candidate].version; 280 version_ = g_tls_metadata[slot_candidate].version;
279 break; 281 break;
280 } 282 }
281 } 283 }
282 } 284 }
283 CHECK_NE(slot_, kInvalidSlotValue); 285 CHECK_NE(slot_, kInvalidSlotValue);
284 CHECK_LT(slot_, kThreadLocalStorageSize); 286 CHECK_LT(slot_, kThreadLocalStorageSize);
285 287
286 // Setup our destructor. 288 // Setup our destructor.
287 base::subtle::Release_Store(&initialized_, 1); 289 base::subtle::Release_Store(&initialized_, 1);
288 } 290 }
289 291
290 void ThreadLocalStorage::StaticSlot::Free() { 292 void ThreadLocalStorage::StaticSlot::Free() {
291 DCHECK_NE(slot_, kInvalidSlotValue); 293 DCHECK_NE(slot_, kInvalidSlotValue);
292 DCHECK_LT(slot_, kThreadLocalStorageSize); 294 DCHECK_LT(slot_, kThreadLocalStorageSize);
293 { 295 {
294 base::AutoLock auto_lock(g_tls_metadata_lock.Get()); 296 base::AutoLock auto_lock(*GetTLSMetadataLock());
295 g_tls_metadata[slot_].status = TlsStatus::FREE; 297 g_tls_metadata[slot_].status = TlsStatus::FREE;
296 g_tls_metadata[slot_].destructor = nullptr; 298 g_tls_metadata[slot_].destructor = nullptr;
297 ++(g_tls_metadata[slot_].version); 299 ++(g_tls_metadata[slot_].version);
298 } 300 }
299 slot_ = kInvalidSlotValue; 301 slot_ = kInvalidSlotValue;
300 base::subtle::Release_Store(&initialized_, 0); 302 base::subtle::Release_Store(&initialized_, 0);
301 } 303 }
302 304
303 void* ThreadLocalStorage::StaticSlot::Get() const { 305 void* ThreadLocalStorage::StaticSlot::Get() const {
304 TlsVectorEntry* tls_data = static_cast<TlsVectorEntry*>( 306 TlsVectorEntry* tls_data = static_cast<TlsVectorEntry*>(
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 338
337 void* ThreadLocalStorage::Slot::Get() const { 339 void* ThreadLocalStorage::Slot::Get() const {
338 return tls_slot_.Get(); 340 return tls_slot_.Get();
339 } 341 }
340 342
341 void ThreadLocalStorage::Slot::Set(void* value) { 343 void ThreadLocalStorage::Slot::Set(void* value) {
342 tls_slot_.Set(value); 344 tls_slot_.Set(value);
343 } 345 }
344 346
345 } // namespace base 347 } // namespace base
OLDNEW
« no previous file with comments | « base/path_service.cc ('k') | base/threading/watchdog.cc » ('j') | base/trace_event/trace_log.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698