/* * Copyright (c) 2014 Google, Inc. All Rights Reserved. * Copyright (c) 2015 NVIDIA, Inc. All Rights Reserved. * */ #include "timed_qos_manager.h" #include <fcntl.h> #include <assert.h> #undef LOG_TAG #define LOG_TAG "powerHAL::TimedQosManager" void SysfsQosObject::enter() { sysfs_write(mNodeName, mEnterCmd); } void SysfsQosObject::exit() { sysfs_write(mNodeName, mExitCmd); } bool TimedQosManager::threadLoop() { AutoMutex lock(mLock); ALOGI("threadLoop [%s] starting\n", mName); while (1) { if (exitPending()) { ALOGV("threadLoop [%s] exiting\n", mName); break; } if (mTargetTime == 0) { // wait for something to do ALOGV("threadLoop [%s] nothing to do, waiting\n", mName); mCondition.wait(mLock); ALOGV("threadLoop [%s] woke from wait\n", mName); } else { // open qos file if not already open mQosObject->enter(); // wait for target time to expire nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); ALOGV("threadLoop [%s] waiting with relative time %lld\n", mName, mTargetTime - currentTime); mCondition.waitRelative(mLock, mTargetTime - currentTime); // check if we're done. if not (typically because // someone extended our time while we were blocked) // just loop again and sleep until new target time currentTime = systemTime(SYSTEM_TIME_MONOTONIC); if (currentTime >= mTargetTime) { mQosObject->exit(); mTargetTime = 0; } else { ALOGV("threadLoop [%s] timeout extended\n"); } } } return false; } void TimedQosManager::requestTimedQos(nsecs_t reltime) { AutoMutex lock(mLock); nsecs_t targetTime = systemTime() + reltime; /* new target time should always be ahead of current one */ assert(mTargetTime <= targetTime); mTargetTime = targetTime; ALOGV("threadLoop [%s] requesting reltime %lld, mTargetTime set to %lld\n", mName, reltime, mTargetTime); /* wake the Thread. if it's already waiting on a different * timeout, this will just wake it early and it'll wait again. */ mCondition.signal(Condition::WAKE_UP_ALL); }