1*6777b538SAndroid Build Coastguard Worker // Copyright 2017 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_THREADING_SCOPED_BLOCKING_CALL_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_THREADING_SCOPED_BLOCKING_CALL_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 9*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_forward.h" 10*6777b538SAndroid Build Coastguard Worker #include "base/location.h" 11*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_piece.h" 12*6777b538SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call_internal.h" 13*6777b538SAndroid Build Coastguard Worker #include "base/types/strong_alias.h" 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Worker namespace base { 16*6777b538SAndroid Build Coastguard Worker 17*6777b538SAndroid Build Coastguard Worker // A "blocking call" refers to any call that causes the calling thread to wait 18*6777b538SAndroid Build Coastguard Worker // off-CPU. It includes but is not limited to calls that wait on synchronous 19*6777b538SAndroid Build Coastguard Worker // file I/O operations: read or write a file from disk, interact with a pipe or 20*6777b538SAndroid Build Coastguard Worker // a socket, rename or delete a file, enumerate files in a directory, etc. 21*6777b538SAndroid Build Coastguard Worker // Acquiring a low contention lock is not considered a blocking call. 22*6777b538SAndroid Build Coastguard Worker 23*6777b538SAndroid Build Coastguard Worker // BlockingType indicates the likelihood that a blocking call will actually 24*6777b538SAndroid Build Coastguard Worker // block. 25*6777b538SAndroid Build Coastguard Worker enum class BlockingType { 26*6777b538SAndroid Build Coastguard Worker // The call might block (e.g. file I/O that might hit in memory cache). 27*6777b538SAndroid Build Coastguard Worker MAY_BLOCK, 28*6777b538SAndroid Build Coastguard Worker // The call will definitely block (e.g. cache already checked and now pinging 29*6777b538SAndroid Build Coastguard Worker // server synchronously). 30*6777b538SAndroid Build Coastguard Worker WILL_BLOCK 31*6777b538SAndroid Build Coastguard Worker }; 32*6777b538SAndroid Build Coastguard Worker 33*6777b538SAndroid Build Coastguard Worker // This class must be instantiated in every scope where a blocking call is made 34*6777b538SAndroid Build Coastguard Worker // and serves as a precise annotation of the scope that may/will block for the 35*6777b538SAndroid Build Coastguard Worker // scheduler. When a ScopedBlockingCall is instantiated, it asserts that 36*6777b538SAndroid Build Coastguard Worker // blocking calls are allowed in its scope with a call to 37*6777b538SAndroid Build Coastguard Worker // base::AssertBlockingAllowed(). CPU usage should be minimal within that scope. 38*6777b538SAndroid Build Coastguard Worker // //base APIs that block instantiate their own ScopedBlockingCall; it is not 39*6777b538SAndroid Build Coastguard Worker // necessary to instantiate another ScopedBlockingCall in the scope where these 40*6777b538SAndroid Build Coastguard Worker // APIs are used. Nested ScopedBlockingCalls are supported (mostly a no-op 41*6777b538SAndroid Build Coastguard Worker // except for WILL_BLOCK nested within MAY_BLOCK which will result in immediate 42*6777b538SAndroid Build Coastguard Worker // WILL_BLOCK semantics). 43*6777b538SAndroid Build Coastguard Worker // 44*6777b538SAndroid Build Coastguard Worker // Good: 45*6777b538SAndroid Build Coastguard Worker // Data data; 46*6777b538SAndroid Build Coastguard Worker // { 47*6777b538SAndroid Build Coastguard Worker // ScopedBlockingCall scoped_blocking_call( 48*6777b538SAndroid Build Coastguard Worker // FROM_HERE, BlockingType::WILL_BLOCK); 49*6777b538SAndroid Build Coastguard Worker // data = GetDataFromNetwork(); 50*6777b538SAndroid Build Coastguard Worker // } 51*6777b538SAndroid Build Coastguard Worker // CPUIntensiveProcessing(data); 52*6777b538SAndroid Build Coastguard Worker // 53*6777b538SAndroid Build Coastguard Worker // Bad: 54*6777b538SAndroid Build Coastguard Worker // ScopedBlockingCall scoped_blocking_call(FROM_HERE, 55*6777b538SAndroid Build Coastguard Worker // BlockingType::WILL_BLOCK); 56*6777b538SAndroid Build Coastguard Worker // Data data = GetDataFromNetwork(); 57*6777b538SAndroid Build Coastguard Worker // CPUIntensiveProcessing(data); // CPU usage within a ScopedBlockingCall. 58*6777b538SAndroid Build Coastguard Worker // 59*6777b538SAndroid Build Coastguard Worker // Good: 60*6777b538SAndroid Build Coastguard Worker // Data a; 61*6777b538SAndroid Build Coastguard Worker // Data b; 62*6777b538SAndroid Build Coastguard Worker // { 63*6777b538SAndroid Build Coastguard Worker // ScopedBlockingCall scoped_blocking_call( 64*6777b538SAndroid Build Coastguard Worker // FROM_HERE, BlockingType::MAY_BLOCK); 65*6777b538SAndroid Build Coastguard Worker // a = GetDataFromMemoryCacheOrNetwork(); 66*6777b538SAndroid Build Coastguard Worker // b = GetDataFromMemoryCacheOrNetwork(); 67*6777b538SAndroid Build Coastguard Worker // } 68*6777b538SAndroid Build Coastguard Worker // CPUIntensiveProcessing(a); 69*6777b538SAndroid Build Coastguard Worker // CPUIntensiveProcessing(b); 70*6777b538SAndroid Build Coastguard Worker // 71*6777b538SAndroid Build Coastguard Worker // Bad: 72*6777b538SAndroid Build Coastguard Worker // ScopedBlockingCall scoped_blocking_call( 73*6777b538SAndroid Build Coastguard Worker // FROM_HERE, BlockingType::MAY_BLOCK); 74*6777b538SAndroid Build Coastguard Worker // Data a = GetDataFromMemoryCacheOrNetwork(); 75*6777b538SAndroid Build Coastguard Worker // Data b = GetDataFromMemoryCacheOrNetwork(); 76*6777b538SAndroid Build Coastguard Worker // CPUIntensiveProcessing(a); // CPU usage within a ScopedBlockingCall. 77*6777b538SAndroid Build Coastguard Worker // CPUIntensiveProcessing(b); // CPU usage within a ScopedBlockingCall. 78*6777b538SAndroid Build Coastguard Worker // 79*6777b538SAndroid Build Coastguard Worker // Good: 80*6777b538SAndroid Build Coastguard Worker // base::WaitableEvent waitable_event(...); 81*6777b538SAndroid Build Coastguard Worker // waitable_event.Wait(); 82*6777b538SAndroid Build Coastguard Worker // 83*6777b538SAndroid Build Coastguard Worker // Bad: 84*6777b538SAndroid Build Coastguard Worker // base::WaitableEvent waitable_event(...); 85*6777b538SAndroid Build Coastguard Worker // ScopedBlockingCall scoped_blocking_call( 86*6777b538SAndroid Build Coastguard Worker // FROM_HERE, BlockingType::WILL_BLOCK); 87*6777b538SAndroid Build Coastguard Worker // waitable_event.Wait(); // Wait() instantiates its own ScopedBlockingCall. 88*6777b538SAndroid Build Coastguard Worker // 89*6777b538SAndroid Build Coastguard Worker // When a ScopedBlockingCall is instantiated from a ThreadPool parallel or 90*6777b538SAndroid Build Coastguard Worker // sequenced task, the thread pool size is incremented to compensate for the 91*6777b538SAndroid Build Coastguard Worker // blocked thread (more or less aggressively depending on BlockingType). 92*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT [[nodiscard]] ScopedBlockingCall 93*6777b538SAndroid Build Coastguard Worker : public internal::UncheckedScopedBlockingCall { 94*6777b538SAndroid Build Coastguard Worker public: 95*6777b538SAndroid Build Coastguard Worker ScopedBlockingCall(const Location& from_here, BlockingType blocking_type); 96*6777b538SAndroid Build Coastguard Worker ~ScopedBlockingCall(); 97*6777b538SAndroid Build Coastguard Worker }; 98*6777b538SAndroid Build Coastguard Worker 99*6777b538SAndroid Build Coastguard Worker // Usage reserved for //base callers. 100*6777b538SAndroid Build Coastguard Worker namespace internal { 101*6777b538SAndroid Build Coastguard Worker 102*6777b538SAndroid Build Coastguard Worker // This class must be instantiated in every scope where a sync primitive is 103*6777b538SAndroid Build Coastguard Worker // used. When a ScopedBlockingCallWithBaseSyncPrimitives is instantiated, it 104*6777b538SAndroid Build Coastguard Worker // asserts that sync primitives are allowed in its scope with a call to 105*6777b538SAndroid Build Coastguard Worker // internal::AssertBaseSyncPrimitivesAllowed(). The same guidelines as for 106*6777b538SAndroid Build Coastguard Worker // ScopedBlockingCall should be followed. 107*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT [[nodiscard]] ScopedBlockingCallWithBaseSyncPrimitives 108*6777b538SAndroid Build Coastguard Worker : public UncheckedScopedBlockingCall { 109*6777b538SAndroid Build Coastguard Worker public: 110*6777b538SAndroid Build Coastguard Worker ScopedBlockingCallWithBaseSyncPrimitives(const Location& from_here, 111*6777b538SAndroid Build Coastguard Worker BlockingType blocking_type); 112*6777b538SAndroid Build Coastguard Worker ~ScopedBlockingCallWithBaseSyncPrimitives(); 113*6777b538SAndroid Build Coastguard Worker }; 114*6777b538SAndroid Build Coastguard Worker 115*6777b538SAndroid Build Coastguard Worker } // namespace internal 116*6777b538SAndroid Build Coastguard Worker 117*6777b538SAndroid Build Coastguard Worker using IOJankReportingCallback = 118*6777b538SAndroid Build Coastguard Worker RepeatingCallback<void(int janky_intervals_per_minute, 119*6777b538SAndroid Build Coastguard Worker int total_janks_per_minute)>; 120*6777b538SAndroid Build Coastguard Worker using OnlyObservedThreadsForTest = 121*6777b538SAndroid Build Coastguard Worker StrongAlias<class OnlyObservedThreadsTag, bool>; 122*6777b538SAndroid Build Coastguard Worker // Enables IO jank monitoring and reporting for this process. Should be called 123*6777b538SAndroid Build Coastguard Worker // at most once per process and only if 124*6777b538SAndroid Build Coastguard Worker // base::TimeTicks::IsConsistentAcrossProcesses() (the algorithm is unsafe 125*6777b538SAndroid Build Coastguard Worker // otherwise). |reporting_callback| will be invoked each time a monitoring 126*6777b538SAndroid Build Coastguard Worker // window completes, see internal::~IOJankMonitoringWindow() for details 127*6777b538SAndroid Build Coastguard Worker // (must be thread-safe). |only_observed_threads| can be set to true to have 128*6777b538SAndroid Build Coastguard Worker // the IOJank implementation ignore ScopedBlockingCalls on threads without a 129*6777b538SAndroid Build Coastguard Worker // BlockingObserver in tests that need to deterministically observe 130*6777b538SAndroid Build Coastguard Worker // ScopedBlockingCall side-effects. 131*6777b538SAndroid Build Coastguard Worker void BASE_EXPORT EnableIOJankMonitoringForProcess( 132*6777b538SAndroid Build Coastguard Worker IOJankReportingCallback reporting_callback, 133*6777b538SAndroid Build Coastguard Worker OnlyObservedThreadsForTest only_observed_threads = 134*6777b538SAndroid Build Coastguard Worker OnlyObservedThreadsForTest(false)); 135*6777b538SAndroid Build Coastguard Worker 136*6777b538SAndroid Build Coastguard Worker } // namespace base 137*6777b538SAndroid Build Coastguard Worker 138*6777b538SAndroid Build Coastguard Worker #endif // BASE_THREADING_SCOPED_BLOCKING_CALL_H_ 139