• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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 #ifndef BASE_THREADING_SCOPED_THREAD_PRIORITY_H_
6 #define BASE_THREADING_SCOPED_THREAD_PRIORITY_H_
7 
8 #include <atomic>
9 #include <optional>
10 
11 #include "base/base_export.h"
12 #include "base/compiler_specific.h"
13 #include "base/location.h"
14 #include "base/macros/uniquify.h"
15 #include "base/memory/raw_ptr.h"
16 #include "build/build_config.h"
17 
18 namespace base {
19 
20 class Location;
21 enum class ThreadType : int;
22 
23 // All code that may load a DLL on a background thread must be surrounded by a
24 // scope that starts with this macro.
25 //
26 // Example:
27 //   Foo();
28 //   {
29 //     SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
30 //     LoadMyDll();
31 //   }
32 //   Bar();
33 //
34 // The macro raises the thread priority to match ThreadType::kDefault for the
35 // scope if no other thread has completed the current scope already (multiple
36 // threads can racily begin the initialization and will all be boosted for it).
37 // On Windows, loading a DLL on a background thread can lead to a priority
38 // inversion on the loader lock and cause huge janks.
39 #define SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY()                  \
40   static std::atomic_bool BASE_UNIQUIFY(already_loaded){false};           \
41   base::internal::ScopedMayLoadLibraryAtBackgroundPriority BASE_UNIQUIFY( \
42       scoped_may_load_library_at_background_priority)(                    \
43       FROM_HERE, &BASE_UNIQUIFY(already_loaded));
44 
45 // Like SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY, but raises the thread
46 // priority every time the scope is entered. Use this around code that may
47 // conditionally load a DLL each time it is executed, or which repeatedly loads
48 // and unloads DLLs.
49 #define SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY_REPEATEDLY()       \
50   base::internal::ScopedMayLoadLibraryAtBackgroundPriority BASE_UNIQUIFY( \
51       scoped_may_load_library_at_background_priority)(FROM_HERE, nullptr);
52 
53 // Boosts the current thread's priority to match the priority of threads of
54 // `target_thread_type` in this scope. `target_thread_type` must be lower
55 // priority than kRealtimeAudio, since realtime priority should only be used by
56 // dedicated media threads.
57 class BASE_EXPORT ScopedBoostPriority {
58  public:
59   explicit ScopedBoostPriority(ThreadType target_thread_type);
60   ~ScopedBoostPriority();
61 
62   ScopedBoostPriority(const ScopedBoostPriority&) = delete;
63   ScopedBoostPriority& operator=(const ScopedBoostPriority&) = delete;
64 
65  private:
66   std::optional<ThreadType> original_thread_type_;
67 };
68 
69 namespace internal {
70 
71 class BASE_EXPORT ScopedMayLoadLibraryAtBackgroundPriority {
72  public:
73   // Boosts thread priority to match ThreadType::kDefault within its scope if
74   // `already_loaded` is nullptr or set to false.
75   explicit ScopedMayLoadLibraryAtBackgroundPriority(
76       const Location& from_here,
77       std::atomic_bool* already_loaded);
78 
79   ScopedMayLoadLibraryAtBackgroundPriority(
80       const ScopedMayLoadLibraryAtBackgroundPriority&) = delete;
81   ScopedMayLoadLibraryAtBackgroundPriority& operator=(
82       const ScopedMayLoadLibraryAtBackgroundPriority&) = delete;
83 
84   ~ScopedMayLoadLibraryAtBackgroundPriority();
85 
86  private:
87 #if BUILDFLAG(IS_WIN)
88   // The original priority when invoking entering the scope().
89   std::optional<ThreadType> original_thread_type_;
90   const raw_ptr<std::atomic_bool> already_loaded_;
91 #endif
92 };
93 
94 }  // namespace internal
95 
96 }  // namespace base
97 
98 #endif  // BASE_THREADING_SCOPED_THREAD_PRIORITY_H_
99