diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-22 01:01:42 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-22 01:01:42 +0000 |
commit | 484997260df1d7f432461af289aead399704dd7f (patch) | |
tree | c130893e90c7e7e8763c64b643bca6577a8be6aa | |
parent | 4f019655a4641c0747eb35f6a8a3ade732508bf5 (diff) | |
parent | df08a31b762c00220673003b1f46b4b4746637e1 (diff) | |
download | gs-common-484997260df1d7f432461af289aead399704dd7f.tar.gz |
Snap for 8485504 from df08a31b762c00220673003b1f46b4b4746637e1 to tm-release
Change-Id: I6fd3dbbfe742ce249cb99cee662835c10e710b0b
-rw-r--r-- | powerstats/AocStateResidencyDataProvider.cpp | 98 | ||||
-rw-r--r-- | powerstats/include/AocStateResidencyDataProvider.h | 7 |
2 files changed, 96 insertions, 9 deletions
diff --git a/powerstats/AocStateResidencyDataProvider.cpp b/powerstats/AocStateResidencyDataProvider.cpp index c64496d..574a23d 100644 --- a/powerstats/AocStateResidencyDataProvider.cpp +++ b/powerstats/AocStateResidencyDataProvider.cpp @@ -17,6 +17,8 @@ #include "AocStateResidencyDataProvider.h" #include <android-base/logging.h> +#include <chrono> +#include <pthread.h> namespace aidl { namespace android { @@ -24,12 +26,23 @@ namespace hardware { namespace power { namespace stats { +struct async_data_t { + pthread_cond_t *cond; + pthread_mutex_t *lock; + uint64_t timeoutMillis; + std::unordered_map<std::string, std::vector<StateResidency>> *residencies; + std::unordered_map<std::string, + std::vector<std::unique_ptr<GenericStateResidencyDataProvider>>> *providers; +}; + AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector<std::pair<std::string, - std::string>> ids, std::vector<std::pair<std::string, std::string>> states) { + std::string>> ids, std::vector<std::pair<std::string, std::string>> states, + const uint64_t timeoutMillis) { // AoC stats are reported in ticks of 244.140625ns. The transform // function converts ticks to milliseconds. // 1000000 / 244.140625 = 4096. static const uint64_t AOC_CLK = 4096; + static const uint64_t TIMEOUT_MILLIS = 120; std::function<uint64_t(uint64_t)> aocTickToMs = [](uint64_t a) { return a / AOC_CLK; }; GenericStateResidencyDataProvider::StateResidencyConfig config = { .entryCountSupported = true, @@ -54,13 +67,17 @@ AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector<std::pa mProviders[id.first].push_back(std::move(sdp)); } } + mStateCount = states.size(); + mTimeoutMillis = timeoutMillis == 0 ? TIMEOUT_MILLIS : timeoutMillis; } -bool AocStateResidencyDataProvider::getStateResidencies( - std::unordered_map<std::string, std::vector<StateResidency>> *residencies) { +void *getStateResidenciesAsync(void *arg) { + struct timespec start, end; + struct async_data_t *async = (struct async_data_t*)arg; + uint64_t timeoutUs = async->timeoutMillis * 1000; + // States from the same power entity are merged. - bool ret = true; - for (const auto &providerList : mProviders) { + for (const auto &providerList : *async->providers) { int32_t stateId = 0; std::string curEntity = providerList.first; std::vector<StateResidency> stateResidencies; @@ -68,7 +85,18 @@ bool AocStateResidencyDataProvider::getStateResidencies( // Iterate over each provider in the providerList, appending each of the states for (const auto &provider : providerList.second) { std::unordered_map<std::string, std::vector<StateResidency>> residency; - ret &= provider->getStateResidencies(&residency); + + clock_gettime(CLOCK_REALTIME, &start); + provider->getStateResidencies(&residency); + clock_gettime(CLOCK_REALTIME, &end); + uint64_t elapsedUs = + ((end.tv_sec - start.tv_sec) * 1000000) + ((end.tv_nsec - start.tv_nsec) / 1000); + + if (elapsedUs >= timeoutUs) { + LOG(WARNING) << "getStateResidencies latency for " << curEntity + << " exceeds time allowed: " << elapsedUs << " us"; + return 0; + } // Each provider should only return data for curEntity but checking anyway if (residency.find(curEntity) != residency.end()) { @@ -84,8 +112,64 @@ bool AocStateResidencyDataProvider::getStateResidencies( } } - residencies->emplace(curEntity, stateResidencies); + async->residencies->emplace(curEntity, stateResidencies); } + + pthread_mutex_lock(async->lock); + pthread_cond_signal(async->cond); + pthread_mutex_unlock(async->lock); + + return 0; +} + +bool AocStateResidencyDataProvider::getStateResidencies( + std::unordered_map<std::string, std::vector<StateResidency>> *residencies) { + bool ret = true; + int condResult = 0; + pthread_t tid; + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + std::unordered_map<std::string, std::vector<StateResidency>> stateResidencies; + struct timespec start, timeout; + struct async_data_t async = { + .cond = &cond, + .lock = &lock, + .timeoutMillis = mTimeoutMillis, + .residencies = &stateResidencies, + .providers = &mProviders + }; + + pthread_create(&tid, NULL, &getStateResidenciesAsync, (void*)&async); + + clock_gettime(CLOCK_REALTIME, &start); + + uint64_t expirationMillis = mTimeoutMillis * mStateCount; + timeout.tv_sec = start.tv_sec + expirationMillis / 1000; + uint64_t nsec = start.tv_nsec + (expirationMillis % 1000) * 1000000; + if (nsec < 1000000000) { + timeout.tv_nsec = nsec; + } else { + timeout.tv_sec += 1; + timeout.tv_nsec = nsec - 1000000000; + } + + pthread_mutex_lock(&lock); + condResult = pthread_cond_timedwait(&cond, &lock, &timeout); + pthread_mutex_unlock(&lock); + + if (condResult != 0) { + if (condResult == ETIMEDOUT) { + LOG(WARNING) << __func__ << " latency for AoC timeout: " << expirationMillis << " ms"; + } else { + LOG(ERROR) << "Failed to wait for the condition variable: " << condResult; + } + ret = false; + } else { + for (const auto &residency : stateResidencies) { + residencies->emplace(residency.first, residency.second); + } + } + return ret; } diff --git a/powerstats/include/AocStateResidencyDataProvider.h b/powerstats/include/AocStateResidencyDataProvider.h index 5008912..150f335 100644 --- a/powerstats/include/AocStateResidencyDataProvider.h +++ b/powerstats/include/AocStateResidencyDataProvider.h @@ -27,7 +27,8 @@ namespace stats { class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { public: AocStateResidencyDataProvider(std::vector<std::pair<std::string, std::string>> ids, - std::vector<std::pair<std::string, std::string>> states); + std::vector<std::pair<std::string, std::string>> states, + const uint64_t timeoutMillis); ~AocStateResidencyDataProvider() = default; bool getStateResidencies( std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override; @@ -36,10 +37,12 @@ class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProv private: std::unordered_map<std::string /* entity name */, std::vector<std::unique_ptr<GenericStateResidencyDataProvider>> /* providers */> mProviders; + int32_t mStateCount; + uint64_t mTimeoutMillis; }; } // namespace stats } // namespace power } // namespace hardware } // namespace android -} // namespace aidl
\ No newline at end of file +} // namespace aidl |