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.
5 #include "base/sequence_checker_impl.h"
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"
21 void SequenceCheckerImpl::EnableStackLogging() {
22 ThreadChecker::EnableStackLogging();
25 SequenceCheckerImpl::SequenceCheckerImpl() = default;
26 SequenceCheckerImpl::~SequenceCheckerImpl() = default;
28 SequenceCheckerImpl::SequenceCheckerImpl(SequenceCheckerImpl&& other) = default;
29 SequenceCheckerImpl& SequenceCheckerImpl::operator=(
30 SequenceCheckerImpl&& other) = default;
32 bool 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())) {
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.
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
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()) {
63 *bound_at = thread_checker_.GetBoundAt();
69 // SequenceChecker behaves as a ThreadChecker when it is not bound to a
70 // valid sequence token.
71 return thread_checker_.CalledOnValidThreadInternal(bound_at);
74 void SequenceCheckerImpl::DetachFromSequence() {
75 thread_checker_.DetachFromThread();