Snap for 8485840 from d68c4c2c1deaefc958ade99e07e404913ff5ff08 to udc-release

Change-Id: I1a7d64f17174ee83a03283fdd253a254ee76937c
This commit is contained in:
Android Build Coastguard Worker 2022-04-22 03:03:11 +00:00
commit e419ba1a50
2 changed files with 96 additions and 9 deletions

View File

@ -17,6 +17,8 @@
#include "AocStateResidencyDataProvider.h" #include "AocStateResidencyDataProvider.h"
#include <android-base/logging.h> #include <android-base/logging.h>
#include <chrono>
#include <pthread.h>
namespace aidl { namespace aidl {
namespace android { namespace android {
@ -24,12 +26,23 @@ namespace hardware {
namespace power { namespace power {
namespace stats { 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, 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 // AoC stats are reported in ticks of 244.140625ns. The transform
// function converts ticks to milliseconds. // function converts ticks to milliseconds.
// 1000000 / 244.140625 = 4096. // 1000000 / 244.140625 = 4096.
static const uint64_t AOC_CLK = 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; }; std::function<uint64_t(uint64_t)> aocTickToMs = [](uint64_t a) { return a / AOC_CLK; };
GenericStateResidencyDataProvider::StateResidencyConfig config = { GenericStateResidencyDataProvider::StateResidencyConfig config = {
.entryCountSupported = true, .entryCountSupported = true,
@ -54,13 +67,17 @@ AocStateResidencyDataProvider::AocStateResidencyDataProvider(std::vector<std::pa
mProviders[id.first].push_back(std::move(sdp)); mProviders[id.first].push_back(std::move(sdp));
} }
} }
mStateCount = states.size();
mTimeoutMillis = timeoutMillis == 0 ? TIMEOUT_MILLIS : timeoutMillis;
} }
bool AocStateResidencyDataProvider::getStateResidencies( void *getStateResidenciesAsync(void *arg) {
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) { 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. // States from the same power entity are merged.
bool ret = true; for (const auto &providerList : *async->providers) {
for (const auto &providerList : mProviders) {
int32_t stateId = 0; int32_t stateId = 0;
std::string curEntity = providerList.first; std::string curEntity = providerList.first;
std::vector<StateResidency> stateResidencies; std::vector<StateResidency> stateResidencies;
@ -68,7 +85,18 @@ bool AocStateResidencyDataProvider::getStateResidencies(
// Iterate over each provider in the providerList, appending each of the states // Iterate over each provider in the providerList, appending each of the states
for (const auto &provider : providerList.second) { for (const auto &provider : providerList.second) {
std::unordered_map<std::string, std::vector<StateResidency>> residency; 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 // Each provider should only return data for curEntity but checking anyway
if (residency.find(curEntity) != residency.end()) { 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; return ret;
} }

View File

@ -27,7 +27,8 @@ namespace stats {
class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider { class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProvider {
public: public:
AocStateResidencyDataProvider(std::vector<std::pair<std::string, std::string>> ids, 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; ~AocStateResidencyDataProvider() = default;
bool getStateResidencies( bool getStateResidencies(
std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override; std::unordered_map<std::string, std::vector<StateResidency>> *residencies) override;
@ -36,10 +37,12 @@ class AocStateResidencyDataProvider : public PowerStats::IStateResidencyDataProv
private: private:
std::unordered_map<std::string /* entity name */, std::unordered_map<std::string /* entity name */,
std::vector<std::unique_ptr<GenericStateResidencyDataProvider>> /* providers */> mProviders; std::vector<std::unique_ptr<GenericStateResidencyDataProvider>> /* providers */> mProviders;
int32_t mStateCount;
uint64_t mTimeoutMillis;
}; };
} // namespace stats } // namespace stats
} // namespace power } // namespace power
} // namespace hardware } // namespace hardware
} // namespace android } // namespace android
} // namespace aidl } // namespace aidl