aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-22 01:01:42 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-22 01:01:42 +0000
commit484997260df1d7f432461af289aead399704dd7f (patch)
treec130893e90c7e7e8763c64b643bca6577a8be6aa
parent4f019655a4641c0747eb35f6a8a3ade732508bf5 (diff)
parentdf08a31b762c00220673003b1f46b4b4746637e1 (diff)
downloadgs-common-484997260df1d7f432461af289aead399704dd7f.tar.gz
Snap for 8485504 from df08a31b762c00220673003b1f46b4b4746637e1 to tm-release
Change-Id: I6fd3dbbfe742ce249cb99cee662835c10e710b0b
-rw-r--r--powerstats/AocStateResidencyDataProvider.cpp98
-rw-r--r--powerstats/include/AocStateResidencyDataProvider.h7
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