1 // Copyright 2017 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/threading/scoped_blocking_call.h"
6
7 #include "base/lazy_instance.h"
8 #include "base/threading/thread_local.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "base/time/time.h"
11 #include "base/trace_event/base_tracing.h"
12 #include "base/tracing_buildflags.h"
13 #include "build/build_config.h"
14
15 #if BUILDFLAG(ENABLE_BASE_TRACING)
16 #include "third_party/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h" // nogncheck
17 #endif // BUILDFLAG(ENABLE_BASE_TRACING)
18
19 #if DCHECK_IS_ON()
20 #include "base/auto_reset.h"
21 #include "third_party/abseil-cpp/absl/base/attributes.h"
22 #endif
23
24 namespace base {
25
26 namespace {
27
28 #if DCHECK_IS_ON()
29 // Used to verify that the trace events used in the constructor do not result in
30 // instantiating a ScopedBlockingCall themselves (which would cause an infinite
31 // reentrancy loop).
32 ABSL_CONST_INIT thread_local bool construction_in_progress = false;
33 #endif
34
35 } // namespace
36
ScopedBlockingCall(const Location & from_here,BlockingType blocking_type)37 ScopedBlockingCall::ScopedBlockingCall(const Location& from_here,
38 BlockingType blocking_type)
39 : UncheckedScopedBlockingCall(
40 blocking_type,
41 UncheckedScopedBlockingCall::BlockingCallType::kRegular) {
42 #if DCHECK_IS_ON()
43 const AutoReset<bool> resetter(&construction_in_progress, true, false);
44 #endif
45
46 internal::AssertBlockingAllowed();
47 TRACE_EVENT_BEGIN(
48 "base", "ScopedBlockingCall", [&](perfetto::EventContext ctx) {
49 ctx.event()->set_source_location_iid(
50 base::trace_event::InternedSourceLocation::Get(&ctx, from_here));
51 });
52 }
53
~ScopedBlockingCall()54 ScopedBlockingCall::~ScopedBlockingCall() {
55 TRACE_EVENT_END("base");
56 }
57
58 namespace internal {
59
60 ScopedBlockingCallWithBaseSyncPrimitives::
ScopedBlockingCallWithBaseSyncPrimitives(const Location & from_here,BlockingType blocking_type)61 ScopedBlockingCallWithBaseSyncPrimitives(const Location& from_here,
62 BlockingType blocking_type)
63 : UncheckedScopedBlockingCall(
64 blocking_type,
65 UncheckedScopedBlockingCall::BlockingCallType::kBaseSyncPrimitives) {
66 #if DCHECK_IS_ON()
67 const AutoReset<bool> resetter(&construction_in_progress, true, false);
68 #endif
69
70 internal::AssertBaseSyncPrimitivesAllowed();
71 TRACE_EVENT_BEGIN(
72 "base", "ScopedBlockingCallWithBaseSyncPrimitives",
73 [&](perfetto::EventContext ctx) {
74 perfetto::protos::pbzero::SourceLocation* source_location_data =
75 ctx.event()->set_source_location();
76 source_location_data->set_file_name(from_here.file_name());
77 source_location_data->set_function_name(from_here.function_name());
78 });
79 }
80
81 ScopedBlockingCallWithBaseSyncPrimitives::
~ScopedBlockingCallWithBaseSyncPrimitives()82 ~ScopedBlockingCallWithBaseSyncPrimitives() {
83 TRACE_EVENT_END("base");
84 }
85
86 } // namespace internal
87
88 } // namespace base
89