xref: /aosp_15_r20/system/media/audio_utils/tests/generate_mutex_order.cpp (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
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 <iostream>
18 
19 // To dump the mutex code to stdout:
20 //
21 // $ clang++ -std=c++2a generate_mutex_order.cpp
22 // $ ./a.out
23 //
24 
25 constexpr const char* mutexes[] {
26   // These mutexes obey partial ordering rules.
27   // 1) AudioFlinger::mutex() -> PatchCommandThread::mutex() -> MelReporter::mutex().
28   // 2) If both AudioFlinger::mutex() and AudioFlinger::hardwareMutex() must be held,
29   //    always take mutex() before hardwareMutex().
30   // 3) AudioFlinger::clientMutex() protects mClients and mNotificationClients,
31   //    must be locked after mutex() and ThreadBase::mutex() if both must be locked
32   //    avoids acquiring AudioFlinger::mutex() from inside thread loop.
33   // 4) AudioFlinger -> ThreadBase -> EffectChain -> EffectBase(EffectModule)
34   // 5) EffectHandle -> ThreadBase -> EffectChain -> EffectBase(EffectModule)
35   // 6) AudioFlinger::mutex() -> DeviceEffectManager -> DeviceEffectProxy -> EffectChain
36   //    -> AudioFlinger::hardwareMutex() when adding/removing effect to/from HAL
37   // 7) AudioFlinger -> DeviceEffectManager -> DeviceEffectProxy -> DeviceEffectHandle
38 
39   "Spatializer_Mutex",         // AP - must come before EffectHandle_Mutex
40   "AudioPolicyEffects_Mutex",  // AP - never hold AudioPolicyEffects_Mutex while calling APS,
41                                // not sure if this is still true.
42   "EffectHandle_Mutex",        // AF - must be after AudioPolicyEffects_Mutex
43   "EffectBase_PolicyMutex",    // AF - Held for AudioSystem::registerEffect, must come
44                                // after EffectHandle_Mutex and before AudioPolicyService_Mutex
45 
46   "AudioPolicyService_Mutex",  // AP
47   "CommandThread_Mutex",       // AP
48   "AudioCommand_Mutex",        // AP
49   "UidPolicy_Mutex",           // AP
50 
51   "AudioFlinger_Mutex",            // AF
52   "DeviceEffectManager_Mutex",     // AF
53   "DeviceEffectProxy_ProxyMutex",  // AF: used for device effects (which have no chain).
54   "DeviceEffectHandle_Mutex",      // AF: used for device effects when controlled internally.
55   "PatchCommandThread_Mutex",      // AF
56   "ThreadBase_Mutex",              // AF
57   "AudioFlinger_ClientMutex",      // AF
58   "EffectChain_Mutex",             // AF
59   "EffectBase_Mutex",              // AF
60   "AudioFlinger_HardwareMutex",    // AF: used for HAL, called from AF or DeviceEffectManager
61   "MelReporter_Mutex",             // AF
62 
63   // These mutexes are in leaf objects
64   // and are presented afterwards in arbitrary order.
65 
66   "AudioFlinger_UnregisteredWritersMutex",       // AF
67   "AsyncCallbackThread_Mutex",                   // AF
68   "ConfigEvent_Mutex",                           // AF
69   "OutputTrack_TrackMetadataMutex",              // AF
70   "PassthruPatchRecord_ReadMutex",               // AF
71   "PatchCommandThread_ListenerMutex",            // AF
72   "PlaybackThread_AudioTrackCbMutex",            // AF
73   "AudioPolicyService_NotificationClientsMutex", // AP
74   "MediaLogNotifier_Mutex",                      // AF
75   "OtherMutex", // DO NOT CHANGE THIS: OtherMutex is used for mutexes without a specified order.
76                 // An OtherMutex will always be the lowest order mutex and cannot acquire
77                 // another named mutex while being held.
78 };
79 
80 using namespace std;
81 
82 // Utility program to print out the mutex
83 // ordering and exclusion as listed above.
84 
main()85 int main() {
86   cout << "// Lock order\n";
87   cout << "enum class MutexOrder : uint32_t {\n";
88 
89   for (size_t i = 0; i < std::size(mutexes); ++i) {
90       cout << "    k" << mutexes[i] << " = " << i << ",\n";
91   }
92   cout << "    kSize = " << std::size(mutexes) << ",\n";
93   cout << "};\n";
94 
95   cout << "\n// Lock by name\n";
96   cout << "inline constexpr const char* const gMutexNames[] = {\n";
97   for (size_t i = 0; i < std::size(mutexes); ++i) {
98       cout << "    \"" << mutexes[i] << "\",\n";
99   }
100   cout << "};\n";
101 
102   cout << "\n// Forward declarations\n";
103   cout << "class AudioMutexAttributes;\n";
104   cout << "template <typename T> class mutex_impl;\n";
105   cout << "using mutex = mutex_impl<AudioMutexAttributes>;\n";
106 
107   cout << "\n// Capabilities in priority order\n"
108        << "// (declaration only, value is nullptr)\n";
109   const char *last = nullptr;
110   for (auto mutex : mutexes) {
111     if (last == nullptr) {
112       cout << "inline mutex* " << mutex << ";\n";
113     } else {
114       cout << "inline mutex* " << mutex
115            << "\n        ACQUIRED_AFTER(android::audio_utils::"
116            << last << ");\n";
117     }
118     last = mutex;
119   }
120   cout << "\n";
121 
122   cout << "// Exclusion by capability\n";
123   last = nullptr;
124   for (size_t i = 0; i < std::size(mutexes); ++i) {
125     // exclusion is defined in reverse order of priority.
126     auto mutex = mutexes[std::size(mutexes) - i - 1];
127     if (last == nullptr) {
128       cout << "#define EXCLUDES_BELOW_" << mutex << "\n";
129     } else {
130       cout << "#define EXCLUDES_BELOW_" << mutex
131            << " \\\n    EXCLUDES_" << last << "\n";
132     }
133     cout << "#define EXCLUDES_" << mutex
134          << " \\\n    EXCLUDES(android::audio_utils::" << mutex << ")"
135          << " \\\n    EXCLUDES_BELOW_" << mutex << "\n\n";
136     last = mutex;
137   }
138 
139   cout << "#define EXCLUDES_AUDIO_ALL"
140        << " \\\n    EXCLUDES_" << last << "\n\n";
141   return 0;
142 }
143