/*
* 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);
}