| Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2011 The Chromium Authors |
| license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 4 | |
| [email protected] | bc581a68 | 2011-01-01 23:16:20 | [diff] [blame] | 5 | #ifndef BASE_SYNCHRONIZATION_LOCK_IMPL_H_ |
| 6 | #define BASE_SYNCHRONIZATION_LOCK_IMPL_H_ |
| [email protected] | 08048c7 | 2008-08-08 16:19:43 | [diff] [blame] | 7 | |
| Jose Dapena Paz | 48e39d6 | 2024-06-11 10:43:36 | [diff] [blame] | 8 | #include <utility> |
| 9 | |
| avi | 9b6f4293 | 2015-12-26 22:15:14 | [diff] [blame] | 10 | #include "base/base_export.h" |
| Nico Weber | f718af8 | 2022-03-21 16:56:29 | [diff] [blame] | 11 | #include "base/check.h" |
| David Sanders | fc1f17fa | 2022-04-15 00:15:49 | [diff] [blame] | 12 | #include "base/dcheck_is_on.h" |
| Bartek Nowierski | aaa105f7 | 2024-01-31 07:25:07 | [diff] [blame] | 13 | #include "base/memory/raw_ptr_exclusion.h" |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 14 | #include "base/memory/stack_allocated.h" |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 15 | #include "base/synchronization/lock_subtle.h" |
| Anand Ravi | 9d185cd68 | 2025-03-27 16:41:52 | [diff] [blame] | 16 | #include "base/synchronization/synchronization_buildflags.h" |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 17 | #include "base/thread_annotations.h" |
| [email protected] | 08048c7 | 2008-08-08 16:19:43 | [diff] [blame] | 18 | #include "build/build_config.h" |
| 19 | |
| Xiaohan Wang | 94424e3 | 2022-01-15 14:51:32 | [diff] [blame] | 20 | #if BUILDFLAG(IS_WIN) |
| Bruce Dawson | bfdc3fd | 2018-01-03 20:32:36 | [diff] [blame] | 21 | #include "base/win/windows_types.h" |
| Xiaohan Wang | 94424e3 | 2022-01-15 14:51:32 | [diff] [blame] | 22 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
| hans | 73f022a | 2017-06-21 02:34:17 | [diff] [blame] | 23 | #include <errno.h> |
| [email protected] | 08048c7 | 2008-08-08 16:19:43 | [diff] [blame] | 24 | #include <pthread.h> |
| Hidehiko Abe | b63733e | 2020-04-17 18:35:39 | [diff] [blame] | 25 | #include <string.h> |
| [email protected] | 08048c7 | 2008-08-08 16:19:43 | [diff] [blame] | 26 | #endif |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 27 | |
| [email protected] | bc581a68 | 2011-01-01 23:16:20 | [diff] [blame] | 28 | namespace base { |
| Benoit Lize | b3b9e14 | 2020-09-01 09:48:11 | [diff] [blame] | 29 | class Lock; |
| 30 | class ConditionVariable; |
| 31 | |
| 32 | namespace win { |
| 33 | namespace internal { |
| 34 | class AutoNativeLock; |
| 35 | class ScopedHandleVerifier; |
| 36 | } // namespace internal |
| 37 | } // namespace win |
| 38 | |
| [email protected] | bc581a68 | 2011-01-01 23:16:20 | [diff] [blame] | 39 | namespace internal { |
| 40 | |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 41 | // This class implements the underlying platform-specific spin-lock mechanism |
| Benoit Lize | b3b9e14 | 2020-09-01 09:48:11 | [diff] [blame] | 42 | // used for the Lock class. Do not use, use Lock instead. |
| [email protected] | 0bea725 | 2011-08-05 15:34:00 | [diff] [blame] | 43 | class BASE_EXPORT LockImpl { |
| Peter Boström | 75cd3c0 | 2021-09-28 15:23:18 | [diff] [blame] | 44 | public: |
| 45 | LockImpl(const LockImpl&) = delete; |
| 46 | LockImpl& operator=(const LockImpl&) = delete; |
| 47 | |
| 48 | private: |
| Benoit Lize | b3b9e14 | 2020-09-01 09:48:11 | [diff] [blame] | 49 | friend class base::Lock; |
| 50 | friend class base::ConditionVariable; |
| 51 | friend class base::win::internal::AutoNativeLock; |
| 52 | friend class base::win::internal::ScopedHandleVerifier; |
| 53 | |
| Xiaohan Wang | 94424e3 | 2022-01-15 14:51:32 | [diff] [blame] | 54 | #if BUILDFLAG(IS_WIN) |
| Bruce Dawson | bfdc3fd | 2018-01-03 20:32:36 | [diff] [blame] | 55 | using NativeHandle = CHROME_SRWLOCK; |
| Xiaohan Wang | 94424e3 | 2022-01-15 14:51:32 | [diff] [blame] | 56 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
| hans | 73f022a | 2017-06-21 02:34:17 | [diff] [blame] | 57 | using NativeHandle = pthread_mutex_t; |
| [email protected] | 08048c7 | 2008-08-08 16:19:43 | [diff] [blame] | 58 | #endif |
| 59 | |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 60 | LockImpl(); |
| 61 | ~LockImpl(); |
| 62 | |
| 63 | // If the lock is not held, take it and return true. If the lock is already |
| 64 | // held by something else, immediately return false. |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 65 | inline bool Try(); |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 66 | |
| 67 | // Take the lock, blocking until it is available if necessary. |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 68 | inline void Lock(); |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 69 | |
| 70 | // Release the lock. This must only be called by the lock's holder: after |
| 71 | // a successful call to Try, or a call to Lock. |
| hans | 73f022a | 2017-06-21 02:34:17 | [diff] [blame] | 72 | inline void Unlock(); |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 73 | |
| [email protected] | 7f19742 | 2011-12-15 18:57:23 | [diff] [blame] | 74 | // Return the native underlying lock. |
| [email protected] | 08048c7 | 2008-08-08 16:19:43 | [diff] [blame] | 75 | // TODO(awalker): refactor lock and condition variables so that this is |
| 76 | // unnecessary. |
| [email protected] | 8fe650c2 | 2013-09-14 05:27:08 | [diff] [blame] | 77 | NativeHandle* native_handle() { return &native_handle_; } |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 78 | |
| Xiaohan Wang | 94424e3 | 2022-01-15 14:51:32 | [diff] [blame] | 79 | #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
| robliao | 206071838 | 2016-08-01 20:59:42 | [diff] [blame] | 80 | // Whether this lock will attempt to use priority inheritance. |
| 81 | static bool PriorityInheritanceAvailable(); |
| 82 | #endif |
| 83 | |
| Joe Mason | a0ba58b05 | 2023-02-22 20:46:29 | [diff] [blame] | 84 | void LockInternal(); |
| [email protected] | 8fe650c2 | 2013-09-14 05:27:08 | [diff] [blame] | 85 | NativeHandle native_handle_; |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 86 | }; |
| 87 | |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 88 | void LockImpl::Lock() { |
| Joe Mason | a0ba58b05 | 2023-02-22 20:46:29 | [diff] [blame] | 89 | // Try the lock first to acquire it cheaply if it's not contended. Try() is |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 90 | // cheap on platforms with futex-type locks, as it doesn't call into the |
| Peter Kasting | fa48899 | 2024-08-06 07:48:14 | [diff] [blame] | 91 | // kernel. Not marked `[[likely]]`, as: |
| Joe Mason | a0ba58b05 | 2023-02-22 20:46:29 | [diff] [blame] | 92 | // 1. We don't know how much contention the lock would experience |
| 93 | // 2. This may lead to weird-looking code layout when inlined into a caller |
| Peter Kasting | fa48899 | 2024-08-06 07:48:14 | [diff] [blame] | 94 | // with `[[(un)likely]]` attributes. |
| Joe Mason | a0ba58b05 | 2023-02-22 20:46:29 | [diff] [blame] | 95 | if (Try()) { |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 96 | return; |
| Joe Mason | a0ba58b05 | 2023-02-22 20:46:29 | [diff] [blame] | 97 | } |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 98 | |
| Joe Mason | a0ba58b05 | 2023-02-22 20:46:29 | [diff] [blame] | 99 | LockInternal(); |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 100 | } |
| 101 | |
| Xiaohan Wang | 94424e3 | 2022-01-15 14:51:32 | [diff] [blame] | 102 | #if BUILDFLAG(IS_WIN) |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 103 | bool LockImpl::Try() { |
| 104 | return !!::TryAcquireSRWLockExclusive( |
| 105 | reinterpret_cast<PSRWLOCK>(&native_handle_)); |
| 106 | } |
| 107 | |
| hans | 73f022a | 2017-06-21 02:34:17 | [diff] [blame] | 108 | void LockImpl::Unlock() { |
| Bruce Dawson | bfdc3fd | 2018-01-03 20:32:36 | [diff] [blame] | 109 | ::ReleaseSRWLockExclusive(reinterpret_cast<PSRWLOCK>(&native_handle_)); |
| hans | 73f022a | 2017-06-21 02:34:17 | [diff] [blame] | 110 | } |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 111 | |
| Xiaohan Wang | 94424e3 | 2022-01-15 14:51:32 | [diff] [blame] | 112 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 113 | |
| Nico Weber | f718af8 | 2022-03-21 16:56:29 | [diff] [blame] | 114 | #if DCHECK_IS_ON() |
| 115 | BASE_EXPORT void dcheck_trylock_result(int rv); |
| 116 | BASE_EXPORT void dcheck_unlock_result(int rv); |
| 117 | #endif |
| Benoit Lize | 50bbea9 | 2021-08-18 21:10:58 | [diff] [blame] | 118 | |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 119 | bool LockImpl::Try() { |
| 120 | int rv = pthread_mutex_trylock(&native_handle_); |
| Nico Weber | f718af8 | 2022-03-21 16:56:29 | [diff] [blame] | 121 | #if DCHECK_IS_ON() |
| 122 | dcheck_trylock_result(rv); |
| 123 | #endif |
| Benoit Lize | 7d86528b | 2020-09-08 17:41:00 | [diff] [blame] | 124 | return rv == 0; |
| 125 | } |
| 126 | |
| hans | 73f022a | 2017-06-21 02:34:17 | [diff] [blame] | 127 | void LockImpl::Unlock() { |
| Nico Weber | f718af8 | 2022-03-21 16:56:29 | [diff] [blame] | 128 | [[maybe_unused]] int rv = pthread_mutex_unlock(&native_handle_); |
| 129 | #if DCHECK_IS_ON() |
| 130 | dcheck_unlock_result(rv); |
| 131 | #endif |
| hans | 73f022a | 2017-06-21 02:34:17 | [diff] [blame] | 132 | } |
| 133 | #endif |
| 134 | |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 135 | // This is an implementation used for AutoLock templated on the lock type. |
| 136 | template <class LockType> |
| David Baron | 440f7cc | 2025-03-20 21:19:04 | [diff] [blame] | 137 | class [[nodiscard]] SCOPED_LOCKABLE BasicAutoLock { |
| Bartek Nowierski | 6e340a2 | 2024-06-06 00:14:50 | [diff] [blame] | 138 | STACK_ALLOCATED(); |
| 139 | |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 140 | public: |
| 141 | struct AlreadyAcquired {}; |
| 142 | |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 143 | explicit BasicAutoLock( |
| 144 | LockType& lock, |
| 145 | subtle::LockTracking tracking = subtle::LockTracking::kDisabled) |
| 146 | EXCLUSIVE_LOCK_FUNCTION(lock) |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 147 | : lock_(lock) { |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 148 | lock_.Acquire(tracking); |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 149 | } |
| 150 | |
| 151 | BasicAutoLock(LockType& lock, const AlreadyAcquired&) |
| 152 | EXCLUSIVE_LOCKS_REQUIRED(lock) |
| 153 | : lock_(lock) { |
| Jeremie Boulic | 8973042 | 2024-01-23 10:42:54 | [diff] [blame] | 154 | lock_.AssertAcquired(); |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 155 | } |
| 156 | |
| Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 157 | BasicAutoLock(const BasicAutoLock&) = delete; |
| 158 | BasicAutoLock& operator=(const BasicAutoLock&) = delete; |
| 159 | |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 160 | ~BasicAutoLock() UNLOCK_FUNCTION() { |
| Jeremie Boulic | 8973042 | 2024-01-23 10:42:54 | [diff] [blame] | 161 | lock_.AssertAcquired(); |
| 162 | lock_.Release(); |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | private: |
| Bartek Nowierski | 6e340a2 | 2024-06-06 00:14:50 | [diff] [blame] | 166 | LockType& lock_; |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 167 | }; |
| 168 | |
| Bartek Nowierski | bd32053 | 2024-06-04 23:58:52 | [diff] [blame] | 169 | // This is an implementation used for MovableAutoLock templated on the lock |
| 170 | // type. |
| 171 | template <class LockType> |
| David Baron | 440f7cc | 2025-03-20 21:19:04 | [diff] [blame] | 172 | class [[nodiscard]] SCOPED_LOCKABLE BasicMovableAutoLock { |
| Bartek Nowierski | bd32053 | 2024-06-04 23:58:52 | [diff] [blame] | 173 | public: |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 174 | explicit BasicMovableAutoLock( |
| 175 | LockType& lock, |
| 176 | subtle::LockTracking tracking = subtle::LockTracking::kDisabled) |
| 177 | EXCLUSIVE_LOCK_FUNCTION(lock) |
| Bartek Nowierski | bd32053 | 2024-06-04 23:58:52 | [diff] [blame] | 178 | : lock_(&lock) { |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 179 | lock_->Acquire(tracking); |
| Bartek Nowierski | bd32053 | 2024-06-04 23:58:52 | [diff] [blame] | 180 | } |
| 181 | |
| 182 | BasicMovableAutoLock(const BasicMovableAutoLock&) = delete; |
| 183 | BasicMovableAutoLock& operator=(const BasicMovableAutoLock&) = delete; |
| Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 184 | BasicMovableAutoLock(BasicMovableAutoLock&& other) |
| 185 | : lock_(std::exchange(other.lock_, nullptr)) {} |
| Bartek Nowierski | bd32053 | 2024-06-04 23:58:52 | [diff] [blame] | 186 | BasicMovableAutoLock& operator=(BasicMovableAutoLock&& other) = delete; |
| 187 | |
| 188 | ~BasicMovableAutoLock() UNLOCK_FUNCTION() { |
| 189 | // The lock may have been moved out. |
| 190 | if (lock_) { |
| 191 | lock_->AssertAcquired(); |
| 192 | lock_->Release(); |
| 193 | } |
| 194 | } |
| 195 | |
| 196 | private: |
| 197 | // RAW_PTR_EXCLUSION: Stack-scoped. |
| 198 | RAW_PTR_EXCLUSION LockType* lock_; |
| 199 | }; |
| 200 | |
| Koji Ishii | 22c7071 | 2021-10-20 22:21:09 | [diff] [blame] | 201 | // This is an implementation used for AutoTryLock templated on the lock type. |
| 202 | template <class LockType> |
| David Baron | 440f7cc | 2025-03-20 21:19:04 | [diff] [blame] | 203 | class [[nodiscard]] SCOPED_LOCKABLE BasicAutoTryLock { |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 204 | STACK_ALLOCATED(); |
| 205 | |
| Koji Ishii | 22c7071 | 2021-10-20 22:21:09 | [diff] [blame] | 206 | public: |
| Dan McArdle | f97ab60 | 2024-05-16 15:44:59 | [diff] [blame] | 207 | // The `LOCKS_EXCLUDED(lock)` annotation requires that the caller has not |
| 208 | // acquired `lock`. Without the annotation, Clang's Thread Safety Analysis |
| 209 | // would generate a false positive despite correct usage. For instance, a |
| 210 | // caller that checks `is_acquired()` before writing to guarded data would be |
| 211 | // flagged with "writing variable 'foo' requires holding 'lock' exclusively." |
| 212 | // See <https://crbug.com/340196356>. |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 213 | explicit BasicAutoTryLock( |
| 214 | LockType& lock, |
| 215 | subtle::LockTracking tracking = subtle::LockTracking::kDisabled) |
| 216 | LOCKS_EXCLUDED(lock) |
| 217 | : lock_(lock), is_acquired_(lock_.Try(tracking)) {} |
| Koji Ishii | 22c7071 | 2021-10-20 22:21:09 | [diff] [blame] | 218 | |
| 219 | BasicAutoTryLock(const BasicAutoTryLock&) = delete; |
| 220 | BasicAutoTryLock& operator=(const BasicAutoTryLock&) = delete; |
| 221 | |
| 222 | ~BasicAutoTryLock() UNLOCK_FUNCTION() { |
| 223 | if (is_acquired_) { |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 224 | lock_.AssertAcquired(); |
| 225 | lock_.Release(); |
| Koji Ishii | 22c7071 | 2021-10-20 22:21:09 | [diff] [blame] | 226 | } |
| 227 | } |
| 228 | |
| Dan McArdle | f97ab60 | 2024-05-16 15:44:59 | [diff] [blame] | 229 | bool is_acquired() const EXCLUSIVE_TRYLOCK_FUNCTION(true) { |
| 230 | return is_acquired_; |
| 231 | } |
| Koji Ishii | 22c7071 | 2021-10-20 22:21:09 | [diff] [blame] | 232 | |
| 233 | private: |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 234 | LockType& lock_; |
| Koji Ishii | 22c7071 | 2021-10-20 22:21:09 | [diff] [blame] | 235 | const bool is_acquired_; |
| 236 | }; |
| 237 | |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 238 | // This is an implementation used for AutoUnlock templated on the lock type. |
| 239 | template <class LockType> |
| David Baron | 440f7cc | 2025-03-20 21:19:04 | [diff] [blame] | 240 | class [[nodiscard]] BasicAutoUnlock { |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 241 | STACK_ALLOCATED(); |
| 242 | |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 243 | public: |
| 244 | explicit BasicAutoUnlock(LockType& lock) : lock_(lock) { |
| 245 | // We require our caller to have the lock. |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 246 | lock_.AssertAcquired(); |
| 247 | lock_.Release(); |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 248 | } |
| 249 | |
| Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 250 | BasicAutoUnlock(const BasicAutoUnlock&) = delete; |
| 251 | BasicAutoUnlock& operator=(const BasicAutoUnlock&) = delete; |
| 252 | |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 253 | ~BasicAutoUnlock() { lock_.Acquire(); } |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 254 | |
| 255 | private: |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 256 | LockType& lock_; |
| Etienne Pierre-doray | 8760a095 | 2019-03-07 03:13:12 | [diff] [blame] | 257 | }; |
| 258 | |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 259 | // This is an implementation used for AutoLockMaybe templated on the lock type. |
| 260 | template <class LockType> |
| David Baron | 440f7cc | 2025-03-20 21:19:04 | [diff] [blame] | 261 | class [[nodiscard]] SCOPED_LOCKABLE BasicAutoLockMaybe { |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 262 | STACK_ALLOCATED(); |
| 263 | |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 264 | public: |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 265 | explicit BasicAutoLockMaybe( |
| 266 | LockType* lock, |
| 267 | subtle::LockTracking tracking = subtle::LockTracking::kDisabled) |
| 268 | EXCLUSIVE_LOCK_FUNCTION(lock) |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 269 | : lock_(lock) { |
| Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 270 | if (lock_) { |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 271 | lock_->Acquire(tracking); |
| Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 272 | } |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 273 | } |
| 274 | |
| Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 275 | BasicAutoLockMaybe(const BasicAutoLockMaybe&) = delete; |
| 276 | BasicAutoLockMaybe& operator=(const BasicAutoLockMaybe&) = delete; |
| 277 | |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 278 | ~BasicAutoLockMaybe() UNLOCK_FUNCTION() { |
| 279 | if (lock_) { |
| 280 | lock_->AssertAcquired(); |
| 281 | lock_->Release(); |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | private: |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 286 | LockType* const lock_; |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 287 | }; |
| 288 | |
| 289 | // This is an implementation used for ReleasableAutoLock templated on the lock |
| 290 | // type. |
| 291 | template <class LockType> |
| David Baron | 440f7cc | 2025-03-20 21:19:04 | [diff] [blame] | 292 | class [[nodiscard]] SCOPED_LOCKABLE BasicReleasableAutoLock { |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 293 | STACK_ALLOCATED(); |
| 294 | |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 295 | public: |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 296 | explicit BasicReleasableAutoLock( |
| 297 | LockType* lock, |
| 298 | subtle::LockTracking tracking = subtle::LockTracking::kDisabled) |
| 299 | EXCLUSIVE_LOCK_FUNCTION(lock) |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 300 | : lock_(lock) { |
| 301 | DCHECK(lock_); |
| François Doray | 6671c40 | 2024-06-21 17:47:39 | [diff] [blame] | 302 | lock_->Acquire(tracking); |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 303 | } |
| 304 | |
| Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 305 | BasicReleasableAutoLock(const BasicReleasableAutoLock&) = delete; |
| 306 | BasicReleasableAutoLock& operator=(const BasicReleasableAutoLock&) = delete; |
| 307 | |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 308 | ~BasicReleasableAutoLock() UNLOCK_FUNCTION() { |
| 309 | if (lock_) { |
| 310 | lock_->AssertAcquired(); |
| 311 | lock_->Release(); |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | void Release() UNLOCK_FUNCTION() { |
| 316 | DCHECK(lock_); |
| 317 | lock_->AssertAcquired(); |
| 318 | lock_->Release(); |
| 319 | lock_ = nullptr; |
| 320 | } |
| 321 | |
| 322 | private: |
| Bartek Nowierski | 3bc9806 | 2024-03-28 02:41:36 | [diff] [blame] | 323 | LockType* lock_; |
| Gabriel Charette | d773f12 | 2019-03-19 22:06:38 | [diff] [blame] | 324 | }; |
| 325 | |
| [email protected] | bc581a68 | 2011-01-01 23:16:20 | [diff] [blame] | 326 | } // namespace internal |
| Anand Ravi | 9d185cd68 | 2025-03-27 16:41:52 | [diff] [blame] | 327 | |
| Anand Ravi | 9d185cd68 | 2025-03-27 16:41:52 | [diff] [blame] | 328 | // Check to see whether the current kernel supports priority inheritance |
| 329 | // properly by adjusting process priorities to boost the futex owner. |
| 330 | BASE_EXPORT bool KernelSupportsPriorityInheritanceFutex(); |
| Anand Ravi | 9d185cd68 | 2025-03-27 16:41:52 | [diff] [blame] | 331 | |
| [email protected] | bc581a68 | 2011-01-01 23:16:20 | [diff] [blame] | 332 | } // namespace base |
| initial.commit | d7cae12 | 2008-07-26 21:49:38 | [diff] [blame] | 333 | |
| [email protected] | bc581a68 | 2011-01-01 23:16:20 | [diff] [blame] | 334 | #endif // BASE_SYNCHRONIZATION_LOCK_IMPL_H_ |