1 /*
2 * Copyright (C) 2023 MediaTek Inc., this file is modified on 02/26/2021
3 * by MediaTek Inc. based on MIT License .
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the ""Software""), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #pragma once
24
25 #include <android/log.h>
26 #include <dlfcn.h>
27 #include <cstdlib>
28 #include <memory>
29 #include <string>
30 #include <thread>
31 #include <utility>
32 using namespace std;
33
34 typedef enum {
35 LOW_POWER_MODE = 0, // For model execution preference
36 FAST_SINGLE_ANSWER_MODE, // For model execution preference
37 SUSTAINED_SPEED_MODE, // For model execution preference
38 FAST_COMPILE_MODE, // For model compile preference
39 PERFORMANCE_MODE_MAX,
40 } PERFORMANCE_MODE_E;
41
42 //------------------------------------- -------------------------------------
43 #define APUWARE_LOG_D(format, ...) \
44 __android_log_print( \
45 ANDROID_LOG_DEBUG, "APUWARELIB", format "\n", ##__VA_ARGS__);
46
47 #define APUWARE_LOG_E(format, ...) \
48 __android_log_print( \
49 ANDROID_LOG_ERROR, "APUWARELIB", format "\n", ##__VA_ARGS__);
50
voidFunction()51 inline void* voidFunction() {
52 return nullptr;
53 }
54
55 // ApuWareUtils library construct
56 struct ApuWareUtilsLib {
GetInstanceApuWareUtilsLib57 static struct ApuWareUtilsLib& GetInstance() {
58 static struct ApuWareUtilsLib instance;
59 return instance;
60 }
61
ApuWareUtilsLibApuWareUtilsLib62 ApuWareUtilsLib() {
63 load();
64 }
65
66 using AcquirePerformanceLockPtr =
67 std::add_pointer<int32_t(int32_t, PERFORMANCE_MODE_E, uint32_t)>::type;
68 using AcquirePerfParamsLockPtr =
69 std::add_pointer<int32_t(int32_t, uint32_t, int32_t[], uint32_t)>::type;
70 using ReleasePerformanceLockPtr = std::add_pointer<bool(int32_t)>::type;
71
72 // Open a given library and load symbols
loadApuWareUtilsLib73 bool load() {
74 void* handle = nullptr;
75 const std::string libraries[] = {
76 "libapuwareutils_v2.mtk.so", "libapuwareutils.mtk.so"};
77 for (const auto& lib : libraries) {
78 handle = dlopen(lib.c_str(), RTLD_LAZY | RTLD_LOCAL);
79 if (handle) {
80 APUWARE_LOG_D("dlopen %s", lib.c_str());
81 acquirePerformanceLock =
82 reinterpret_cast<decltype(acquirePerformanceLock)>(
83 dlsym(handle, "acquirePerformanceLockInternal"));
84 acquirePerfParamsLock =
85 reinterpret_cast<decltype(acquirePerfParamsLock)>(
86 dlsym(handle, "acquirePerfParamsLockInternal"));
87 releasePerformanceLock =
88 reinterpret_cast<decltype(releasePerformanceLock)>(
89 dlsym(handle, "releasePerformanceLockInternal"));
90 return mEnable = acquirePerformanceLock && releasePerformanceLock &&
91 acquirePerfParamsLock;
92 } else {
93 APUWARE_LOG_E("unable to open library %s", lib.c_str());
94 }
95 }
96 return false;
97 }
98
99 bool mEnable = false;
100
101 AcquirePerformanceLockPtr acquirePerformanceLock =
102 reinterpret_cast<decltype(acquirePerformanceLock)>(voidFunction);
103 AcquirePerfParamsLockPtr acquirePerfParamsLock =
104 reinterpret_cast<decltype(acquirePerfParamsLock)>(voidFunction);
105 ReleasePerformanceLockPtr releasePerformanceLock =
106 reinterpret_cast<decltype(releasePerformanceLock)>(voidFunction);
107 };
108
109 class ScopePerformancer {
110 public:
111 ScopePerformancer(uint32_t ms = 2000)
mLib(ApuWareUtilsLib::GetInstance ())112 : mLib(ApuWareUtilsLib::GetInstance()), mMs(ms) {
113 mLock = mLib.mEnable;
114 if (mLock) {
115 APUWARE_LOG_D("Powerhal Up");
116 mRunning.store(true);
117 mThread = std::thread(&ScopePerformancer::acquireLockRepeatedly, this);
118 }
119 };
120
Stop()121 void Stop() {
122 if (mRunning.load()) {
123 mRunning.store(false);
124 mCond.notify_one();
125 }
126 }
127
~ScopePerformancer()128 ~ScopePerformancer() {
129 Stop();
130 if (mThread.joinable()) {
131 mThread.join();
132 }
133 if (mHalHandle != 0 && mLock) {
134 APUWARE_LOG_D("Powerhal Free");
135 mLib.releasePerformanceLock(mHalHandle);
136 mHalHandle = 0;
137 }
138 }
139
140 private:
acquireLockRepeatedly()141 void acquireLockRepeatedly() {
142 std::unique_lock<std::mutex> lock(mMutex);
143 while (mRunning.load()) {
144 mHalHandle =
145 mLib.acquirePerformanceLock(mHalHandle, FAST_SINGLE_ANSWER_MODE, mMs);
146 mCond.wait_for(lock, std::chrono::milliseconds(1000), [this] {
147 return !mRunning.load();
148 });
149 }
150 }
151
152 struct ApuWareUtilsLib mLib;
153
154 bool mLock = false;
155
156 int mHalHandle = 0;
157
158 uint32_t mMs;
159
160 std::atomic<bool> mRunning{false};
161
162 std::thread mThread;
163
164 std::mutex mMutex;
165
166 std::condition_variable mCond;
167 };