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