1 // Copyright 2012 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/sequence_checker_impl.h" 6 7 #include <utility> 8 9 #include "base/check.h" 10 #include "base/compiler_specific.h" 11 #include "base/debug/stack_trace.h" 12 #include "base/memory/ptr_util.h" 13 #include "base/sequence_token.h" 14 #include "base/threading/thread_checker.h" 15 #include "base/threading/thread_checker_impl.h" 16 #include "base/threading/thread_local_storage.h" 17 18 namespace base { 19 20 // static EnableStackLogging()21void SequenceCheckerImpl::EnableStackLogging() { 22 ThreadChecker::EnableStackLogging(); 23 } 24 25 SequenceCheckerImpl::SequenceCheckerImpl() = default; 26 SequenceCheckerImpl::~SequenceCheckerImpl() = default; 27 28 SequenceCheckerImpl::SequenceCheckerImpl(SequenceCheckerImpl&& other) = default; 29 SequenceCheckerImpl& SequenceCheckerImpl::operator=( 30 SequenceCheckerImpl&& other) = default; 31 CalledOnValidSequence(std::unique_ptr<debug::StackTrace> * bound_at) const32bool SequenceCheckerImpl::CalledOnValidSequence( 33 std::unique_ptr<debug::StackTrace>* bound_at) const { 34 AutoLock auto_lock(thread_checker_.lock_); 35 // When `sequence_token_` or SequenceToken::GetForCurrentThread() are 36 // invalid fall back on ThreadChecker. We assume that SequenceChecker things 37 // are mostly run on a sequence and that that is the correct sequence (hence 38 // using LIKELY annotation). 39 if (LIKELY(thread_checker_.sequence_token_.IsValid())) { 40 if (LIKELY(thread_checker_.sequence_token_ == 41 SequenceToken::GetForCurrentThread())) { 42 return true; 43 } 44 45 // TODO(pbos): This preserves existing behavior that `sequence_token_` is 46 // ignored after TLS shutdown. It should either be documented here why 47 // that is necessary (shouldn't this destroy on sequence?) or 48 // SequenceCheckerTest.CalledOnValidSequenceFromThreadDestruction should 49 // be updated to reflect the expected behavior. 50 // 51 // crrev.com/682023 added this TLS-check to solve an edge case but that 52 // edge case was probably only a problem before TLS-destruction order was 53 // fixed in crrev.com/1119244. crrev.com/1117059 further improved 54 // TLS-destruction order of tokens by using `thread_local` and making it 55 // deterministic. 56 // See https://timsong-cpp.github.io/cppwp/n4140/basic.start.term: "If the 57 // completion of the constructor or dynamic initialization of an object 58 // with thread storage duration is sequenced before that of another, the 59 // completion of the destructor of the second is sequenced before the 60 // initiation of the destructor of the first." 61 if (!ThreadLocalStorage::HasBeenDestroyed()) { 62 if (bound_at) { 63 *bound_at = thread_checker_.GetBoundAt(); 64 } 65 return false; 66 } 67 } 68 69 // SequenceChecker behaves as a ThreadChecker when it is not bound to a 70 // valid sequence token. 71 return thread_checker_.CalledOnValidThreadInternal(bound_at); 72 } 73 DetachFromSequence()74void SequenceCheckerImpl::DetachFromSequence() { 75 thread_checker_.DetachFromThread(); 76 } 77 78 } // namespace base 79