• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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