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 #include <audio_utils/mutex.h>
18 #include <gtest/gtest.h>
19 
20 #include <thread>
21 
22 using namespace std::chrono_literals;
23 
24 // Currently tests mutex priority-inheritance (or not) based on flag
25 // adb shell setprop \
26 // persist.device_config.aconfig_flags.media_audio.\
27 // com.android.media.audio.flags.mutex_priority_inheritance true
28 //
29 // TODO(b/209491695) enable both PI/non-PI mutex tests regardless of flag.
30 
31 namespace android {
32 
33 namespace audio_locks {
34 
35 // Audio capabilities are typically assigned a partial order -
36 // but to furnish a proof of deadlock free audio, we create a global order
37 // (which isn't unique, just used to prove deadlock free access).
38 
39 // Clang thread-safety can assigns capabilities to mutex-like objects.
40 // Here we use pointers to audio_utils::mutex*, they can be nullptr (never allocated)
41 // because they are used solely as a capability declaration, not as a mutex
42 // instance.
43 //
44 // In this example, we have 4 capabilities, labeled cap1, cap2, cap3, cap4.
45 // We'll show later in the IContainer.h example how we assign
46 // capabilities to actual mutexes.
47 
48 // Add highest priority here
49 inline audio_utils::mutex* cap1;
50 inline audio_utils::mutex* cap2 ACQUIRED_AFTER(cap1);
51 inline audio_utils::mutex* cap3 ACQUIRED_AFTER(cap2);
52 inline audio_utils::mutex* cap4 ACQUIRED_AFTER(cap3);
53 // Add lowest priority here
54 
55 // Now ACQUIRED_AFTER() isn't implemented (yet) in Clang Thread-Safety.
56 // As a solution, we define priority exclusion for lock acquisition.
57 // if you lock at a capability n, then you cannot hold
58 // locks at a lower capability (n+1, n+2, ...) otherwise
59 // there is lock inversion.
60 
61 #define EXCLUDES_BELOW_4  // no capability below 4.
62 #define EXCLUDES_4 EXCLUDES(cap4) EXCLUDES_BELOW_4
63 
64 #define EXCLUDES_BELOW_3 EXCLUDES_4
65 #define EXCLUDES_3 EXCLUDES(cap3) EXCLUDES_BELOW_3
66 
67 #define EXCLUDES_BELOW_2 EXCLUDES_3
68 #define EXCLUDES_2 EXCLUDES(cap2) EXCLUDES_BELOW_2
69 
70 #define EXCLUDES_BELOW_1 EXCLUDES_2
71 #define EXCLUDES_1 EXCLUDES(cap1) EXCLUDES_BELOW_1
72 
73 #define EXCLUDES_ALL EXCLUDES_1
74 
75 }  // namespace audio_locks
76 
77 using namespace audio_locks;
78 // -----------------------------------------
79 
80 // Example IContainer.h
81 //
82 // This is a Container interface with multiple exposed mutexes.
83 // Since the capabilities file audio_locks.h is global,
84 // this interface can be used in projects outside of the implementing
85 // project.
86 
87 // Here RETURN_CAPABILITY is used to assign a capability to a mutex.
88 
89 class IContainer {
90 public:
91     virtual ~IContainer() = default;
92 
93     // This is an example of returning many mutexes for test purposes.
94     // In AudioFlinger interfaces, we may return mutexes for locking
95     // AudioFlinger_Mutex, AudioFlinger_ClientMutex, ThreadBase_Mutex, etc. for interface methods.
96     //
97     // We do not allow access to the mutex when holding a mutex of lower priority, so
98     // we use EXCLUDES_....
99     virtual audio_utils::mutex& mutex1() const RETURN_CAPABILITY(cap1) EXCLUDES_BELOW_1 = 0;
100     virtual audio_utils::mutex& mutex2() const RETURN_CAPABILITY(cap2) EXCLUDES_BELOW_2 = 0;
101     virtual audio_utils::mutex& mutex3() const RETURN_CAPABILITY(cap3) EXCLUDES_BELOW_3 = 0;
102 
103     // acquires capability 1, can't hold cap1 or lower level locks
104     virtual int value1() const EXCLUDES_1 = 0;
105 
106     virtual int value1_l() const REQUIRES(cap1) = 0;
107     virtual int value2_l() const REQUIRES(cap2) = 0;
108     virtual int value3_l() const REQUIRES(cap3) = 0;
109 
110     virtual int combo12_l() const REQUIRES(cap1) EXCLUDES_2 = 0;
111 
112     // As value1, value2, value3 access requires cap1, cap2, cap3 individually,
113     // combo123_lll() requires all three.
114     virtual int combo123_lll() const REQUIRES(cap1, cap2, cap3) = 0;
115 
116     // We cannot use any of mutex1, mutex2, mutex3, as they are acquired
117     // within the combo123() method.
118     // If we happen to know EXCLUDES_1 > EXCLUDES2 > EXCLUDES_3
119     // we could just use EXCLUDES_1.  We include all 3 here.
120     virtual int combo123() const EXCLUDES_1 EXCLUDES_2 EXCLUDES_3 = 0;
121 };
122 
123 // -----------------------------------------
124 //
125 // Example Container.cpp
126 //
127 // The container implemented the IContainer interface.
128 //
129 // We see here how the RETURN_CAPABILITY() is used to assign capability to mutexes.
130 
131 class Container : public IContainer {
132 public:
133     // Here we implement the mutexes that has the global capabilities.
mutex1() const134     audio_utils::mutex& mutex1() const override RETURN_CAPABILITY(cap1) EXCLUDES_BELOW_1 {
135         return mMutex1;
136     }
137 
mutex2() const138     audio_utils::mutex& mutex2() const override RETURN_CAPABILITY(cap2) EXCLUDES_BELOW_2 {
139         return mMutex2;
140     }
141 
mutex3() const142     audio_utils::mutex& mutex3() const override RETURN_CAPABILITY(cap3) EXCLUDES_BELOW_3 {
143         return mMutex3;
144     }
145 
146     // We use EXCLUDES_1 (which is prevents cap1 and all lesser priority mutexes)
147     // EXCLUDES(cap1) is not sufficient because if we acquire cap1,
148     // we ALSO can't hold lower level locks.
value1() const149     int value1() const override EXCLUDES_1 {
150 
151         // Locking is through mutex1() to get the proper capability.
152         audio_utils::lock_guard l(mutex1());
153         return value1_l();
154     }
value1_l() const155     int value1_l() const override REQUIRES(cap1) {
156         return v1_;
157     }
value2_l() const158     int value2_l() const override REQUIRES(cap2) {
159         return v2_;
160     }
value3_l() const161     int value3_l() const override REQUIRES(cap3)  {
162         return v3_;
163     }
164 
165     // This requires cap1, acquires cap2.
combo12_l() const166     int combo12_l() const override REQUIRES(cap1) EXCLUDES_2 {
167 
168         // Fails  return value1_l() + value2_l() + value3_l();
169         audio_utils::lock_guard l(mutex2());
170         return value1_l() + value2_l();
171     }
172 
173 #if 0
174     // fails!
175     int combo123_lll() REQUIRES(cap1, cap2, cap2) {
176         return value1_l() + value2_l() + value3_l();
177     }
178 #endif
179 
180     // We can use REQUIRES(cap1, cap2, cap3)
181     //         or REQUIRES(cap1, cap2, mutex3())
182     //
183     // The REQUIRES expression must be valid as the first line in the function body.
184     // This means that if the expression has visibility issues (accesses
185     // a private base class member from a derived class, etc.) it won't work.
186     // Quick test: Does a decltype(expr) work as the first line?
187     // If not, then REQUIRES(expr) won't either.
188     //
combo123_lll() const189     int combo123_lll() const override REQUIRES(cap1, cap2, mutex3()) {
190         return value1_l() + value2_l() + value3_l();
191     }
192 
193 #if 1
194     // In this example, the 3 exclusions are needed because we acquire
195     // 3 locks.  If we happen to know EXCLUDES_1 > EXCLUDES2 > EXCLUDES_3
196     // we could just use EXCLUDES_1.  We include all 3 here.
combo123() const197     int combo123() const override EXCLUDES_1 EXCLUDES_2 EXCLUDES_3 {
198         audio_utils::lock_guard l1(mutex1());
199         audio_utils::lock_guard l2(mutex2());
200         audio_utils::lock_guard l3(mutex3());
201 
202         return value1_l() + value2_l() + value3_l();
203     }
204 
205 #else
206     // THIS FAILS
combo123() const207     int combo123() const override EXCLUDES_1 EXCLUDES_2 EXCLUDES_3 {
208         audio_utils::lock_guard l2(mutex2());
209         audio_utils::lock_guard l1(mutex1());  // 2 is acquired before 1.
210         audio_utils::lock_guard l3(mutex3());
211 
212         return value1_l() + value2_l() + value3_l();
213     }
214 #endif
215 
216 private:
217     // The actual implementation mutexes are never directly exposed.
218     mutable audio_utils::mutex mMutex1;
219     mutable audio_utils::mutex mMutex2;
220     mutable audio_utils::mutex mMutex3;
221 
222     int v1_ GUARDED_BY(cap1) = 1;
223     int v2_ GUARDED_BY(mutex2()) = 2;
224     int v3_ GUARDED_BY(cap3) = 3;
225 };
226 
TEST(audio_mutex_tests,Container)227 TEST(audio_mutex_tests, Container) {
228     Container c;
229 
230     EXPECT_EQ(1, c.value1()); // success
231 
232 #if 0
233     // fails
234     {
235         audio_utils::lock_guard(c.mutex1());
236         EXPECT_EQ(3, c.combo12_l());
237     }
238 #endif
239 
240     {
241         audio_utils::lock_guard l(c.mutex1());
242         EXPECT_EQ(3, c.combo12_l()); // success
243     }
244 }
245 
246 // Test access through the IContainer interface -
247 // see that mutex checking is done without knowledge of
248 // the actual implementation.
249 
TEST(audio_mutex_tests,Interface)250 TEST(audio_mutex_tests, Interface) {
251     Container c;
252     IContainer *i = static_cast<IContainer*>(&c);
253 
254     EXPECT_EQ(1, i->value1()); // success
255 
256 #if 0
257     // fails
258     {
259         audio_utils::lock_guard(c.mutex1());
260         EXPECT_EQ(3, c.combo12_l());
261     }
262 #endif
263 
264     {
265         audio_utils::lock_guard l(i->mutex1());
266         EXPECT_EQ(3, i->combo12_l()); // success
267     }
268 
269     ALOGD("%s: %s", __func__, audio_utils::mutex::all_stats_to_string().c_str());
270 }
271 
TEST(audio_mutex_tests,Stack)272 TEST(audio_mutex_tests, Stack) {
273     android::audio_utils::atomic_stack<int, int, 2> as;
274 
275     // set up stack
276     EXPECT_EQ(0UL, as.size());
277     as.push(1, 10);
278     EXPECT_EQ(1UL, as.size());
279     as.push(2, 20);
280     EXPECT_EQ(2UL, as.size());
281 
282     // 3rd item exceeds the stack capacity.
283     as.push(3, 30);
284     // 2 items tracked (subset)
285     EXPECT_EQ(2UL, as.size());
286     // 3 items total.
287     EXPECT_EQ(3UL, as.true_size());
288 
289     const auto& bot = as.bottom();
290     const auto& top = as.top();
291 
292     // these are the 2 items tracked:
293     EXPECT_EQ(1, bot.first.load());
294     EXPECT_EQ(10, bot.second.load());
295 
296     EXPECT_EQ(3, top.first.load());
297     EXPECT_EQ(30, top.second.load());
298 
299     // remove the bottom item.
300     EXPECT_EQ(true, as.remove(1));
301     EXPECT_EQ(1UL, as.size());
302     EXPECT_EQ(2UL, as.true_size());
303 
304     // now remove the "virtual" item.
305     // (actually any non-existing item value works).
306     EXPECT_EQ(true, as.remove(2));
307     EXPECT_EQ(1UL, as.size());
308     EXPECT_EQ(1UL, as.true_size());
309 
310     // now an invalid removal
311     EXPECT_EQ(false, as.remove(5));
312     EXPECT_EQ(1UL, as.size());
313     EXPECT_EQ(1UL, as.true_size());
314 
315     // now remove the final item.
316     EXPECT_EQ(true, as.remove(3));
317     EXPECT_EQ(0UL, as.size());
318     EXPECT_EQ(0UL, as.true_size());
319 }
320 
TEST(audio_mutex_tests,RecursiveLockDetection)321 TEST(audio_mutex_tests, RecursiveLockDetection) {
322     constexpr pid_t pid = 0;  // avoid registry shutdown.
323     android::audio_utils::thread_mutex_info<int, int, 8 /* stack depth */> tmi(pid);
324 
325     // set up stack
326     tmi.push_held(50, 1);
327     tmi.push_held(40, 2);
328     tmi.push_held(30, 3);
329     EXPECT_EQ(3UL, tmi.stack().size());
330 
331     // remove bottom.
332     tmi.remove_held(50);
333     EXPECT_EQ(2UL, tmi.stack().size());
334 
335     // test recursive lock detection.
336 
337     // same order, same item is recursive.
338     const auto& recursive = tmi.check_held(30, 3);
339     EXPECT_EQ(30, recursive.first.load());
340     EXPECT_EQ(3, recursive.second.load());
341 
342     // same order but different item (10 != 30) is OK.
343     const auto& nil = tmi.check_held(10, 3);
344     EXPECT_EQ(0, nil.first.load());
345     EXPECT_EQ(0, nil.second.load());
346 }
347 
TEST(audio_mutex_tests,OrderDetection)348 TEST(audio_mutex_tests, OrderDetection) {
349     constexpr pid_t pid = 0;  // avoid registry shutdown.
350     android::audio_utils::thread_mutex_info<int, int, 8 /* stack depth */> tmi(pid);
351 
352     // set up stack
353     tmi.push_held(50, 1);
354     tmi.push_held(40, 2);
355     tmi.push_held(30, 3);
356     EXPECT_EQ(3UL, tmi.stack().size());
357 
358     // remove middle
359     tmi.remove_held(40);
360     EXPECT_EQ(2UL, tmi.stack().size());
361 
362     // test inversion detection.
363 
364     // lower order is a problem 1 < 3.
365     const auto& inversion = tmi.check_held(1, 1);
366     EXPECT_EQ(30, inversion.first.load());
367     EXPECT_EQ(3, inversion.second.load());
368 
369     // higher order is OK.
370     const auto& nil2 = tmi.check_held(4, 4);
371     EXPECT_EQ(0, nil2.first.load());
372     EXPECT_EQ(0, nil2.second.load());
373 }
374 
375 // The following tests are evaluated for the android::audio_utils::mutex
376 // Non-Priority Inheritance and Priority Inheritance cases.
377 
378 class MutexTestSuite : public testing::TestWithParam<bool> {};
379 
380 // Test that the mutex aborts on recursion (if the abort flag is set).
381 
TEST_P(MutexTestSuite,FatalRecursiveMutex)382 TEST_P(MutexTestSuite, FatalRecursiveMutex)
383 NO_THREAD_SAFETY_ANALYSIS {
384     if (!android::audio_utils::AudioMutexAttributes::abort_on_recursion_check_
385             || !audio_utils::mutex_get_enable_flag()) {
386         ALOGD("Test FatalRecursiveMutex skipped");
387         return;
388     }
389 
390     using Mutex = android::audio_utils::mutex;
391     using LockGuard = android::audio_utils::lock_guard;
392     const bool priority_inheritance = GetParam();
393 
394     Mutex m(priority_inheritance);
395     LockGuard lg(m);
396 
397     // Can't lock ourselves again.
398     ASSERT_DEATH(m.lock(), ".*recursive mutex.*");
399 }
400 
401 // Test that the mutex aborts on lock order inversion (if the abort flag is set).
402 
TEST_P(MutexTestSuite,FatalLockOrder)403 TEST_P(MutexTestSuite, FatalLockOrder)
404 NO_THREAD_SAFETY_ANALYSIS {
405     if (!android::audio_utils::AudioMutexAttributes::abort_on_order_check_
406             || !audio_utils::mutex_get_enable_flag()) {
407         ALOGD("Test FatalLockOrder skipped");
408         return;
409     }
410 
411     using Mutex = android::audio_utils::mutex;
412     using LockGuard = android::audio_utils::lock_guard;
413     const bool priority_inheritance = GetParam();
414 
415     Mutex m1{priority_inheritance, (android::audio_utils::AudioMutexAttributes::order_t)1};
416     Mutex m2{priority_inheritance, (android::audio_utils::AudioMutexAttributes::order_t)2};
417 
418     LockGuard lg2(m2);
419     // m1 must be locked before m2 as 1 < 2.
420     ASSERT_DEATH(m1.lock(), ".*mutex order.*");
421 }
422 
423 // Test that the mutex aborts on lock order inversion (if the abort flag is set).
424 
TEST_P(MutexTestSuite,UnexpectedUnlock)425 TEST_P(MutexTestSuite, UnexpectedUnlock)
426 NO_THREAD_SAFETY_ANALYSIS {
427     if (!android::audio_utils::AudioMutexAttributes::abort_on_invalid_unlock_
428             || !audio_utils::mutex_get_enable_flag()) {
429         ALOGD("Test UnexpectedUnlock skipped");
430         return;
431     }
432 
433     using Mutex = android::audio_utils::mutex;
434     const bool priority_inheritance = GetParam();
435 
436     Mutex m1{priority_inheritance, (android::audio_utils::AudioMutexAttributes::order_t)1};
437     ASSERT_DEATH(m1.unlock(), ".*mutex unlock.*");
438 }
439 
TEST_P(MutexTestSuite,TimedLock)440 TEST_P(MutexTestSuite, TimedLock) {
441     using ConditionVariable = android::audio_utils::condition_variable;
442     using Mutex = android::audio_utils::mutex;
443     using UniqueLock = android::audio_utils::unique_lock;
444     const bool priority_inheritance = GetParam();
445 
446     Mutex m{priority_inheritance}, m1{priority_inheritance};
447     ConditionVariable cv;
448     bool quit = false;  // GUARDED_BY(m)
449 
450     std::atomic<pid_t> tid1{};
451 
452     // launch thread.
453     std::thread t1([&]() {
454         UniqueLock ul1(m1);
455         UniqueLock ul(m);
456         tid1 = android::audio_utils::gettid_wrapper();
457         while (!quit) {
458             cv.wait(ul, [&]{ return quit; });
459             if (quit) break;
460         }
461     });
462 
463     // ensure thread tid1 has acquired all locks.
464     while (tid1 == 0) { usleep(1000); }
465 
466     // try lock for 1s
467     constexpr int64_t kTimeoutNs = 1'000'000'000;
468     {
469         //  verify timed out state.
470         const int64_t beginNs = systemTime();
471         const bool success = m1.try_lock(kTimeoutNs);
472         const int64_t endNs = systemTime();
473         const int64_t diffNs = endNs - beginNs;
474 
475         if (success) m1.unlock();
476         EXPECT_GT(diffNs, kTimeoutNs);
477         EXPECT_FALSE(success);
478     }
479 
480     // exit the thread
481     {
482         UniqueLock ul(m);
483 
484         quit = true;
485         cv.notify_one();
486     }
487 
488     t1.join();
489 
490     {
491         // verify success state.
492         const int64_t beginNs = systemTime();
493         const bool success = m1.try_lock(kTimeoutNs);
494         const int64_t endNs = systemTime();
495         const int64_t diffNs = endNs - beginNs;
496 
497         if (success) m1.unlock();
498         constexpr int64_t kSuccessLockNs = kTimeoutNs / 4;
499         EXPECT_LT(diffNs, kSuccessLockNs);
500         EXPECT_TRUE(success);
501     }
502 }
503 
504 // Test the deadlock detection algorithm for a single wait chain
505 // (no cycle).
506 
TEST_P(MutexTestSuite,DeadlockDetection)507 TEST_P(MutexTestSuite, DeadlockDetection) {
508     using Mutex = android::audio_utils::mutex;
509     using UniqueLock = android::audio_utils::unique_lock;
510     using ConditionVariable = android::audio_utils::condition_variable;
511     const bool priority_inheritance = GetParam();
512 
513     // order checked below.
514     constexpr size_t kOrder1 = 1;
515     constexpr size_t kOrder2 = 2;
516     constexpr size_t kOrder3 = 3;
517     static_assert(Mutex::attributes_t::order_size_ > kOrder3);
518 
519     Mutex m1{priority_inheritance, static_cast<Mutex::attributes_t::order_t>(kOrder1)};
520     Mutex m2{priority_inheritance, static_cast<Mutex::attributes_t::order_t>(kOrder2)};
521     Mutex m3{priority_inheritance, static_cast<Mutex::attributes_t::order_t>(kOrder3)};
522     Mutex m4{priority_inheritance};
523     Mutex m{priority_inheritance};
524     ConditionVariable cv;
525     bool quit = false;  // GUARDED_BY(m)
526     std::atomic<pid_t> tid1{}, tid2{}, tid3{}, tid4{};
527 
528     std::thread t4([&]() {
529         UniqueLock ul4(m4);
530         UniqueLock ul(m);
531         tid4 = android::audio_utils::gettid_wrapper();
532         while (!quit) {
533             cv.wait(ul, [&]{ return quit; });
534             if (quit) break;
535         }
536     });
537 
538     while (tid4 == 0) { usleep(1000); }
539 
540     std::thread t3([&]() {
541         UniqueLock ul3(m3);
542         tid3 = android::audio_utils::gettid_wrapper();
543         UniqueLock ul4(m4);
544     });
545 
546     while (tid3 == 0) { usleep(1000); }
547 
548     std::thread t2([&]() {
549         UniqueLock ul2(m2);
550         tid2 = android::audio_utils::gettid_wrapper();
551         UniqueLock ul3(m3);
552     });
553 
554     while (tid2 == 0) { usleep(1000); }
555 
556     std::thread t1([&]() {
557         UniqueLock ul1(m1);
558         tid1 = android::audio_utils::gettid_wrapper();
559         UniqueLock ul2(m2);
560     });
561 
562     while (tid1 == 0) { usleep(1000); }
563 
564     // we know that the threads will now block in the proper order.
565     // however, we need to wait for the block to happen.
566     // this part is racy unless we check the thread state or use
567     // futexes directly in our mutex (which allows atomic accuracy of wait).
568     usleep(20000);
569 
570     const auto deadlockInfo = android::audio_utils::mutex::deadlock_detection(tid1);
571 
572     // no cycle.
573     EXPECT_EQ(false, deadlockInfo.has_cycle);
574 
575     // no condition_variable detected
576     EXPECT_EQ(audio_utils::other_wait_reason_t::none, deadlockInfo.other_wait_reason);
577 
578     // thread1 is waiting on a chain of 3 other threads.
579     const auto chain = deadlockInfo.chain;
580     const size_t chain_size = chain.size();
581     EXPECT_EQ(3u, chain_size);
582 
583     const auto default_idx = static_cast<size_t>(Mutex::attributes_t::order_default_);
584     if (chain_size > 0) {
585         EXPECT_EQ(tid2, chain[0].first);
586         EXPECT_EQ(Mutex::attributes_t::order_names_[kOrder2], chain[0].second);
587     }
588     if (chain_size > 1) {
589         EXPECT_EQ(tid3, chain[1].first);
590         EXPECT_EQ(Mutex::attributes_t::order_names_[kOrder3], chain[1].second);
591     }
592     if (chain_size > 2) {
593         EXPECT_EQ(tid4, chain[2].first);
594         EXPECT_EQ(Mutex::attributes_t::order_names_[default_idx], chain[2].second);
595     }
596 
597     ALOGD("%s", android::audio_utils::mutex::all_threads_to_string().c_str());
598 
599     {
600         UniqueLock ul(m);
601 
602         quit = true;
603         cv.notify_one();
604     }
605 
606     t4.join();
607     t3.join();
608     t2.join();
609     t1.join();
610 }
611 
TEST_P(MutexTestSuite,DeadlockConditionVariableDetection)612 TEST_P(MutexTestSuite, DeadlockConditionVariableDetection) {
613     using Mutex = android::audio_utils::mutex;
614     using UniqueLock = android::audio_utils::unique_lock;
615     using ConditionVariable = android::audio_utils::condition_variable;
616     const bool priority_inheritance = GetParam();
617 
618     // order checked below.
619     constexpr size_t kOrder1 = 1;
620     constexpr size_t kOrder2 = 2;
621     constexpr size_t kOrder3 = 3;
622     static_assert(Mutex::attributes_t::order_size_ > kOrder3);
623 
624     Mutex m1{priority_inheritance, static_cast<Mutex::attributes_t::order_t>(kOrder1)};
625     Mutex m2{priority_inheritance, static_cast<Mutex::attributes_t::order_t>(kOrder2)};
626     Mutex m3{priority_inheritance, static_cast<Mutex::attributes_t::order_t>(kOrder3)};
627     Mutex m4{priority_inheritance};
628     Mutex m{priority_inheritance};
629     ConditionVariable cv, cv2, cv4;
630     bool quit = false;  // GUARDED_BY(m)
631     std::atomic<pid_t> tid1{}, tid2{}, tid3{}, tid4{};
632 
633     std::thread t4([&]() {
634         // UniqueLock ul4(m4);
635         UniqueLock ul(m);
636         tid4 = android::audio_utils::gettid_wrapper();
637         while (!quit) {
638             cv.wait(ul, [&]{ return quit; });
639             if (quit) break;
640         }
641     });
642 
643     while (tid4 == 0) { usleep(1000); }
644 
645     std::thread t3([&]() {
646         UniqueLock ul3(m3);
647         tid3 = android::audio_utils::gettid_wrapper();
648         UniqueLock ul4(m4);
649         while (!quit) {
650             // use the wait method with the notifier_tid metadata.
651             cv4.wait(ul4, [&]{ return quit; }, tid4);
652             if (quit) break;
653         }
654     });
655 
656     while (tid3 == 0) { usleep(1000); }
657 
658     std::thread t2([&]() {
659         // UniqueLock ul2(m2);
660         tid2 = android::audio_utils::gettid_wrapper();
661         UniqueLock ul3(m3);
662     });
663 
664     while (tid2 == 0) { usleep(1000); }
665 
666     std::thread t1([&]() {
667         UniqueLock ul1(m1);
668         tid1 = android::audio_utils::gettid_wrapper();
669         UniqueLock ul2(m2);
670         while (!quit) {
671             // use the wait method with the notifier_tid metadata.
672             cv2.wait(ul2, [&]{ return quit; }, tid2);
673             if (quit) break;
674         }
675     });
676 
677     while (tid1 == 0) { usleep(1000); }
678 
679     // we know that the threads will now block in the proper order.
680     // however, we need to wait for the block to happen.
681     // this part is racy unless we check the thread state or use
682     // futexes directly in our mutex (which allows atomic accuracy of wait).
683     usleep(20000);
684 
685     const auto deadlockInfo = android::audio_utils::mutex::deadlock_detection(tid1);
686 
687     // no cycle.
688     EXPECT_EQ(false, deadlockInfo.has_cycle);
689 
690     // condition_variable detected
691     EXPECT_EQ(audio_utils::other_wait_reason_t::cv, deadlockInfo.other_wait_reason);
692 
693     // thread1 is waiting on a chain of 3 other threads.
694     const auto chain = deadlockInfo.chain;
695     const size_t chain_size = chain.size();
696     EXPECT_EQ(3u, chain_size);
697 
698     const auto default_idx = static_cast<size_t>(Mutex::attributes_t::order_default_);
699     if (chain_size > 0) {
700         EXPECT_EQ(tid2, chain[0].first);
701         EXPECT_EQ(std::string("cv-").append(Mutex::attributes_t::order_names_[kOrder2]).c_str(),
702                 chain[0].second);
703     }
704     if (chain_size > 1) {
705         EXPECT_EQ(tid3, chain[1].first);
706         EXPECT_EQ(Mutex::attributes_t::order_names_[kOrder3], chain[1].second);
707     }
708     if (chain_size > 2) {
709         EXPECT_EQ(tid4, chain[2].first);
710         EXPECT_EQ(std::string("cv-").append(
711                 Mutex::attributes_t::order_names_[default_idx]).c_str(), chain[2].second);
712     }
713 
714     ALOGD("with cv all_threads_to_string():\n%s",
715             android::audio_utils::mutex::all_threads_to_string().c_str());
716     ALOGD("with cv deadlock_info_t:\n%s",
717             android::audio_utils::mutex::deadlock_detection(
718                    tid1).to_string().c_str());
719 
720     {
721         UniqueLock ul(m);
722         quit = true;
723         cv.notify_one();
724     }
725     {
726         UniqueLock ul2(m);
727         cv2.notify_one();
728     }
729     {
730         UniqueLock ul4(m);
731         cv4.notify_one();
732     }
733 
734     t4.join();
735     t3.join();
736     t2.join();
737     t1.join();
738 }
739 
TEST_P(MutexTestSuite,DeadlockJoinDetection)740 TEST_P(MutexTestSuite, DeadlockJoinDetection) {
741     using Mutex = android::audio_utils::mutex;
742     using UniqueLock = android::audio_utils::unique_lock;
743     using ConditionVariable = android::audio_utils::condition_variable;
744     const bool priority_inheritance = GetParam();
745 
746     Mutex m{priority_inheritance};
747     ConditionVariable cv;
748     bool quit = false;  // GUARDED_BY(m)
749     std::atomic<pid_t> tid1{}, tid2{}, tid3{}, tid4{};
750 
751     std::thread t4([&]() {
752         UniqueLock ul(m);
753         tid4 = android::audio_utils::gettid_wrapper();
754         while (!quit) {
755             cv.wait(ul, [&]{ return quit; });
756             if (quit) break;
757         }
758     });
759 
760     while (tid4 == 0) { std::this_thread::sleep_for(1ms); }
761 
762     std::thread t3([&]() {
763         tid3 = android::audio_utils::gettid_wrapper();
764         audio_utils::mutex::scoped_join_wait_check sjw(tid4);
765         t4.join();
766     });
767 
768     while (tid3 == 0) { std::this_thread::sleep_for(1ms); }
769 
770     std::thread t2([&]() {
771         tid2 = android::audio_utils::gettid_wrapper();
772         audio_utils::mutex::scoped_join_wait_check sjw(tid3);
773         t3.join();
774     });
775 
776     while (tid2 == 0) { std::this_thread::sleep_for(1ms); }
777 
778     std::thread t1([&]() {
779         tid1 = android::audio_utils::gettid_wrapper();
780         audio_utils::mutex::scoped_join_wait_check sjw(tid2);
781         t2.join();
782     });
783 
784     while (tid1 == 0) { std::this_thread::sleep_for(1ms); }
785 
786     // we know that the threads will now block in the proper order.
787     // however, we need to wait for the block to happen.
788     // this part is racy unless we check the thread state or use
789     // futexes directly in our mutex (which allows atomic accuracy of wait).
790     std::this_thread::sleep_for(20ms);
791 
792     const auto deadlockInfo = android::audio_utils::mutex::deadlock_detection(tid1);
793 
794     // no cycle.
795     EXPECT_EQ(false, deadlockInfo.has_cycle);
796 
797     // thread join detected
798     EXPECT_EQ(audio_utils::other_wait_reason_t::join, deadlockInfo.other_wait_reason);
799 
800     // thread1 is attempting to join, in a chain of 3 other threads.
801     const auto chain = deadlockInfo.chain;
802     const size_t chain_size = chain.size();
803     EXPECT_EQ(3u, chain_size);
804 
805     const auto default_idx = static_cast<size_t>(Mutex::attributes_t::order_default_);
806     if (chain_size > 0) {
807         EXPECT_EQ(tid2, chain[0].first);
808         EXPECT_EQ("join", chain[0].second);
809     }
810     if (chain_size > 1) {
811         EXPECT_EQ(tid3, chain[1].first);
812         EXPECT_EQ("join", chain[1].second);
813     }
814     if (chain_size > 2) {
815         EXPECT_EQ(tid4, chain[2].first);
816         EXPECT_EQ("join", chain[2].second);
817     }
818 
819     ALOGD("with join all_threads_to_string():\n%s",
820             android::audio_utils::mutex::all_threads_to_string().c_str());
821     ALOGD("with join deadlock_info_t:\n%s",
822             android::audio_utils::mutex::deadlock_detection(
823                    tid1).to_string().c_str());
824 
825     {
826         UniqueLock ul(m);
827         quit = true;
828         cv.notify_one();
829     }
830     t1.join();
831 }
832 
833 INSTANTIATE_TEST_SUITE_P(Mutex_NonPI_and_PI, MutexTestSuite, testing::Values(false, true));
834 
835 } // namespace android
836