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++ 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
36
37 "Spatializer_Mutex", // AP - must come before EffectHandle_Mutex
38 "AudioPolicyEffects_Mutex", // AP - never hold AudioPolicyEffects_Mutex while calling APS,
39 // not sure if this is still true.
40 "EffectHandle_Mutex", // AF - must be after AudioPolicyEffects_Mutex
41 "EffectBase_PolicyMutex", // AF - Held for AudioSystem::registerEffect, must come
42 // after EffectHandle_Mutex and before AudioPolicyService_Mutex
43
44 "AudioPolicyService_Mutex", // AP
45 "CommandThread_Mutex", // AP
46 "AudioCommand_Mutex", // AP
47 "UidPolicy_Mutex", // AP
48
49 "AudioFlinger_Mutex", // AF
50 "AudioFlinger_HardwareMutex", // AF
51 "DeviceEffectManager_Mutex", // AF
52 "PatchCommandThread_Mutex", // AF
53 "ThreadBase_Mutex", // AF
54 "AudioFlinger_ClientMutex", // AF
55 "MelReporter_Mutex", // AF
56 "EffectChain_Mutex", // AF
57 "DeviceEffectProxy_ProxyMutex", // AF: used for device effects (which have no chain).
58 "EffectBase_Mutex", // AF
59
60 // These mutexes are in leaf objects
61 // and are presented afterwards in arbitrary order.
62
63 "AudioFlinger_UnregisteredWritersMutex", // AF
64 "AsyncCallbackThread_Mutex", // AF
65 "ConfigEvent_Mutex", // AF
66 "OutputTrack_TrackMetadataMutex", // AF
67 "PassthruPatchRecord_ReadMutex", // AF
68 "PatchCommandThread_ListenerMutex", // AF
69 "PlaybackThread_AudioTrackCbMutex", // AF
70 "AudioPolicyService_NotificationClientsMutex", // AP
71 "MediaLogNotifier_Mutex", // AF
72 "OtherMutex", // DO NOT CHANGE THIS: OtherMutex is used for mutexes without a specified order.
73 // An OtherMutex will always be the lowest order mutex and cannot acquire
74 // another named mutex while being held.
75 };
76
77 using namespace std;
78
79 // Utility program to print out the mutex
80 // ordering and exclusion as listed above.
81
main()82 int main() {
83 cout << "// Lock order\n";
84 cout << "enum class MutexOrder : uint32_t {\n";
85
86 for (size_t i = 0; i < std::size(mutexes); ++i) {
87 cout << " k" << mutexes[i] << " = " << i << ",\n";
88 }
89 cout << " kSize = " << std::size(mutexes) << ",\n";
90 cout << "};\n";
91
92 cout << "\n// Lock by name\n";
93 cout << "inline constexpr const char* const gMutexNames[] = {\n";
94 for (size_t i = 0; i < std::size(mutexes); ++i) {
95 cout << " \"" << mutexes[i] << "\",\n";
96 }
97 cout << "};\n";
98
99 cout << "\n// Forward declarations\n";
100 cout << "class AudioMutexAttributes;\n";
101 cout << "template <typename T> class mutex_impl;\n";
102 cout << "using mutex = mutex_impl<AudioMutexAttributes>;\n";
103
104 cout << "\n// Capabilities in priority order\n"
105 << "// (declaration only, value is nullptr)\n";
106 const char *last = nullptr;
107 for (auto mutex : mutexes) {
108 if (last == nullptr) {
109 cout << "inline mutex* " << mutex << ";\n";
110 } else {
111 cout << "inline mutex* " << mutex
112 << "\n ACQUIRED_AFTER(android::audio_utils::"
113 << last << ");\n";
114 }
115 last = mutex;
116 }
117 cout << "\n";
118
119 cout << "// Exclusion by capability\n";
120 last = nullptr;
121 for (size_t i = 0; i < std::size(mutexes); ++i) {
122 // exclusion is defined in reverse order of priority.
123 auto mutex = mutexes[std::size(mutexes) - i - 1];
124 if (last == nullptr) {
125 cout << "#define EXCLUDES_BELOW_" << mutex << "\n";
126 } else {
127 cout << "#define EXCLUDES_BELOW_" << mutex
128 << " \\\n EXCLUDES_" << last << "\n";
129 }
130 cout << "#define EXCLUDES_" << mutex
131 << " \\\n EXCLUDES(android::audio_utils::" << mutex << ")"
132 << " \\\n EXCLUDES_BELOW_" << mutex << "\n\n";
133 last = mutex;
134 }
135
136 cout << "#define EXCLUDES_AUDIO_ALL"
137 << " \\\n EXCLUDES_" << last << "\n\n";
138 return 0;
139 }
140