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 #endif
22
23 namespace base {
24
25 namespace {
26
27 #if DCHECK_IS_ON()
28 // Used to verify that the trace events used in the constructor do not result in
29 // instantiating a ScopedBlockingCall themselves (which would cause an infinite
30 // reentrancy loop).
31 constinit thread_local bool construction_in_progress = false;
32 #endif
33
34 } // namespace
35
ScopedBlockingCall(const Location & from_here,BlockingType blocking_type)36 ScopedBlockingCall::ScopedBlockingCall(const Location& from_here,
37 BlockingType blocking_type)
38 : UncheckedScopedBlockingCall(
39 blocking_type,
40 UncheckedScopedBlockingCall::BlockingCallType::kRegular) {
41 #if DCHECK_IS_ON()
42 const AutoReset<bool> resetter(&construction_in_progress, true, false);
43 #endif
44
45 AssertBlockingAllowed();
46 TRACE_EVENT_BEGIN(
47 "base", "ScopedBlockingCall", [&](perfetto::EventContext ctx) {
48 ctx.event()->set_source_location_iid(
49 base::trace_event::InternedSourceLocation::Get(&ctx, from_here));
50 });
51 }
52
~ScopedBlockingCall()53 ScopedBlockingCall::~ScopedBlockingCall() {
54 TRACE_EVENT_END("base");
55 }
56
57 namespace internal {
58
59 ScopedBlockingCallWithBaseSyncPrimitives::
ScopedBlockingCallWithBaseSyncPrimitives(const Location & from_here,BlockingType blocking_type)60 ScopedBlockingCallWithBaseSyncPrimitives(const Location& from_here,
61 BlockingType blocking_type)
62 : UncheckedScopedBlockingCall(
63 blocking_type,
64 UncheckedScopedBlockingCall::BlockingCallType::kBaseSyncPrimitives) {
65 #if DCHECK_IS_ON()
66 const AutoReset<bool> resetter(&construction_in_progress, true, false);
67 #endif
68
69 internal::AssertBaseSyncPrimitivesAllowed();
70 TRACE_EVENT_BEGIN(
71 "base", "ScopedBlockingCallWithBaseSyncPrimitives",
72 [&](perfetto::EventContext ctx) {
73 perfetto::protos::pbzero::SourceLocation* source_location_data =
74 ctx.event()->set_source_location();
75 source_location_data->set_file_name(from_here.file_name());
76 source_location_data->set_function_name(from_here.function_name());
77 });
78 }
79
80 ScopedBlockingCallWithBaseSyncPrimitives::
~ScopedBlockingCallWithBaseSyncPrimitives()81 ~ScopedBlockingCallWithBaseSyncPrimitives() {
82 TRACE_EVENT_END("base");
83 }
84
85 } // namespace internal
86
87 } // namespace base
88