1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #pragma once
18
19 #include <android-base/thread_annotations.h>
20 #include <audio_utils/safe_math.h>
21 #include <audio_utils/threads.h>
22 #include <utils/Log.h>
23 #include <utils/Timers.h>
24
25 #include <algorithm>
26 #include <array>
27 #include <cmath>
28 #include <map>
29 #include <memory>
30 #include <mutex>
31 #include <sys/syscall.h>
32 #include <unordered_map>
33 #include <unordered_set>
34 #include <utility>
35 #include <vector>
36
37 #pragma push_macro("LOG_TAG")
38 #undef LOG_TAG
39 #define LOG_TAG "audio_utils::mutex"
40
41 namespace android::audio_utils {
42
43 // Define global capabilities for thread-safety annotation.
44 //
45 // These can be manually modified, or
46 // compile generate_mutex_order.cpp in the tests directory
47 // to generate this.
48
49 // --- Begin generated section
50
51 // Lock order
52 enum class MutexOrder : uint32_t {
53 kSpatializer_Mutex = 0,
54 kAudioPolicyEffects_Mutex = 1,
55 kEffectHandle_Mutex = 2,
56 kEffectBase_PolicyMutex = 3,
57 kAudioPolicyService_Mutex = 4,
58 kCommandThread_Mutex = 5,
59 kAudioCommand_Mutex = 6,
60 kUidPolicy_Mutex = 7,
61 kAudioFlinger_Mutex = 8,
62 kDeviceEffectManager_Mutex = 9,
63 kDeviceEffectProxy_ProxyMutex = 10,
64 kDeviceEffectHandle_Mutex = 11,
65 kPatchCommandThread_Mutex = 12,
66 kThreadBase_Mutex = 13,
67 kAudioFlinger_ClientMutex = 14,
68 kEffectChain_Mutex = 15,
69 kEffectBase_Mutex = 16,
70 kAudioFlinger_HardwareMutex = 17,
71 kMelReporter_Mutex = 18,
72 kAudioFlinger_UnregisteredWritersMutex = 19,
73 kAsyncCallbackThread_Mutex = 20,
74 kConfigEvent_Mutex = 21,
75 kOutputTrack_TrackMetadataMutex = 22,
76 kPassthruPatchRecord_ReadMutex = 23,
77 kPatchCommandThread_ListenerMutex = 24,
78 kPlaybackThread_AudioTrackCbMutex = 25,
79 kAudioPolicyService_NotificationClientsMutex = 26,
80 kMediaLogNotifier_Mutex = 27,
81 kOtherMutex = 28,
82 kSize = 29,
83 };
84
85 // Lock by name
86 inline constexpr const char* const gMutexNames[] = {
87 "Spatializer_Mutex",
88 "AudioPolicyEffects_Mutex",
89 "EffectHandle_Mutex",
90 "EffectBase_PolicyMutex",
91 "AudioPolicyService_Mutex",
92 "CommandThread_Mutex",
93 "AudioCommand_Mutex",
94 "UidPolicy_Mutex",
95 "AudioFlinger_Mutex",
96 "DeviceEffectManager_Mutex",
97 "DeviceEffectProxy_ProxyMutex",
98 "DeviceEffectHandle_Mutex",
99 "PatchCommandThread_Mutex",
100 "ThreadBase_Mutex",
101 "AudioFlinger_ClientMutex",
102 "EffectChain_Mutex",
103 "EffectBase_Mutex",
104 "AudioFlinger_HardwareMutex",
105 "MelReporter_Mutex",
106 "AudioFlinger_UnregisteredWritersMutex",
107 "AsyncCallbackThread_Mutex",
108 "ConfigEvent_Mutex",
109 "OutputTrack_TrackMetadataMutex",
110 "PassthruPatchRecord_ReadMutex",
111 "PatchCommandThread_ListenerMutex",
112 "PlaybackThread_AudioTrackCbMutex",
113 "AudioPolicyService_NotificationClientsMutex",
114 "MediaLogNotifier_Mutex",
115 "OtherMutex",
116 };
117
118 // Forward declarations
119 class AudioMutexAttributes;
120 template <typename T> class mutex_impl;
121 using mutex = mutex_impl<AudioMutexAttributes>;
122
123 // Capabilities in priority order
124 // (declaration only, value is nullptr)
125 inline mutex* Spatializer_Mutex;
126 inline mutex* AudioPolicyEffects_Mutex
127 ACQUIRED_AFTER(android::audio_utils::Spatializer_Mutex);
128 inline mutex* EffectHandle_Mutex
129 ACQUIRED_AFTER(android::audio_utils::AudioPolicyEffects_Mutex);
130 inline mutex* EffectBase_PolicyMutex
131 ACQUIRED_AFTER(android::audio_utils::EffectHandle_Mutex);
132 inline mutex* AudioPolicyService_Mutex
133 ACQUIRED_AFTER(android::audio_utils::EffectBase_PolicyMutex);
134 inline mutex* CommandThread_Mutex
135 ACQUIRED_AFTER(android::audio_utils::AudioPolicyService_Mutex);
136 inline mutex* AudioCommand_Mutex
137 ACQUIRED_AFTER(android::audio_utils::CommandThread_Mutex);
138 inline mutex* UidPolicy_Mutex
139 ACQUIRED_AFTER(android::audio_utils::AudioCommand_Mutex);
140 inline mutex* AudioFlinger_Mutex
141 ACQUIRED_AFTER(android::audio_utils::UidPolicy_Mutex);
142 inline mutex* DeviceEffectManager_Mutex
143 ACQUIRED_AFTER(android::audio_utils::AudioFlinger_Mutex);
144 inline mutex* DeviceEffectProxy_ProxyMutex
145 ACQUIRED_AFTER(android::audio_utils::DeviceEffectManager_Mutex);
146 inline mutex* DeviceEffectHandle_Mutex
147 ACQUIRED_AFTER(android::audio_utils::DeviceEffectProxy_ProxyMutex);
148 inline mutex* PatchCommandThread_Mutex
149 ACQUIRED_AFTER(android::audio_utils::DeviceEffectHandle_Mutex);
150 inline mutex* ThreadBase_Mutex
151 ACQUIRED_AFTER(android::audio_utils::PatchCommandThread_Mutex);
152 inline mutex* AudioFlinger_ClientMutex
153 ACQUIRED_AFTER(android::audio_utils::ThreadBase_Mutex);
154 inline mutex* EffectChain_Mutex
155 ACQUIRED_AFTER(android::audio_utils::AudioFlinger_ClientMutex);
156 inline mutex* EffectBase_Mutex
157 ACQUIRED_AFTER(android::audio_utils::EffectChain_Mutex);
158 inline mutex* AudioFlinger_HardwareMutex
159 ACQUIRED_AFTER(android::audio_utils::EffectBase_Mutex);
160 inline mutex* MelReporter_Mutex
161 ACQUIRED_AFTER(android::audio_utils::AudioFlinger_HardwareMutex);
162 inline mutex* AudioFlinger_UnregisteredWritersMutex
163 ACQUIRED_AFTER(android::audio_utils::MelReporter_Mutex);
164 inline mutex* AsyncCallbackThread_Mutex
165 ACQUIRED_AFTER(android::audio_utils::AudioFlinger_UnregisteredWritersMutex);
166 inline mutex* ConfigEvent_Mutex
167 ACQUIRED_AFTER(android::audio_utils::AsyncCallbackThread_Mutex);
168 inline mutex* OutputTrack_TrackMetadataMutex
169 ACQUIRED_AFTER(android::audio_utils::ConfigEvent_Mutex);
170 inline mutex* PassthruPatchRecord_ReadMutex
171 ACQUIRED_AFTER(android::audio_utils::OutputTrack_TrackMetadataMutex);
172 inline mutex* PatchCommandThread_ListenerMutex
173 ACQUIRED_AFTER(android::audio_utils::PassthruPatchRecord_ReadMutex);
174 inline mutex* PlaybackThread_AudioTrackCbMutex
175 ACQUIRED_AFTER(android::audio_utils::PatchCommandThread_ListenerMutex);
176 inline mutex* AudioPolicyService_NotificationClientsMutex
177 ACQUIRED_AFTER(android::audio_utils::PlaybackThread_AudioTrackCbMutex);
178 inline mutex* MediaLogNotifier_Mutex
179 ACQUIRED_AFTER(android::audio_utils::AudioPolicyService_NotificationClientsMutex);
180 inline mutex* OtherMutex
181 ACQUIRED_AFTER(android::audio_utils::MediaLogNotifier_Mutex);
182
183 // Exclusion by capability
184 #define EXCLUDES_BELOW_OtherMutex
185 #define EXCLUDES_OtherMutex \
186 EXCLUDES(android::audio_utils::OtherMutex) \
187 EXCLUDES_BELOW_OtherMutex
188
189 #define EXCLUDES_BELOW_MediaLogNotifier_Mutex \
190 EXCLUDES_OtherMutex
191 #define EXCLUDES_MediaLogNotifier_Mutex \
192 EXCLUDES(android::audio_utils::MediaLogNotifier_Mutex) \
193 EXCLUDES_BELOW_MediaLogNotifier_Mutex
194
195 #define EXCLUDES_BELOW_AudioPolicyService_NotificationClientsMutex \
196 EXCLUDES_MediaLogNotifier_Mutex
197 #define EXCLUDES_AudioPolicyService_NotificationClientsMutex \
198 EXCLUDES(android::audio_utils::AudioPolicyService_NotificationClientsMutex) \
199 EXCLUDES_BELOW_AudioPolicyService_NotificationClientsMutex
200
201 #define EXCLUDES_BELOW_PlaybackThread_AudioTrackCbMutex \
202 EXCLUDES_AudioPolicyService_NotificationClientsMutex
203 #define EXCLUDES_PlaybackThread_AudioTrackCbMutex \
204 EXCLUDES(android::audio_utils::PlaybackThread_AudioTrackCbMutex) \
205 EXCLUDES_BELOW_PlaybackThread_AudioTrackCbMutex
206
207 #define EXCLUDES_BELOW_PatchCommandThread_ListenerMutex \
208 EXCLUDES_PlaybackThread_AudioTrackCbMutex
209 #define EXCLUDES_PatchCommandThread_ListenerMutex \
210 EXCLUDES(android::audio_utils::PatchCommandThread_ListenerMutex) \
211 EXCLUDES_BELOW_PatchCommandThread_ListenerMutex
212
213 #define EXCLUDES_BELOW_PassthruPatchRecord_ReadMutex \
214 EXCLUDES_PatchCommandThread_ListenerMutex
215 #define EXCLUDES_PassthruPatchRecord_ReadMutex \
216 EXCLUDES(android::audio_utils::PassthruPatchRecord_ReadMutex) \
217 EXCLUDES_BELOW_PassthruPatchRecord_ReadMutex
218
219 #define EXCLUDES_BELOW_OutputTrack_TrackMetadataMutex \
220 EXCLUDES_PassthruPatchRecord_ReadMutex
221 #define EXCLUDES_OutputTrack_TrackMetadataMutex \
222 EXCLUDES(android::audio_utils::OutputTrack_TrackMetadataMutex) \
223 EXCLUDES_BELOW_OutputTrack_TrackMetadataMutex
224
225 #define EXCLUDES_BELOW_ConfigEvent_Mutex \
226 EXCLUDES_OutputTrack_TrackMetadataMutex
227 #define EXCLUDES_ConfigEvent_Mutex \
228 EXCLUDES(android::audio_utils::ConfigEvent_Mutex) \
229 EXCLUDES_BELOW_ConfigEvent_Mutex
230
231 #define EXCLUDES_BELOW_AsyncCallbackThread_Mutex \
232 EXCLUDES_ConfigEvent_Mutex
233 #define EXCLUDES_AsyncCallbackThread_Mutex \
234 EXCLUDES(android::audio_utils::AsyncCallbackThread_Mutex) \
235 EXCLUDES_BELOW_AsyncCallbackThread_Mutex
236
237 #define EXCLUDES_BELOW_AudioFlinger_UnregisteredWritersMutex \
238 EXCLUDES_AsyncCallbackThread_Mutex
239 #define EXCLUDES_AudioFlinger_UnregisteredWritersMutex \
240 EXCLUDES(android::audio_utils::AudioFlinger_UnregisteredWritersMutex) \
241 EXCLUDES_BELOW_AudioFlinger_UnregisteredWritersMutex
242
243 #define EXCLUDES_BELOW_MelReporter_Mutex \
244 EXCLUDES_AudioFlinger_UnregisteredWritersMutex
245 #define EXCLUDES_MelReporter_Mutex \
246 EXCLUDES(android::audio_utils::MelReporter_Mutex) \
247 EXCLUDES_BELOW_MelReporter_Mutex
248
249 #define EXCLUDES_BELOW_AudioFlinger_HardwareMutex \
250 EXCLUDES_MelReporter_Mutex
251 #define EXCLUDES_AudioFlinger_HardwareMutex \
252 EXCLUDES(android::audio_utils::AudioFlinger_HardwareMutex) \
253 EXCLUDES_BELOW_AudioFlinger_HardwareMutex
254
255 #define EXCLUDES_BELOW_EffectBase_Mutex \
256 EXCLUDES_AudioFlinger_HardwareMutex
257 #define EXCLUDES_EffectBase_Mutex \
258 EXCLUDES(android::audio_utils::EffectBase_Mutex) \
259 EXCLUDES_BELOW_EffectBase_Mutex
260
261 #define EXCLUDES_BELOW_EffectChain_Mutex \
262 EXCLUDES_EffectBase_Mutex
263 #define EXCLUDES_EffectChain_Mutex \
264 EXCLUDES(android::audio_utils::EffectChain_Mutex) \
265 EXCLUDES_BELOW_EffectChain_Mutex
266
267 #define EXCLUDES_BELOW_AudioFlinger_ClientMutex \
268 EXCLUDES_EffectChain_Mutex
269 #define EXCLUDES_AudioFlinger_ClientMutex \
270 EXCLUDES(android::audio_utils::AudioFlinger_ClientMutex) \
271 EXCLUDES_BELOW_AudioFlinger_ClientMutex
272
273 #define EXCLUDES_BELOW_ThreadBase_Mutex \
274 EXCLUDES_AudioFlinger_ClientMutex
275 #define EXCLUDES_ThreadBase_Mutex \
276 EXCLUDES(android::audio_utils::ThreadBase_Mutex) \
277 EXCLUDES_BELOW_ThreadBase_Mutex
278
279 #define EXCLUDES_BELOW_PatchCommandThread_Mutex \
280 EXCLUDES_ThreadBase_Mutex
281 #define EXCLUDES_PatchCommandThread_Mutex \
282 EXCLUDES(android::audio_utils::PatchCommandThread_Mutex) \
283 EXCLUDES_BELOW_PatchCommandThread_Mutex
284
285 #define EXCLUDES_BELOW_DeviceEffectHandle_Mutex \
286 EXCLUDES_PatchCommandThread_Mutex
287 #define EXCLUDES_DeviceEffectHandle_Mutex \
288 EXCLUDES(android::audio_utils::DeviceEffectHandle_Mutex) \
289 EXCLUDES_BELOW_DeviceEffectHandle_Mutex
290
291 #define EXCLUDES_BELOW_DeviceEffectProxy_ProxyMutex \
292 EXCLUDES_DeviceEffectHandle_Mutex
293 #define EXCLUDES_DeviceEffectProxy_ProxyMutex \
294 EXCLUDES(android::audio_utils::DeviceEffectProxy_ProxyMutex) \
295 EXCLUDES_BELOW_DeviceEffectProxy_ProxyMutex
296
297 #define EXCLUDES_BELOW_DeviceEffectManager_Mutex \
298 EXCLUDES_DeviceEffectProxy_ProxyMutex
299 #define EXCLUDES_DeviceEffectManager_Mutex \
300 EXCLUDES(android::audio_utils::DeviceEffectManager_Mutex) \
301 EXCLUDES_BELOW_DeviceEffectManager_Mutex
302
303 #define EXCLUDES_BELOW_AudioFlinger_Mutex \
304 EXCLUDES_DeviceEffectManager_Mutex
305 #define EXCLUDES_AudioFlinger_Mutex \
306 EXCLUDES(android::audio_utils::AudioFlinger_Mutex) \
307 EXCLUDES_BELOW_AudioFlinger_Mutex
308
309 #define EXCLUDES_BELOW_UidPolicy_Mutex \
310 EXCLUDES_AudioFlinger_Mutex
311 #define EXCLUDES_UidPolicy_Mutex \
312 EXCLUDES(android::audio_utils::UidPolicy_Mutex) \
313 EXCLUDES_BELOW_UidPolicy_Mutex
314
315 #define EXCLUDES_BELOW_AudioCommand_Mutex \
316 EXCLUDES_UidPolicy_Mutex
317 #define EXCLUDES_AudioCommand_Mutex \
318 EXCLUDES(android::audio_utils::AudioCommand_Mutex) \
319 EXCLUDES_BELOW_AudioCommand_Mutex
320
321 #define EXCLUDES_BELOW_CommandThread_Mutex \
322 EXCLUDES_AudioCommand_Mutex
323 #define EXCLUDES_CommandThread_Mutex \
324 EXCLUDES(android::audio_utils::CommandThread_Mutex) \
325 EXCLUDES_BELOW_CommandThread_Mutex
326
327 #define EXCLUDES_BELOW_AudioPolicyService_Mutex \
328 EXCLUDES_CommandThread_Mutex
329 #define EXCLUDES_AudioPolicyService_Mutex \
330 EXCLUDES(android::audio_utils::AudioPolicyService_Mutex) \
331 EXCLUDES_BELOW_AudioPolicyService_Mutex
332
333 #define EXCLUDES_BELOW_EffectBase_PolicyMutex \
334 EXCLUDES_AudioPolicyService_Mutex
335 #define EXCLUDES_EffectBase_PolicyMutex \
336 EXCLUDES(android::audio_utils::EffectBase_PolicyMutex) \
337 EXCLUDES_BELOW_EffectBase_PolicyMutex
338
339 #define EXCLUDES_BELOW_EffectHandle_Mutex \
340 EXCLUDES_EffectBase_PolicyMutex
341 #define EXCLUDES_EffectHandle_Mutex \
342 EXCLUDES(android::audio_utils::EffectHandle_Mutex) \
343 EXCLUDES_BELOW_EffectHandle_Mutex
344
345 #define EXCLUDES_BELOW_AudioPolicyEffects_Mutex \
346 EXCLUDES_EffectHandle_Mutex
347 #define EXCLUDES_AudioPolicyEffects_Mutex \
348 EXCLUDES(android::audio_utils::AudioPolicyEffects_Mutex) \
349 EXCLUDES_BELOW_AudioPolicyEffects_Mutex
350
351 #define EXCLUDES_BELOW_Spatializer_Mutex \
352 EXCLUDES_AudioPolicyEffects_Mutex
353 #define EXCLUDES_Spatializer_Mutex \
354 EXCLUDES(android::audio_utils::Spatializer_Mutex) \
355 EXCLUDES_BELOW_Spatializer_Mutex
356
357 #define EXCLUDES_AUDIO_ALL \
358 EXCLUDES_Spatializer_Mutex
359
360 // --- End generated section
361
362 /**
363 * AudioMutexAttributes is a collection of types and constexpr configuration
364 * used for the Android audio mutex.
365 *
366 * A different AudioMutexAttributes configuration will instantiate a completely
367 * independent set of mutex strategies, statics and thread locals,
368 * for a different type of mutexes.
369 */
370
371 class AudioMutexAttributes {
372 public:
373 // Order types, name arrays.
374 using order_t = MutexOrder;
375 static constexpr auto& order_names_ = gMutexNames;
376 static constexpr size_t order_size_ = static_cast<size_t>(MutexOrder::kSize);
377 static constexpr order_t order_default_ = MutexOrder::kOtherMutex;
378
379 // verify order information
380 static_assert(std::size(order_names_) == order_size_);
381 static_assert(static_cast<size_t>(order_default_) < order_size_);
382
383 // Set mutex_tracking_enabled_ to true to enable mutex
384 // statistics and debugging (order checking) features.
385 static constexpr bool mutex_tracking_enabled_ = true;
386
387 // Control the depth of the mutex stack per thread (the mutexes
388 // we track). Set this to the maximum expected
389 // number of mutexes held by a thread. If the depth is too small,
390 // deadlock detection, order checking, and recursion checking
391 // may result in a false negative. This is a static configuration
392 // because reallocating memory for the stack requires a lock for
393 // the reader.
394 static constexpr size_t mutex_stack_depth_ = 16;
395
396 // Enable or disable log always fatal.
397 // This also requires the mutex feature flag to be set.
398 static constexpr bool abort_on_order_check_ = true;
399 static constexpr bool abort_on_recursion_check_ = true;
400 static constexpr bool abort_on_invalid_unlock_ = true;
401 };
402
403 // relaxed_atomic implements the same features as std::atomic<T> but using
404 // std::memory_order_relaxed as default.
405 //
406 // This is the minimum consistency for the multiple writer multiple reader case.
407
408 template <typename T>
409 class relaxed_atomic : private std::atomic<T> {
410 public:
411 constexpr relaxed_atomic(T desired = {}) : std::atomic<T>(desired) {}
T()412 operator T() const { return std::atomic<T>::load(std::memory_order_relaxed); }
413 T operator=(T desired) {
414 std::atomic<T>::store(desired, std::memory_order_relaxed); return desired;
415 }
416
417 T operator--() { return std::atomic<T>::fetch_sub(1, std::memory_order_relaxed) - 1; }
418 T operator++() { return std::atomic<T>::fetch_add(1, std::memory_order_relaxed) + 1; }
419 T operator+=(const T value) {
420 return std::atomic<T>::fetch_add(value, std::memory_order_relaxed) + value;
421 }
422
423 T load(std::memory_order order = std::memory_order_relaxed) const {
424 return std::atomic<T>::load(order);
425 }
426 T fetch_add(T arg, std::memory_order order =std::memory_order_relaxed) {
427 return std::atomic<T>::fetch_add(arg, order);
428 }
429 bool compare_exchange_weak(
430 T& expected, T desired, std::memory_order order = std::memory_order_relaxed) {
431 return std::atomic<T>::compare_exchange_weak(expected, desired, order);
432 }
433 };
434
435 // unordered_atomic implements data storage such that memory reads have a value
436 // consistent with a memory write in some order, i.e. not having values
437 // "out of thin air".
438 //
439 // Unordered memory reads and writes may not actually take place but be implicitly cached.
440 // Nevertheless, a memory read should return at least as contemporaneous a value
441 // as the last memory write before the write thread memory barrier that
442 // preceded the most recent read thread memory barrier.
443 //
444 // This is weaker than relaxed_atomic and has no equivalent C++ terminology.
445 // unordered_atomic would be used for a single writer, multiple reader case,
446 // where data access of type T would be a implemented by the compiler and
447 // hw architecture with a single "uninterruptible" memory operation.
448 // (The current implementation holds true for general realized CPU architectures).
449 // Note that multiple writers would cause read-modify-write unordered_atomic
450 // operations to have inconsistent results.
451 //
452 // unordered_atomic is implemented with normal operations such that compiler
453 // optimizations can take place which would otherwise be discouraged for atomics.
454 // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0062r1.html
455
456 // VT may be volatile qualified, if desired, or a normal arithmetic type.
457 template <typename VT>
458 class unordered_atomic {
459 using T = std::decay_t<VT>;
460 static_assert(std::atomic<T>::is_always_lock_free);
461 public:
t_(desired)462 constexpr unordered_atomic(T desired = {}) : t_(desired) {}
T()463 operator T() const { return t_; }
464 T operator=(T desired) { t_ = desired; return desired; }
465
466 // a volatile ++t_ or t_ += 1 is deprecated in C++20.
467 T operator--() { return operator=(t_ - 1); }
468 T operator++() { return operator=(t_ + 1); }
469 T operator+=(const T value) { return operator=(t_ + value); }
470
471 T load(std::memory_order order = std::memory_order_relaxed) const { (void)order; return t_; }
472
473 private:
474 VT t_;
475 };
476
477 inline constexpr pid_t kInvalidTid = -1;
478
479 // While std::atomic with the default std::memory_order_seq_cst
480 // access could be used, it results in performance loss over less
481 // restrictive memory access.
482
483 // stats_atomic is a multiple writer multiple reader object.
484 //
485 // This is normally used to increment statistics counters on
486 // mutex priority categories.
487 //
488 // We used relaxed_atomic instead of std::atomic/memory_order_seq_cst here.
489 template <typename T>
490 using stats_atomic = relaxed_atomic<T>;
491
492 // thread_atomic is a single writer multiple reader object.
493 //
494 // This is normally accessed as a thread local (hence single writer)
495 // but may be accessed (rarely) by multiple readers on deadlock
496 // detection which does not modify the data.
497 //
498 // We use unordered_atomic instead of std::atomic/memory_order_seq_cst here.
499 template <typename T>
500 using thread_atomic = unordered_atomic<T>;
501
compiler_memory_barrier()502 inline void compiler_memory_barrier() {
503 // Reads or writes are not migrated or cached by the compiler across this barrier.
504 asm volatile("" ::: "memory");
505
506 // if not using gnu / clang, compare with compiler-only barrier generated by
507 // std::atomic_signal_fence(std::memory_order_seq_cst);
508 // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0124r7.html
509 }
510
511 // The mutex locking is thread-safe.
512 //
513 // However, the mutex metadata (statistics and thread info) updates are not locked
514 // by an internal mutex for efficiency reasons. Instead, they use atomics, with
515 // the possibility of false negatives since they are not sampled synchronously.
516 //
517 // To prevent the compiler from excessively caching the statistics and thread metadata
518 // which makes this asynchronous atomic sampling worse, as unordered or relaxed atomics
519 // do not implicitly impose any memory barriers,
520 // we can elect to explicitly issue compiler memory barriers to ensure
521 // metadata visibility across threads. This is optional, and only useful if
522 // the compiler does aggressive inlining.
523 //
metadata_memory_barrier_if_needed()524 inline void metadata_memory_barrier_if_needed() {
525 // check the level of atomicity used for thread metadata to alter the
526 // use of a barrier here.
527 if constexpr (std::is_same_v<thread_atomic<int32_t>, unordered_atomic<int32_t>>
528 || std::is_same_v<thread_atomic<int32_t>, relaxed_atomic<int32_t>>) {
529 compiler_memory_barrier();
530 }
531 }
532
533 /**
534 * Helper method to accumulate floating point values to an atomic
535 * prior to C++23 support of atomic<float> atomic<double> accumulation.
536 */
537 template <typename AccumulateType, typename ValueType>
538 requires std::is_floating_point<AccumulateType>::value
539 void atomic_add_to(std::atomic<AccumulateType> &dst, ValueType src,
540 std::memory_order order = std::memory_order_seq_cst) {
541 static_assert(std::atomic<AccumulateType>::is_always_lock_free);
542 AccumulateType expected;
543 do {
544 expected = dst;
545 } while (!dst.compare_exchange_weak(expected, expected + src, order));
546 }
547
548 template <typename AccumulateType, typename ValueType>
549 requires std::is_integral<AccumulateType>::value
550 void atomic_add_to(std::atomic<AccumulateType> &dst, ValueType src,
551 std::memory_order order = std::memory_order_seq_cst) {
552 dst.fetch_add(src, order);
553 }
554
555 template <typename AccumulateType, typename ValueType>
556 requires std::is_floating_point<AccumulateType>::value
557 void atomic_add_to(relaxed_atomic<AccumulateType> &dst, ValueType src,
558 std::memory_order order = std::memory_order_relaxed) {
559 AccumulateType expected;
560 do {
561 expected = dst;
562 } while (!dst.compare_exchange_weak(expected, expected + src, order));
563 }
564
565 template <typename AccumulateType, typename ValueType>
566 requires std::is_integral<AccumulateType>::value
567 void atomic_add_to(relaxed_atomic<AccumulateType> &dst, ValueType src,
568 std::memory_order order = std::memory_order_relaxed) {
569 dst.fetch_add(src, order);
570 }
571
572 template <typename AccumulateType, typename ValueType>
573 void atomic_add_to(unordered_atomic<AccumulateType> &dst, ValueType src,
574 std::memory_order order = std::memory_order_relaxed) {
575 (void)order; // unused
576 dst = dst + src;
577 }
578
579 /**
580 * mutex_stat is a struct composed of atomic members associated
581 * with usage of a particular mutex order.
582 *
583 * Access of a snapshot of this does not have a global lock, so the reader
584 * may experience temporal shear. Use of this by a different reader thread
585 * is for informative purposes only.
586 */
587
588 // CounterType == uint64_t, AccumulatorType == double
589 template <typename CounterType, typename AccumulatorType>
590 struct mutex_stat {
591 static_assert(std::is_floating_point_v<AccumulatorType>);
592 static_assert(std::is_integral_v<CounterType>);
593 static_assert(std::atomic<CounterType>::is_always_lock_free);
594 static_assert(std::atomic<AccumulatorType>::is_always_lock_free);
595 stats_atomic<CounterType> locks = 0; // number of times locked
596 stats_atomic<CounterType> unlocks = 0; // number of times unlocked
597 stats_atomic<CounterType> waits = 0; // number of locks that waited
598 stats_atomic<AccumulatorType> wait_sum_ns = 0.; // sum of time waited.
599 stats_atomic<AccumulatorType> wait_sumsq_ns = 0.; // sumsq of time waited.
600
601 template <typename WaitTimeType>
add_wait_timemutex_stat602 void add_wait_time(WaitTimeType wait_ns) {
603 AccumulatorType value_ns = wait_ns;
604 atomic_add_to(wait_sum_ns, value_ns);
605 atomic_add_to(wait_sumsq_ns, value_ns * value_ns);
606 }
607
to_stringmutex_stat608 std::string to_string() const {
609 CounterType uncontested = locks - waits;
610 AccumulatorType recip = waits == 0 ? 0. : 1. / waits;
611 AccumulatorType avg_wait_ms = waits == 0 ? 0. : wait_sum_ns * 1e-6 * recip;
612 AccumulatorType std_wait_ms = waits < 2 ? 0. :
613 std::sqrt(std::max(wait_sumsq_ns * recip * 1e-12 - avg_wait_ms * avg_wait_ms,
614 0.));
615 return std::string("locks: ").append(std::to_string(locks))
616 .append("\nuncontested: ").append(std::to_string(uncontested))
617 .append("\nwaits: ").append(std::to_string(waits))
618 .append("\nunlocks: ").append(std::to_string(unlocks))
619 .append("\navg_wait_ms: ").append(std::to_string(avg_wait_ms))
620 .append("\nstd_wait_ms: ").append(std::to_string(std_wait_ms))
621 .append("\n");
622 }
623 };
624
625 /**
626 * atomic_stack is a single writer, multiple reader object.
627 * Readers not on the same thread as the writer may experience temporal shear,
628 * but individual members are accessed atomic-safe, i.e. no partial member
629 * reads or delayed writes due to caching.
630 *
631 * For use with mutex checking, the atomic_stack maintains an ordering on
632 * P (payload) such that the top item pushed must always be greater than or
633 * equal to the P (payload) of items below it.
634 *
635 * Pushes always go to the top of the stack. Removes can occur
636 * from any place in the stack, but typically near the top.
637 *
638 * The atomic_stack never reallocates beyond its fixed capacity of N.
639 * This prevents a lockless reader from accessing invalid memory because
640 * the address region does not change.
641 *
642 * If the number of pushes exceed the capacity N, then items may be discarded.
643 * In that case, the stack is a subset stack of the "true" unlimited
644 * capacity stack. Nevertheless, a subset of an ordered stack
645 * with items deleted is also ordered.
646 *
647 * The size() of the atomic_stack is the size of the subset stack of tracked items.
648 * The true_size() is the size of the number of items pushed minus the
649 * number of items removed (the "true" size if capacity were unlimited).
650 * Since the capacity() is constant the true_size() may include
651 * items we don't track except by count. If true_size() == size() then
652 * the subset stack is complete.
653 *
654 * In this single writer, multiple reader model, we could get away with
655 * memory_order_relaxed as the reader is purely informative,
656 * but we choose memory_order_seq_cst which imposes the most
657 * restrictions on the compiler (variable access reordering) and the
658 * processor (memory access reordering). This means operations take effect
659 * in the order written. However, this isn't strictly needed - as there is
660 * only one writer, a read-modify-write operation is safe (no need for special
661 * memory instructions), and there isn't the acquire-release semantics with
662 * non-atomic memory access needed for a lockless fifo, for example.
663 */
664
665 /*
666 * For audio mutex purposes, one question arises - why don't we use
667 * a bitmask to represent the capabilities taken by a thread
668 * instead of a stack?
669 *
670 * A bitmask arrangement works if there exists a one-to-one relationship
671 * from a physical mutex to its capability. That may exist for some
672 * projects, but not AudioFlinger.
673 *
674 * As a consequence, we need the actual count and handle:
675 *
676 * 1) A single thread may hold multiple instances of some capabilities
677 * (e.g. ThreadBase_Mutex and EffectChain_Mutex).
678 * For example there may be multiple effect chains locked during mixing.
679 * There may be multiple PlaybackThreads locked during effect chain movement.
680 * A bit per capability can't count beyond 1.
681 *
682 * 2) Deadlock detection requires tracking the actual MutexHandle (a void*)
683 * to form a cycle, because there may be many mutexes associated with a
684 * given capability order.
685 * For example, each PlaybackThread or RecordThread will have its own mutex
686 * with the ThreadBase_Mutex capability.
687 *
688 */
689
690 template <typename Item, typename Payload, size_t N>
691 class atomic_stack {
692 public:
693 using item_payload_pair_t = std::pair<thread_atomic<Item>, thread_atomic<Payload>>;
694
695 /**
696 * Puts the item at the top of the stack.
697 *
698 * If the stack depth is exceeded the item
699 * replaces the top.
700 *
701 * Mutexes when locked are always placed on the top of the stack;
702 * however, they may be unlocked in a non last-in-first-out (LIFO)
703 * order. It is rare to see a non LIFO order, but it can happen.
704 */
push(const Item & item,const Payload & payload)705 void push(const Item& item, const Payload& payload) {
706 size_t location = top_;
707 size_t increment = 1;
708 if (location >= N) {
709 // we exceed the top of stack.
710 //
711 // although we could ignore this item (subset is the oldest),
712 // the better solution is to replace the topmost entry as
713 // it allows quicker removal.
714 location = N - 1;
715 increment = 0;
716 }
717 // issue the operations close together.
718 pairs_[location].first = item;
719 pairs_[location].second = payload;
720 ++true_top_;
721 top_ += increment;
722 }
723
724 /**
725 * Removes the item which is expected at the top of the stack
726 * but may be lower. Mutexes are generally unlocked in stack
727 * order (LIFO), but this is not a strict requirement.
728 */
remove(const Item & item)729 bool remove(const Item& item) {
730 if (true_top_ == 0) {
731 return false; // cannot remove.
732 }
733 // there is a temporary benign read race here where true_top_ != top_.
734 --true_top_;
735 for (size_t i = top_; i > 0; ) {
736 if (item == pairs_[--i].first) {
737 // We shift to preserve order.
738 // A reader may temporarily see a "duplicate" entry
739 // but that is preferable to a "missing" entry
740 // for the purposes of deadlock detection.
741 const size_t limit = top_ - 1;
742 while (i < limit) { // using atomics, we need to assign first, second separately.
743 pairs_[i].first = pairs_[i + 1].first.load();
744 pairs_[i].second = pairs_[i + 1].second.load();
745 ++i;
746 }
747 --top_; // now we restrict our range.
748 // on relaxed semantics, it might be better to clear out the last
749 // pair, but we are seq_cst.
750 return true;
751 }
752 }
753 // not found in our subset.
754 //
755 // we return true upon correct removal (true_top_ must always be >= top_).
756 if (true_top_ >= top_) return true;
757
758 // else recover and return false to notify that removal was invalid.
759 true_top_ = top_.load();
760 return false;
761 }
762
763 /**
764 * return the top of our atomic subset stack
765 * or the invalid_ (zero-initialized) entry if it doesn't exist.
766 */
767 // Consideration of using std::optional<> is a possibility
768 // but as std::atomic doesn't have a copy ctor (and does not make sense),
769 // we would want to directly return an optional on the non-atomic values,
770 // in a custom pair.
771 const item_payload_pair_t& top(size_t offset = 0) const {
772 const ssize_t top = static_cast<ssize_t>(top_) - static_cast<ssize_t>(offset);
773 if (top > 0 && top <= static_cast<ssize_t>(N)) return pairs_[top - 1];
774 return invalid_; // we don't know anything.
775 }
776
777 /**
778 * return the bottom (or base) of our atomic subset stack
779 * or the invalid_ (zero-initialized) entry if it doesn't exist.
780 */
781 const item_payload_pair_t& bottom(size_t offset = 0) const {
782 if (offset < top_) return pairs_[offset];
783 return invalid_; // we don't know anything.
784 }
785
786 /**
787 * prints the contents of the stack starting from the most recent first.
788 *
789 * If the thread is not the same as the writer thread, there could be
790 * temporal shear in the data printed.
791 */
to_string()792 std::string to_string() const {
793 std::string s("size: ");
794 s.append(std::to_string(size()))
795 .append(" true_size: ").append(std::to_string(true_size()))
796 .append(" items: [");
797 for (size_t i = 0; i < top_; ++i) {
798 s.append("{ ")
799 .append(std::to_string(reinterpret_cast<uintptr_t>(pairs_[i].first.load())))
800 .append(", ")
801 .append(std::to_string(static_cast<size_t>(pairs_[i].second.load())))
802 .append(" } ");
803 }
804 s.append("]");
805 return s;
806 }
807
808 /*
809 * stack configuration
810 */
capacity()811 static consteval size_t capacity() { return N; }
true_size()812 size_t true_size() const { return true_top_; }
size()813 size_t size() const { return top_; }
invalid()814 const auto& invalid() const { return invalid_; }
815
816 private:
817 thread_atomic<size_t> top_ = 0; // ranges from 0 to N - 1
818 thread_atomic<size_t> true_top_ = 0; // always >= top_.
819 // if true_top_ == top_ the subset stack is complete.
820
821 /*
822 * The subset stack entries are a pair of atomics rather than an atomic<pair>
823 * to prevent lock requirements if T and P are small enough, i.e. <= sizeof(size_t).
824 *
825 * As atomics are not composable from smaller atomics, there may be some
826 * temporary inconsistencies when reading from a different thread than the writer.
827 */
828 item_payload_pair_t pairs_[N]{};
829
830 /*
831 * The invalid pair is returned when top() is called without a tracked item.
832 * This might occur with an empty subset of the "true" stack.
833 */
834 static inline const item_payload_pair_t invalid_{}; // volatile != constexpr, if so qualified
835 };
836
837 // A list of reasons why we might have an inter-thread wait besides a mutex.
838 enum class other_wait_reason_t {
839 none = 0,
840 cv = 1,
841 join = 2,
842 queue = 3,
843 };
844
reason_to_string(other_wait_reason_t reason)845 inline constexpr const char* reason_to_string(other_wait_reason_t reason) {
846 switch (reason) {
847 case other_wait_reason_t::none: return "none";
848 case other_wait_reason_t::cv: return "cv";
849 case other_wait_reason_t::join: return "join";
850 case other_wait_reason_t::queue: return "queue";
851 default: return "invalid";
852 }
853 }
854
855 /**
856 * thread_mutex_info is a struct that is associated with every
857 * thread the first time a mutex is used on it. Writing will be through
858 * a single thread (essentially thread_local), but the thread_registry
859 * debug methods may access this through a different reader thread.
860 *
861 * If the thread does not use the audio_utils mutex, the allocation of this
862 * struct never occurs, although there is approx 16 bytes for a shared ptr and
863 * 1 byte for a thread local once bool.
864 *
865 * Here, we use for the MutexHandle a void*, which is used as an opaque unique ID
866 * representing the mutex.
867 *
868 * Since there is no global locking, the validity of the mutex* associated to
869 * the void* is unknown -- the mutex* could be deallocated in a different
870 * thread. Nevertheless the opaque ID can still be used to check deadlocks
871 * realizing there could be a false positive on a potential reader race
872 * where a new mutex is created at the same storage location.
873 */
874 template <typename MutexHandle, typename Order, size_t N>
875 class thread_mutex_info {
876 public:
877 using atomic_stack_t = atomic_stack<MutexHandle, Order, N>;
878
879 class other_wait_info {
880 public:
881 thread_atomic<pid_t> tid_ = kInvalidTid;
882 thread_atomic<other_wait_reason_t> reason_ = other_wait_reason_t::none;
883 thread_atomic<Order> order_ = (Order)-1;
884
to_string()885 std::string to_string() const {
886 const pid_t tid = tid_.load();
887 const other_wait_reason_t reason = reason_.load();
888 const Order order = order_.load();
889
890 std::string s;
891 if (tid != kInvalidTid) {
892 switch (reason) {
893 case other_wait_reason_t::none:
894 default:
895 break;
896 case other_wait_reason_t::cv:
897 s.append("cv_tid: ").append(std::to_string(tid))
898 .append(" cv_order: ").append(std::to_string(
899 static_cast<size_t>(order)));
900 break;
901 case other_wait_reason_t::join:
902 s.append("join_tid: ").append(std::to_string(tid));
903 break;
904 case other_wait_reason_t::queue:
905 s.append("queue_tid: ").append(std::to_string(tid));
906 break;
907 }
908 }
909 return s;
910 }
911 };
912
thread_mutex_info(pid_t tid)913 thread_mutex_info(pid_t tid) : tid_(tid) {}
914
915 // the destructor releases the thread_mutex_info.
916 // declared here, defined below due to use of thread_registry.
917 ~thread_mutex_info();
918
919 void reset_waiter(MutexHandle waiter = nullptr) {
920 mutex_wait_ = waiter;
921 }
922
923 /**
924 * check_held returns the stack pair that conflicts
925 * with the existing mutex handle and order, or the invalid
926 * stack pair (empty mutex handle and empty order).
927 */
928 const typename atomic_stack_t::item_payload_pair_t&
check_held(MutexHandle mutex,Order order)929 check_held(MutexHandle mutex, Order order) const {
930 // validate mutex order.
931 const size_t size = mutexes_held_.size();
932 for (size_t i = 0; i < size; ++i) {
933 const auto& top = mutexes_held_.top(i);
934 const auto top_order = top.second.load();
935
936 if (top_order < order) break; // ok
937 if (top_order > order) return top; // inverted order
938 if (top.first.load() == mutex) return top; // recursive mutex
939 }
940 return mutexes_held_.invalid();
941 }
942
943 /*
944 * This is unverified push. Use check_held() prior to this to
945 * verify no lock inversion or replication.
946 */
push_held(MutexHandle mutex,Order order)947 void push_held(MutexHandle mutex, Order order) {
948 mutexes_held_.push(mutex, order);
949 }
950
remove_held(MutexHandle mutex)951 bool remove_held(MutexHandle mutex) {
952 return mutexes_held_.remove(mutex);
953 }
954
955 // Variants used by condition_variable on wait() that handle
956 // hint metadata. This is used by deadlock detection algorithm to inform we
957 // are waiting on a worker thread identified by notifier_tid.
958
push_held_for_cv(MutexHandle mutex,Order order)959 void push_held_for_cv(MutexHandle mutex, Order order) {
960 push_held(mutex, order);
961 // condition wait has expired. always invalidate.
962 other_wait_info_.tid_ = kInvalidTid;
963 }
964
remove_held_for_cv(MutexHandle mutex,Order order,pid_t notifier_tid)965 bool remove_held_for_cv(MutexHandle mutex, Order order, pid_t notifier_tid) {
966 // last condition on the mutex overwrites.
967 other_wait_info_.order_ = order;
968 other_wait_info_.reason_ = other_wait_reason_t::cv;
969 other_wait_info_.tid_ = notifier_tid;
970 return remove_held(mutex);
971 }
972
973 // Add waiting state for join.
add_wait_join(pid_t waiting_tid)974 void add_wait_join(pid_t waiting_tid) {
975 other_wait_info_.reason_ = other_wait_reason_t::join;
976 other_wait_info_.tid_ = waiting_tid;
977 }
978
remove_wait_join()979 void remove_wait_join() {
980 other_wait_info_.tid_ = kInvalidTid;
981 }
982
983 // Add waiting state for queue.
add_wait_queue(pid_t waiting_tid)984 void add_wait_queue(pid_t waiting_tid) {
985 other_wait_info_.reason_ = other_wait_reason_t::queue;
986 other_wait_info_.tid_ = waiting_tid;
987 }
988
remove_wait_queue()989 void remove_wait_queue() {
990 other_wait_info_.tid_ = kInvalidTid;
991 }
992
993 /*
994 * Due to the fact that the thread_mutex_info contents are not globally locked,
995 * there may be temporal shear. The string representation is
996 * informative only.
997 */
to_string()998 std::string to_string() const {
999 std::string s;
1000 s.append("tid: ").append(std::to_string(static_cast<int>(tid_)));
1001 s.append("\nwaiting: ").append(std::to_string(
1002 reinterpret_cast<uintptr_t>(mutex_wait_.load())));
1003 // inform if there is a condition variable wait associated with a known thread.
1004 if (other_wait_info_.tid_ != kInvalidTid) {
1005 s.append("\n").append(other_wait_info_.to_string());
1006 }
1007 s.append("\nheld: ").append(mutexes_held_.to_string());
1008 return s;
1009 }
1010
1011 /*
1012 * empty() indicates that the thread is not waiting for or
1013 * holding any mutexes.
1014 */
empty()1015 bool empty() const {
1016 return mutex_wait_ == nullptr && mutexes_held_.size() == 0;
1017 }
1018
stack()1019 const auto& stack() const {
1020 return mutexes_held_;
1021 }
1022
1023 const pid_t tid_; // me
1024 thread_atomic<MutexHandle> mutex_wait_{}; // mutex waiting for
1025 other_wait_info other_wait_info_;
1026 atomic_stack_t mutexes_held_; // mutexes held
1027 };
1028
1029
1030 /**
1031 * deadlock_info_t encapsulates the mutex wait / cycle information from
1032 * thread_registry::deadlock_detection().
1033 *
1034 * If a cycle is detected, the last element of the vector chain represents
1035 * a tid that is repeated somewhere earlier in the vector.
1036 */
1037 struct deadlock_info_t {
1038 public:
deadlock_info_tdeadlock_info_t1039 explicit deadlock_info_t(pid_t tid_param) : tid(tid_param) {}
1040
emptydeadlock_info_t1041 bool empty() const {
1042 return chain.empty();
1043 }
1044
to_stringdeadlock_info_t1045 std::string to_string() const {
1046 std::string description;
1047
1048 if (has_cycle) {
1049 description.append("mutex cycle found (last tid repeated) ");
1050 } else {
1051 description.append("mutex wait chain ");
1052 }
1053 description.append("[ ").append(std::to_string(tid));
1054 // Note: when we dump here, we add the timeout tid to the start of the wait chain.
1055 for (const auto& [ tid2, name ] : chain) {
1056 description.append(", ").append(std::to_string(tid2))
1057 .append(" (by ").append(name).append(")");
1058 }
1059 description.append(" ]");
1060 return description;
1061 }
1062
1063 const pid_t tid; // tid for which the deadlock was checked
1064 bool has_cycle = false; // true if there is a cycle detected
1065 other_wait_reason_t other_wait_reason = other_wait_reason_t::none;
1066 std::vector<std::pair<pid_t, std::string>> chain; // wait chain of tids and mutexes.
1067 };
1068
1069 /**
1070 * The thread_registry is a thread-safe locked structure that
1071 * maintains a list of the threads that contain thread_mutex_info.
1072 *
1073 * Only first mutex access from a new thread and the destruction of that
1074 * thread will trigger an access to the thread_registry map.
1075 *
1076 * The debug methods to_string() and deadlock_detection() will also lock the struct
1077 * long enough to copy the map and safely obtain the weak pointers,
1078 * and then deal with the thread local data afterwards.
1079 *
1080 * It is recommended to keep a static singleton of the thread_registry for the
1081 * type desired. The singleton should be associated properly with the object
1082 * it should be unique for, which in this case is the mutex_impl template.
1083 * This enables access to the elements as needed.
1084 */
1085 template <typename ThreadInfo>
1086 class thread_registry {
1087 public:
add_to_registry(const std::shared_ptr<ThreadInfo> & tminfo)1088 bool add_to_registry(const std::shared_ptr<ThreadInfo>& tminfo) EXCLUDES(mutex_) {
1089 ALOGV("%s: registered for %d", __func__, tminfo->tid_);
1090 std::lock_guard l(mutex_);
1091 if (registry_.count(tminfo->tid_) > 0) {
1092 ALOGW_IF("%s: tid %d already exists", __func__, tminfo->tid_);
1093 return false;
1094 }
1095 registry_[tminfo->tid_] = tminfo;
1096 return true;
1097 }
1098
remove_from_registry(pid_t tid)1099 bool remove_from_registry(pid_t tid) EXCLUDES(mutex_) {
1100 ALOGV("%s: unregistered for %d", __func__, tid);
1101 std::lock_guard l(mutex_);
1102 // don't crash here because it might be a test app.
1103 const bool success = registry_.erase(tid) == 1;
1104 ALOGW_IF(!success, "%s: Cannot find entry for tid:%d", __func__, tid);
1105 return success;
1106 }
1107
1108 // Returns a std::unordered_map for easy access on tid.
copy_map()1109 auto copy_map() EXCLUDES(mutex_) {
1110 std::lock_guard l(mutex_);
1111 return registry_;
1112 }
1113
1114 // Returns a std::map sorted on tid for easy debug reading.
copy_ordered_map()1115 auto copy_ordered_map() EXCLUDES(mutex_) {
1116 std::lock_guard l(mutex_);
1117 std::map<pid_t, std::weak_ptr<ThreadInfo>> sorted(registry_.begin(), registry_.end());
1118 return sorted;
1119 }
1120
1121 /**
1122 * Returns a string containing the thread mutex info for each
1123 * thread that has accessed the audio_utils mutex.
1124 */
to_string()1125 std::string to_string() {
1126 // for debug purposes it is much easier to see the tids in numeric order.
1127 const auto registry_map = copy_ordered_map();
1128 ALOGV("%s: dumping tids: %zu", __func__, registry_map.size());
1129 std::string s("thread count: ");
1130 s.append(std::to_string(registry_map.size())).append("\n");
1131
1132 std::vector<pid_t> empty;
1133 for (const auto& [tid, weak_info] : registry_map) {
1134 const auto info = weak_info.lock();
1135 if (info) {
1136 if (info->empty()) {
1137 empty.push_back(tid);
1138 } else {
1139 s.append(info->to_string()).append("\n");
1140 }
1141 }
1142 }
1143
1144 // dump remaining empty tids out
1145 s.append("tids without current activity [ ");
1146 for (const auto tid : empty) {
1147 s.append(std::to_string(tid)).append(" ");
1148 }
1149 s.append("]\n");
1150 return s;
1151 }
1152
1153 /**
1154 * Returns the thread info for a pid_t.
1155 *
1156 * It should use a copy of the registry map which is not changing
1157 * as it does not take any lock.
1158 */
tid_to_info(const std::unordered_map<pid_t,std::weak_ptr<ThreadInfo>> & registry_map,pid_t tid)1159 static std::shared_ptr<ThreadInfo> tid_to_info(
1160 const std::unordered_map<pid_t, std::weak_ptr<ThreadInfo>>& registry_map,
1161 pid_t tid) {
1162 const auto it = registry_map.find(tid);
1163 if (it == registry_map.end()) return {};
1164 const auto& weak_info = it->second; // unmapped returns empty weak_ptr.
1165 return weak_info.lock();
1166 }
1167
1168 /**
1169 * Returns a deadlock_info_t struct describing the mutex wait / cycle information.
1170 *
1171 * The deadlock_detection() method is not exceptionally fast
1172 * and is not designed to be called for every mutex locked (and contended).
1173 * It is designed to run as a diagnostic routine to enhance
1174 * dumping for watchdogs, like TimeCheck, when a tid is believed blocked.
1175 *
1176 * Access of state is through atomics, so has minimal overhead on
1177 * concurrent execution, with the possibility of (mostly) false
1178 * negatives due to race.
1179 *
1180 * \param tid target tid which may be in a cycle or blocked.
1181 * \param mutex_names a string array of mutex names indexed on capability order.
1182 * \return a deadlock_info_t struct, which contains whether a cycle was found and
1183 * a vector of tids and mutex names in the mutex wait chain.
1184 */
1185 template <typename StringArray>
deadlock_detection(pid_t tid,const StringArray & mutex_names)1186 deadlock_info_t deadlock_detection(pid_t tid, const StringArray& mutex_names) {
1187 const auto registry_map = copy_map();
1188 deadlock_info_t deadlock_info{tid};
1189
1190 // if tid not waiting, return.
1191
1192 const auto tinfo_original_tid = tid_to_info(registry_map, tid);
1193 if (tinfo_original_tid == nullptr) return deadlock_info;
1194
1195 void* m = tinfo_original_tid->mutex_wait_.load();
1196 pid_t other_wait_tid = tinfo_original_tid->other_wait_info_.tid_.load();
1197 if (m == nullptr && other_wait_tid == kInvalidTid) return deadlock_info;
1198 other_wait_reason_t other_wait_reason =
1199 tinfo_original_tid->other_wait_info_.reason_.load();
1200 size_t other_wait_order =
1201 static_cast<size_t>(tinfo_original_tid->other_wait_info_.order_.load());
1202
1203 bool subset = false; // do we have missing mutex data per thread?
1204
1205 // Create helper map from mutex to tid.
1206 //
1207 // The helper map is built up from thread_local info rather than from
1208 // a global mutex list.
1209 //
1210 // There are multiple reasons behind this.
1211 // 1) There are many mutexes (mostly not held). We don't want to keep and
1212 // manage a "global" list of them.
1213 // 2) The mutex pointer itself may be deallocated from a different thread
1214 // from the reader. To keep it alive requires either a mutex, or a
1215 // weak_ptr to shared_ptr promotion.
1216 // Lifetime management is expensive on a per-mutex basis as there are many
1217 // of them, but cheaper on a per-thread basis as the threads are fewer.
1218 // 3) The thread_local lookup is very inexpensive for thread info (special
1219 // acceleration by C++ and the OS), but more complex for a mutex list
1220 // which at best is a static concurrent hash map.
1221 //
1222 // Note that the mutex_ptr handle is opaque -- it may be deallocated from
1223 // a different thread, so we use the tid from the thread registry map.
1224 //
1225 using pid_order_index_pair_t = std::pair<pid_t, size_t>;
1226 std::unordered_map<void*, pid_order_index_pair_t> mutex_to_tid;
1227 for (const auto& [tid2, weak_info] : registry_map) {
1228 const auto info = weak_info.lock();
1229 if (info == nullptr) continue;
1230 const auto& stack = info->mutexes_held_;
1231 static constinit size_t capacity = std::decay_t<decltype(stack)>::capacity();
1232 const size_t size = std::min(stack.size(), capacity);
1233 subset = subset || size != stack.true_size();
1234 for (size_t i = 0; i < size; ++i) {
1235 const auto& mutex_order_pair = stack.bottom(i);
1236 // if this method is not called by the writer thread
1237 // it is possible for data to change.
1238 const auto mutex_ptr = mutex_order_pair.first.load();
1239 const auto order = static_cast<size_t>(mutex_order_pair.second.load());
1240 if (mutex_ptr != nullptr) {
1241 mutex_to_tid[mutex_ptr] = pid_order_index_pair_t{tid2, order};
1242 }
1243 }
1244 }
1245 ALOGD_IF(subset, "%s: mutex info only subset, deadlock detection may be inaccurate",
1246 __func__);
1247
1248 // traverse from tid -> waiting mutex, then
1249 // mutex -> tid holding
1250 // until we get no more tids, or a tid cycle.
1251 std::unordered_set<pid_t> visited;
1252 visited.insert(tid); // mark the original tid, we start there for cycle detection.
1253 for (pid_t tid2 = tid; true;) {
1254 size_t order;
1255 other_wait_reason_t reason = other_wait_reason_t::none;
1256
1257 if (m != nullptr && mutex_to_tid.count(m)) {
1258 // waiting on mutex held by another tid.
1259 std::tie(tid2, order) = mutex_to_tid[m];
1260 } else if (other_wait_tid != kInvalidTid) {
1261 // condition variable waiting on tid.
1262 tid2 = other_wait_tid;
1263 order = other_wait_order;
1264 reason = other_wait_reason;
1265 deadlock_info.other_wait_reason = reason;
1266 } else {
1267 // no mutex or cv info.
1268 return deadlock_info;
1269 }
1270
1271 // add to chain.
1272 // if waiting through a condition variable, we prefix with "cv-".
1273 const auto name = order < std::size(mutex_names) ? mutex_names[order] : "unknown";
1274 deadlock_info.chain.emplace_back(tid2,
1275 reason == other_wait_reason_t::cv
1276 ? std::string("cv-").append(name).c_str()
1277 : reason == other_wait_reason_t::join ? "join"
1278 : reason == other_wait_reason_t::queue ? "queue" : name);
1279
1280 // cycle detected
1281 if (visited.count(tid2)) {
1282 deadlock_info.has_cycle = true;
1283 return deadlock_info;
1284 }
1285 visited.insert(tid2);
1286
1287 // if tid not waiting return (could be blocked on binder).
1288 const auto tinfo = tid_to_info(registry_map, tid2);
1289 if (tinfo == nullptr) {
1290 // thread may have disappeared.
1291 return deadlock_info;
1292 }
1293 m = tinfo->mutex_wait_.load();
1294 other_wait_tid = tinfo->other_wait_info_.tid_.load();
1295 other_wait_reason = tinfo->other_wait_info_.reason_.load();
1296 other_wait_order = static_cast<size_t>(tinfo->other_wait_info_.order_.load());
1297 }
1298 }
1299
1300 private:
1301 mutable std::mutex mutex_;
1302 std::unordered_map<pid_t, std::weak_ptr<ThreadInfo>> registry_ GUARDED_BY(mutex_);
1303 };
1304
1305 // audio_utils::mutex, audio_utils::lock_guard, audio_utils::unique_lock,
1306 // and audio_utils::condition_variable are method compatible versions
1307 // of std::mutex, std::lock_guard, std::unique_lock, and std::condition_variable
1308 // for optimizing audio thread performance and debugging.
1309 //
1310 // Note: we do not use std::timed_mutex as its Clang library implementation
1311 // is inefficient. One is better off making a custom timed implementation using
1312 // pthread_mutex_timedlock() on the mutex::native_handle().
1313
1314 extern bool mutex_get_enable_flag();
1315
1316 // Returns true if the mutex was locked within the timeout_ns.
1317 //
1318 // std::timed_mutex is implemented using a condition variable and doesn't
1319 // have complete thread safety annotations.
1320 //
1321 // Here, we add the flexibility of a timed lock on an existing std::mutex.
1322 //
std_mutex_timed_lock(std::mutex & m,int64_t timeout_ns)1323 inline bool std_mutex_timed_lock(std::mutex& m, int64_t timeout_ns) TRY_ACQUIRE(true, m) {
1324 const int64_t deadline_ns =
1325 safe_add_sat(timeout_ns, systemTime(SYSTEM_TIME_REALTIME));
1326 const struct timespec ts = {
1327 .tv_sec = static_cast<time_t>(deadline_ns / 1'000'000'000),
1328 .tv_nsec = static_cast<long>(deadline_ns % 1'000'000'000),
1329 };
1330 if (pthread_mutex_timedlock(m.native_handle(), &ts) != 0) {
1331 metadata_memory_barrier_if_needed();
1332 return false;
1333 }
1334 return true;
1335 }
1336
1337 template <typename Attributes>
1338 class CAPABILITY("mutex") [[nodiscard]] mutex_impl {
1339 public:
1340 using attributes_t = Attributes;
1341
1342 // We use composition here.
1343 // No copy/move ctors as the member std::mutex has it deleted.
1344
1345 // Constructor selects priority inheritance based on the platform default.
1346 mutex_impl(typename Attributes::order_t order = Attributes::order_default_)
mutex_impl(mutex_get_enable_flag (),order)1347 : mutex_impl(mutex_get_enable_flag(), order)
1348 {}
1349
1350 // Constructor selects priority inheritance based on input argument.
1351 mutex_impl(bool priority_inheritance,
1352 typename Attributes::order_t order = Attributes::order_default_)
order_(order)1353 : order_(order)
1354 , stat_{get_mutex_stat_array()[static_cast<size_t>(order)]}
1355 {
1356 LOG_ALWAYS_FATAL_IF(static_cast<size_t>(order) >= Attributes::order_size_,
1357 "mutex order %zu is equal to or greater than order limit:%zu",
1358 static_cast<size_t>(order), Attributes::order_size_);
1359
1360 if (!priority_inheritance) return;
1361
1362 pthread_mutexattr_t attr;
1363 int ret = pthread_mutexattr_init(&attr);
1364 if (ret != 0) {
1365 ALOGW("%s, pthread_mutexattr_init returned %d", __func__, ret);
1366 return;
1367 }
1368
1369 ret = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
1370 if (ret != 0) {
1371 ALOGW("%s, pthread_mutexattr_setprotocol returned %d", __func__, ret);
1372 return;
1373 }
1374
1375 // use of the native_handle() is implementation defined.
1376 const auto handle = m_.native_handle();
1377 ret = pthread_mutex_init(handle, &attr);
1378 if (ret != 0) {
1379 ALOGW("%s, pthread_mutex_init returned %d", __func__, ret);
1380 }
1381 ALOGV("%s: audio_mutex initialized: ret:%d order:%zu",
1382 __func__, ret, static_cast<size_t>(order_));
1383 }
1384
~mutex_impl()1385 ~mutex_impl() {
1386 // Note: std::mutex behavior is undefined if released holding ownership.
1387 }
1388
native_handle()1389 auto native_handle() {
1390 return m_.native_handle();
1391 }
1392
lock()1393 void lock() ACQUIRE() {
1394 lock_scoped_stat_t::pre_lock(*this);
1395 if (!m_.try_lock()) { // if we directly use futex, we can optimize this with m_.lock().
1396 // lock_scoped_stat_t accumulates waiting time for the mutex lock call.
1397 lock_scoped_stat_t ls(*this);
1398 m_.lock();
1399 }
1400 lock_scoped_stat_t::post_lock(*this);
1401 metadata_memory_barrier_if_needed();
1402 }
1403
unlock()1404 void unlock() RELEASE() {
1405 lock_scoped_stat_t::pre_unlock(*this);
1406 m_.unlock();
1407 metadata_memory_barrier_if_needed();
1408 }
1409
TRY_ACQUIRE(true)1410 bool try_lock(int64_t timeout_ns = 0) TRY_ACQUIRE(true) {
1411 lock_scoped_stat_t::pre_lock(*this);
1412 if (timeout_ns <= 0) {
1413 if (!m_.try_lock()) return false;
1414 } else {
1415 const int64_t deadline_ns =
1416 safe_add_sat(timeout_ns, systemTime(SYSTEM_TIME_REALTIME));
1417 const struct timespec ts = {
1418 .tv_sec = static_cast<time_t>(deadline_ns / 1'000'000'000),
1419 .tv_nsec = static_cast<long>(deadline_ns % 1'000'000'000),
1420 };
1421 lock_scoped_stat_t ls(*this);
1422 if (pthread_mutex_timedlock(m_.native_handle(), &ts) != 0) {
1423 ls.ignoreWaitTime(); // didn't get lock, don't count wait time
1424 metadata_memory_barrier_if_needed();
1425 return false;
1426 }
1427 }
1428 lock_scoped_stat_t::post_lock(*this);
1429 metadata_memory_barrier_if_needed();
1430 return true;
1431 }
1432
1433 // additional method to obtain the underlying std::mutex.
std_mutex()1434 std::mutex& std_mutex() {
1435 return m_;
1436 }
1437
1438 using mutex_stat_t = mutex_stat<uint64_t, double>;
1439
get_stat()1440 mutex_stat_t& get_stat() const {
1441 return stat_;
1442 }
1443
1444 /**
1445 * Returns the locking statistics per mutex capability category.
1446 */
all_stats_to_string()1447 static std::string all_stats_to_string() {
1448 std::string out("mutex stats: priority inheritance ");
1449 out.append(mutex_get_enable_flag() ? "enabled" : "disabled")
1450 .append("\n");
1451 const auto& stat_array = get_mutex_stat_array();
1452 for (size_t i = 0; i < stat_array.size(); ++i) {
1453 if (stat_array[i].locks != 0) {
1454 out.append("Capability: ").append(Attributes::order_names_[i]).append("\n")
1455 .append(stat_array[i].to_string());
1456 }
1457 }
1458 return out;
1459 }
1460
1461 /**
1462 * Returns the thread locks held per tid.
1463 */
all_threads_to_string()1464 static std::string all_threads_to_string() {
1465 return get_registry().to_string();
1466 }
1467
1468 /**
1469 * Returns a pair of bool (whether a cycle is detected) and a vector
1470 * of mutex wait dependencies.
1471 *
1472 * If a cycle is detected, the last element of the vector represents
1473 * a tid that is repeated somewhere earlier in the vector.
1474 *
1475 * The deadlock_detection() method is not exceptionally fast
1476 * and is not designed to be called for every mutex locked (and contended).
1477 * It is designed to run as a diagnostic routine to enhance
1478 * dumping for watchdogs, like TimeCheck, when a tid is believed blocked.
1479 *
1480 * Access of state is through atomics, so has minimal overhead on
1481 * concurrent execution, with the possibility of (mostly) false
1482 * negatives due to race.
1483 */
1484 static deadlock_info_t
deadlock_detection(pid_t tid)1485 deadlock_detection(pid_t tid) {
1486 return get_registry().deadlock_detection(tid, Attributes::order_names_);
1487 }
1488
1489 using thread_mutex_info_t = thread_mutex_info<
1490 void* /* mutex handle */, MutexOrder, Attributes::mutex_stack_depth_>;
1491
1492 // get_thread_mutex_info is a thread-local "singleton".
1493 //
1494 // We write it like a Meyer's singleton with a single thread_local
1495 // assignment that is guaranteed to be called on first time initialization.
1496 // Since the variables are thread_local, there is no thread contention
1497 // for initialization that would happen with a traditional Meyer's singleton,
1498 // so really a simple thread-local bool will do for a once_flag.
get_thread_mutex_info()1499 static const std::shared_ptr<thread_mutex_info_t>& get_thread_mutex_info() {
1500 thread_local std::shared_ptr<thread_mutex_info_t> tminfo = []() {
1501 auto info = std::make_shared<thread_mutex_info_t>(gettid_wrapper());
1502 get_registry().add_to_registry(info);
1503 return info;
1504 }();
1505 return tminfo;
1506 }
1507
1508 // helper class for registering statistics for a mutex lock.
1509
1510 class [[nodiscard]] lock_scoped_stat_enabled {
1511 public:
lock_scoped_stat_enabled(mutex & m)1512 explicit lock_scoped_stat_enabled(mutex& m)
1513 : mutex_(m)
1514 , time_(systemTime()) {
1515 ++mutex_.stat_.waits;
1516 mutex_.get_thread_mutex_info()->reset_waiter(&mutex_);
1517 }
1518
~lock_scoped_stat_enabled()1519 ~lock_scoped_stat_enabled() {
1520 if (!discard_wait_time_) mutex_.stat_.add_wait_time(systemTime() - time_);
1521 mutex_.get_thread_mutex_info()->reset_waiter();
1522 }
1523
ignoreWaitTime()1524 void ignoreWaitTime() {
1525 discard_wait_time_ = true;
1526 }
1527
pre_unlock(mutex & m)1528 static void pre_unlock(mutex& m) {
1529 ++m.stat_.unlocks;
1530 const bool success = m.get_thread_mutex_info()->remove_held(&m);
1531 LOG_ALWAYS_FATAL_IF(Attributes::abort_on_invalid_unlock_
1532 && !success,
1533 "%s: invalid mutex unlock when not previously held", __func__);
1534 }
1535
1536 // before we lock, we check order and recursion.
pre_lock(mutex & m)1537 static void pre_lock(mutex& m) {
1538 if constexpr (!Attributes::abort_on_order_check_ &&
1539 !Attributes::abort_on_recursion_check_) return;
1540
1541 const auto& p = m.get_thread_mutex_info()->check_held(&m, m.order_);
1542 if (p.first == nullptr) return; // no problematic mutex.
1543
1544 // problem!
1545 const size_t p_order = static_cast<size_t>(p.second.load());
1546 const size_t m_order = static_cast<size_t>(m.order_);
1547
1548 // lock inversion
1549 LOG_ALWAYS_FATAL_IF(Attributes::abort_on_order_check_
1550 && p_order > m_order,
1551 "%s: invalid mutex order (previous) %zu %s> (new) %zu %s",
1552 __func__, p_order, Attributes::order_names_[p_order],
1553 m_order, Attributes::order_names_[m_order]);
1554
1555 // lock recursion
1556 LOG_ALWAYS_FATAL_IF(Attributes::abort_on_recursion_check_
1557 && p_order == m_order,
1558 "%s: recursive mutex access detected (order: %zu %s)",
1559 __func__, p_order, Attributes::order_names_[p_order]);
1560 }
1561
post_lock(mutex & m)1562 static void post_lock(mutex& m) {
1563 ++m.stat_.locks;
1564 m.get_thread_mutex_info()->push_held(&m, m.order_);
1565 }
1566
1567 private:
1568 mutex& mutex_;
1569 const int64_t time_;
1570 bool discard_wait_time_ = false;
1571 };
1572
1573 // A RAII class that implements thread join wait detection
1574 // for the deadlock check.
1575 //
1576 // During the lifetime of this class object, the current thread
1577 // is assumed blocked on the thread tid due to a
1578 // thread join.
1579 //
1580 // {
1581 // scoped_join_wait_check sjw(tid_of_thread);
1582 // thread.join();
1583 // }
1584 //
1585
1586 class [[nodiscard]] scoped_join_wait_check {
1587 public:
scoped_join_wait_check(pid_t tid)1588 explicit scoped_join_wait_check(pid_t tid) {
1589 get_thread_mutex_info()->add_wait_join(tid);
1590 }
~scoped_join_wait_check()1591 ~scoped_join_wait_check() {
1592 get_thread_mutex_info()->remove_wait_join();
1593 }
1594 };
1595
1596 // A RAII class that implements queue wait detection
1597 // for the deadlock check.
1598 //
1599 // During the lifetime of this class object, the current thread
1600 // is assumed blocked on the thread tid due to a
1601 // cross-thread communication via a queue.
1602 //
1603 // {
1604 // scoped_queue_wait_check sjw(tid_of_thread);
1605 // queue.add(...);
1606 // }
1607 //
1608
1609 class [[nodiscard]] scoped_queue_wait_check {
1610 public:
scoped_queue_wait_check(pid_t tid)1611 explicit scoped_queue_wait_check(pid_t tid) {
1612 get_thread_mutex_info()->add_wait_queue(tid);
1613 }
~scoped_queue_wait_check()1614 ~scoped_queue_wait_check() {
1615 get_thread_mutex_info()->remove_wait_queue();
1616 }
1617 };
1618
1619 class lock_scoped_stat_disabled {
1620 public:
lock_scoped_stat_disabled(mutex &)1621 explicit lock_scoped_stat_disabled(mutex&) {}
1622
ignoreWaitTime()1623 void ignoreWaitTime() {}
1624
pre_unlock(mutex &)1625 static void pre_unlock(mutex&) {}
1626
pre_lock(mutex &)1627 static void pre_lock(mutex&) {}
1628
post_lock(mutex &)1629 static void post_lock(mutex&) {}
1630 };
1631
1632 using lock_scoped_stat_t = std::conditional_t<Attributes::mutex_tracking_enabled_,
1633 lock_scoped_stat_enabled, lock_scoped_stat_disabled>;
1634
1635 // helper class for registering statistics for a cv wait.
1636 class [[nodiscard]] cv_wait_scoped_stat_enabled {
1637 public:
1638 explicit cv_wait_scoped_stat_enabled(mutex& m, pid_t notifier_tid = kInvalidTid)
mutex_(m)1639 : mutex_(m) {
1640 ++mutex_.stat_.unlocks;
1641 // metadata that we relinquish lock.
1642 const bool success = mutex_.get_thread_mutex_info()->remove_held_for_cv(
1643 &mutex_, mutex_.order_, notifier_tid);
1644 LOG_ALWAYS_FATAL_IF(Attributes::abort_on_invalid_unlock_
1645 && !success,
1646 "%s: invalid mutex unlock when not previously held", __func__);
1647 }
1648
~cv_wait_scoped_stat_enabled()1649 ~cv_wait_scoped_stat_enabled() {
1650 ++mutex_.stat_.locks;
1651 // metadata that we are reacquiring lock.
1652 mutex_.get_thread_mutex_info()->push_held_for_cv(&mutex_, mutex_.order_);
1653 }
1654 private:
1655 mutex& mutex_;
1656 };
1657
1658 class [[nodiscard]] cv_wait_scoped_stat_disabled {
cv_wait_scoped_stat_disabled(mutex &)1659 explicit cv_wait_scoped_stat_disabled(mutex&) {}
1660 };
1661
1662 using cv_wait_scoped_stat_t = std::conditional_t<Attributes::mutex_tracking_enabled_,
1663 cv_wait_scoped_stat_enabled, cv_wait_scoped_stat_disabled>;
1664
1665 using thread_registry_t = thread_registry<thread_mutex_info_t>;
1666
1667 // One per-process thread registry, one instance per template typename.
1668 // Declared here but must be defined in a .cpp otherwise there will be multiple
1669 // instances if the header is included into different shared libraries.
1670 static thread_registry_t& get_registry();
1671
1672 using stat_array_t = std::array<mutex_stat_t, Attributes::order_size_>;
1673
1674 // One per-process mutex statistics array, one instance per template typename.
1675 // Declared here but must be defined in a .cpp otherwise there will be multiple
1676 // instances if the header is included into different shared libraries.
1677 static stat_array_t& get_mutex_stat_array();
1678
1679 private:
1680
1681 std::mutex m_;
1682 const typename Attributes::order_t order_;
1683 mutex_stat_t& stat_; // set in ctor
1684 };
1685
1686 // define the destructor to remove from registry.
1687 template <typename MutexHandle, typename Order, size_t N>
~thread_mutex_info()1688 inline thread_mutex_info<MutexHandle, Order, N>::~thread_mutex_info() {
1689 if (tid_ != 0) {
1690 mutex::get_registry().remove_from_registry(tid_);
1691 }
1692 }
1693
1694
1695 namespace details {
1696
1697 // Discovery of the audio_utils::mutex vs std::mutex.
1698 template<typename T>
requires(T & a)1699 concept IsAudioMutex = requires (T& a) {
1700 a.std_mutex(); // std::mutex does not have this method.
1701 };
1702
1703 } // details
1704
1705
1706 // audio_utils::lock_guard only works with the defined mutex.
1707 //
1708 // We add [[nodiscard]] to prevent accidentally ignoring construction.
1709 class [[nodiscard]] SCOPED_CAPABILITY lock_guard {
1710 public:
lock_guard(mutex & m)1711 explicit lock_guard(mutex& m) ACQUIRE(m)
1712 : mutex_(m) {
1713 mutex_.lock();
1714 }
1715
RELEASE()1716 ~lock_guard() RELEASE() {
1717 mutex_.unlock();
1718 }
1719
1720 lock_guard(const lock_guard&) = delete;
1721
1722 // Note: a member reference will also delete this.
1723 lock_guard& operator=(const lock_guard&) = delete;
1724
1725 private:
1726 mutex& mutex_;
1727 };
1728
1729 // audio_utils::unique_lock is based on std::unique_lock<std::mutex>
1730 // because std::condition_variable is optimized for std::unique_lock<std::mutex>
1731 //
1732 // Note: std::unique_lock **does not** have thread safety annotations.
1733 // We annotate correctly here. Essentially, this is the same as an annotated
1734 // using unique_lock = std::unique_lock<std::mutex>;
1735 //
1736 // We omit swap(), release() and move methods which don't have thread
1737 // safety annotations.
1738 //
1739 // We add [[nodiscard]] to prevent accidentally ignoring construction.
1740
1741 // The generic unique_lock. This works for std::mutex.
1742 template <typename Mutex>
1743 class [[nodiscard]] SCOPED_CAPABILITY unique_lock : public std::unique_lock<Mutex> {
1744 public:
unique_lock(Mutex & m)1745 explicit unique_lock(Mutex& m) ACQUIRE(m)
1746 : std::unique_lock<Mutex>(m) {}
RELEASE()1747 ~unique_lock() RELEASE() {}
1748
lock()1749 void lock() ACQUIRE() { std::unique_lock<Mutex>::lock(); }
unlock()1750 void unlock() RELEASE() { std::unique_lock<Mutex>::unlock(); }
1751
try_lock()1752 bool try_lock() TRY_ACQUIRE(true) { return std::unique_lock<Mutex>::try_lock(); }
1753
1754 template<class Rep, class Period>
try_lock_for(const std::chrono::duration<Rep,Period> & timeout_duration)1755 bool try_lock_for(const std::chrono::duration<Rep, Period>& timeout_duration)
1756 TRY_ACQUIRE(true) {
1757 return std::unique_lock<Mutex>::try_lock_for(timeout_duration);
1758 }
1759
1760 template<class Clock, class Duration>
try_lock_until(const std::chrono::time_point<Clock,Duration> & timeout_time)1761 bool try_lock_until(const std::chrono::time_point<Clock, Duration>& timeout_time)
1762 TRY_ACQUIRE(true) {
1763 return std::unique_lock<Mutex>::try_lock_until(timeout_time);
1764 }
1765 };
1766
1767 // Specialized unique_lock for the audio_utlis::mutex.
1768 //
1769 // the requires() clause selects this over the generic case upon match.
1770 //
1771 template <typename Mutex>
1772 requires details::IsAudioMutex<Mutex>
1773 class [[nodiscard]] SCOPED_CAPABILITY unique_lock<Mutex> {
1774 public:
unique_lock(Mutex & m)1775 explicit unique_lock(Mutex& m) ACQUIRE(m)
1776 : ul_(m.std_mutex(), std::defer_lock)
1777 , mutex_(m) {
1778 lock();
1779 }
1780
RELEASE()1781 ~unique_lock() RELEASE() {
1782 if (owns_lock()) unlock();
1783 }
1784
lock()1785 void lock() ACQUIRE() {
1786 mutex::lock_scoped_stat_t::pre_lock(mutex_);
1787 if (!ul_.try_lock()) {
1788 typename Mutex::lock_scoped_stat_t ls(mutex_);
1789 ul_.lock();
1790 }
1791 mutex::lock_scoped_stat_t::post_lock(mutex_);
1792 metadata_memory_barrier_if_needed();
1793 }
1794
unlock()1795 void unlock() RELEASE() {
1796 mutex::lock_scoped_stat_t::pre_unlock(mutex_);
1797 ul_.unlock();
1798 metadata_memory_barrier_if_needed();
1799 }
1800
try_lock()1801 bool try_lock() TRY_ACQUIRE(true) {
1802 mutex::lock_scoped_stat_t::pre_lock(mutex_);
1803 if (!ul_.try_lock()) return false;
1804 mutex::lock_scoped_stat_t::post_lock(mutex_);
1805 metadata_memory_barrier_if_needed();
1806 return true;
1807 }
1808
1809 template<class Rep, class Period>
try_lock_for(const std::chrono::duration<Rep,Period> & timeout_duration)1810 bool try_lock_for(const std::chrono::duration<Rep, Period>& timeout_duration)
1811 TRY_ACQUIRE(true) {
1812 mutex::lock_scoped_stat_t::pre_lock(mutex_);
1813 if (!ul_.try_lock_for(timeout_duration)) return false;
1814 mutex::lock_scoped_stat_t::post_lock(mutex_);
1815 metadata_memory_barrier_if_needed();
1816 return true;
1817 }
1818
1819 template<class Clock, class Duration>
try_lock_until(const std::chrono::time_point<Clock,Duration> & timeout_time)1820 bool try_lock_until(const std::chrono::time_point<Clock, Duration>& timeout_time)
1821 TRY_ACQUIRE(true) {
1822 mutex::lock_scoped_stat_t::pre_lock(mutex_);
1823 if (!ul_.try_lock_until(timeout_time)) return false;
1824 mutex::lock_scoped_stat_t::post_lock(mutex_);
1825 metadata_memory_barrier_if_needed();
1826 return true;
1827 }
1828
owns_lock()1829 bool owns_lock() const {
1830 return ul_.owns_lock();
1831 }
1832
1833 explicit operator bool() const {
1834 return owns_lock();
1835 }
1836
1837 // additional method to obtain the underlying std::unique_lock
std_unique_lock()1838 std::unique_lock<std::mutex>& std_unique_lock() {
1839 return ul_;
1840 }
1841
1842 // additional method to obtain the underlying mutex
native_mutex()1843 mutex& native_mutex() {
1844 return mutex_;
1845 }
1846
1847 private:
1848 std::unique_lock<std::mutex> ul_;
1849 mutex& mutex_;
1850 };
1851
1852 // audio_utils::condition_variable uses the optimized version of
1853 // std::condition_variable for std::unique_lock<std::mutex>
1854 // It is possible to use std::condition_variable_any for a generic mutex type,
1855 // but it is less efficient.
1856
1857 // The audio_utils condition_variable permits speicifying a "notifier_tid"
1858 // metadata in the wait() methods, which states the expected tid of the
1859 // notification thread for deadlock / wait detection purposes.
1860 class [[nodiscard]] condition_variable {
1861 public:
notify_one()1862 void notify_one() noexcept {
1863 cv_.notify_one();
1864 }
1865
notify_all()1866 void notify_all() noexcept {
1867 cv_.notify_all();
1868 }
1869
1870 template <typename Mutex>
1871 void wait(unique_lock<Mutex>& lock, pid_t notifier_tid = kInvalidTid) {
1872 typename Mutex::cv_wait_scoped_stat_t ws(lock.native_mutex(), notifier_tid);
1873 cv_.wait(lock.std_unique_lock());
1874 }
1875
1876 template<typename Mutex, typename Predicate>
1877 void wait(unique_lock<Mutex>& lock, Predicate stop_waiting, pid_t notifier_tid = kInvalidTid) {
1878 typename Mutex::cv_wait_scoped_stat_t ws(lock.native_mutex(), notifier_tid);
1879 cv_.wait(lock.std_unique_lock(), std::move(stop_waiting));
1880 }
1881
1882 template<typename Mutex, typename Rep, typename Period>
1883 std::cv_status wait_for(unique_lock<Mutex>& lock,
1884 const std::chrono::duration<Rep, Period>& rel_time,
1885 pid_t notifier_tid = kInvalidTid) {
1886 typename Mutex::cv_wait_scoped_stat_t ws(lock.native_mutex(), notifier_tid);
1887 return cv_.wait_for(lock.std_unique_lock(), rel_time);
1888 }
1889
1890 template<typename Mutex, typename Rep, typename Period, typename Predicate>
1891 bool wait_for(unique_lock<Mutex>& lock,
1892 const std::chrono::duration<Rep, Period>& rel_time,
1893 Predicate stop_waiting, pid_t notifier_tid = kInvalidTid) {
1894 typename Mutex::cv_wait_scoped_stat_t ws(lock.native_mutex(), notifier_tid);
1895 return cv_.wait_for(lock.std_unique_lock(), rel_time, std::move(stop_waiting));
1896 }
1897
1898 template<typename Mutex, typename Clock, typename Duration>
1899 std::cv_status wait_until(unique_lock<Mutex>& lock,
1900 const std::chrono::time_point<Clock, Duration>& timeout_time,
1901 pid_t notifier_tid = kInvalidTid) {
1902 typename Mutex::cv_wait_scoped_stat_t ws(lock.native_mutex(), notifier_tid);
1903 return cv_.wait_until(lock.std_unique_lock(), timeout_time);
1904 }
1905
1906 template<typename Mutex, typename Clock, typename Duration, typename Predicate>
1907 bool wait_until(unique_lock<Mutex>& lock,
1908 const std::chrono::time_point<Clock, Duration>& timeout_time,
1909 Predicate stop_waiting, pid_t notifier_tid = kInvalidTid) {
1910 typename Mutex::cv_wait_scoped_stat_t ws(lock.native_mutex(), notifier_tid);
1911 return cv_.wait_until(lock.std_unique_lock(), timeout_time, std::move(stop_waiting));
1912 }
1913
native_handle()1914 auto native_handle() {
1915 return cv_.native_handle();
1916 }
1917
1918 private:
1919 std::condition_variable cv_;
1920 };
1921
1922 // audio_utils::scoped_lock has proper thread safety annotations.
1923 // std::scoped_lock does not have thread safety annotations for greater than 1 lock
1924 // since the variadic template doesn't convert to the variadic macro def.
1925 //
1926 // We add [[nodiscard]] to prevent accidentally ignoring construction.
1927 template <typename ...Mutexes>
1928 class scoped_lock;
1929
1930 template <typename Mutex1>
1931 class [[nodiscard]] SCOPED_CAPABILITY scoped_lock<Mutex1>
1932 : private std::scoped_lock<Mutex1> {
1933 public:
scoped_lock(Mutex1 & m)1934 explicit scoped_lock(Mutex1& m) ACQUIRE(m) : std::scoped_lock<Mutex1>(m) {}
1935 ~scoped_lock() RELEASE() = default;
1936 };
1937
1938 template <typename Mutex1, typename Mutex2>
1939 class [[nodiscard]] SCOPED_CAPABILITY scoped_lock<Mutex1, Mutex2>
1940 : private std::scoped_lock<Mutex1, Mutex2> {
1941 public:
scoped_lock(Mutex1 & m1,Mutex2 & m2)1942 scoped_lock(Mutex1& m1, Mutex2& m2) ACQUIRE(m1, m2)
1943 : std::scoped_lock<Mutex1, Mutex2>(m1, m2) {}
1944 ~scoped_lock() RELEASE() = default;
1945 };
1946
1947 template <typename Mutex1, typename Mutex2, typename Mutex3>
1948 class [[nodiscard]] SCOPED_CAPABILITY scoped_lock<Mutex1, Mutex2, Mutex3>
1949 : private std::scoped_lock<Mutex1, Mutex2, Mutex3> {
1950 public:
scoped_lock(Mutex1 & m1,Mutex2 & m2,Mutex3 & m3)1951 scoped_lock(Mutex1& m1, Mutex2& m2, Mutex3& m3) ACQUIRE(m1, m2, m3)
1952 : std::scoped_lock<Mutex1, Mutex2, Mutex3>(m1, m2, m3) {}
1953 ~scoped_lock() RELEASE() = default;
1954 };
1955
1956 template <typename ...Mutexes>
1957 class [[nodiscard]] scoped_lock : private std::scoped_lock<Mutexes...> {
1958 public:
scoped_lock(Mutexes &...mutexes)1959 scoped_lock(Mutexes&... mutexes)
1960 : std::scoped_lock<Mutexes...>(mutexes...) {}
1961 };
1962
1963 // audio_utils::lock_guard_no_thread_safety_analysis is used to lock
1964 // the second mutex when the same global capability is aliased
1965 // to 2 (or more) different mutexes.
1966 //
1967 // Example usage:
1968 //
1969 // // Suppose the interface IAfThreadBase::mutex() returns a global capability
1970 // // ThreadBase_Mutex.
1971 //
1972 // sp<IAfThreadBase> srcThread, dstThread;
1973 //
1974 // lock_guard(srcThread->mutex()); // acquires global capability ThreadBase_Mutex;
1975 // ...
1976 // lock_guard_no_thread_safety_analysis( // lock_guard would fail here as
1977 // dstThread->mutex()); // the same global capability is assigned to
1978 // // dstThread->mutex().
1979 // // lock_guard_no_thread_safety_analysis
1980 // // prevents a thread safety error.
1981
1982 template<typename Mutex1>
1983 class lock_guard_no_thread_safety_analysis : private std::lock_guard<Mutex1> {
1984 public:
lock_guard_no_thread_safety_analysis(Mutex1 & m)1985 lock_guard_no_thread_safety_analysis(Mutex1& m) : std::lock_guard<Mutex1>(m) {}
1986 };
1987
1988 } // namespace android::audio_utils
1989
1990 #pragma pop_macro("LOG_TAG")
1991