1 /* 2 * Copyright (c) 2014 Google, Inc. All Rights Reserved. 3 * Copyright (c) 2015 NVIDIA, Inc. All Rights Reserved. 4 * 5 */ 6 #include "timed_qos_manager.h" 7 #include <fcntl.h> 8 #include <assert.h> 9 10 #undef LOG_TAG 11 #define LOG_TAG "powerHAL::TimedQosManager" 12 13 void SysfsQosObject::enter() 14 { 15 sysfs_write(mNodeName, mEnterCmd); 16 } 17 18 void SysfsQosObject::exit() 19 { 20 sysfs_write(mNodeName, mExitCmd); 21 } 22 23 bool TimedQosManager::threadLoop() 24 { 25 AutoMutex lock(mLock); 26 27 ALOGI("threadLoop [%s] starting\n", mName); 28 29 while (1) { 30 if (exitPending()) { 31 ALOGV("threadLoop [%s] exiting\n", mName); 32 break; 33 } 34 if (mTargetTime == 0) { 35 // wait for something to do 36 ALOGV("threadLoop [%s] nothing to do, waiting\n", mName); 37 mCondition.wait(mLock); 38 ALOGV("threadLoop [%s] woke from wait\n", mName); 39 } else { 40 // open qos file if not already open 41 mQosObject->enter(); 42 43 // wait for target time to expire 44 nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC); 45 ALOGV("threadLoop [%s] waiting with relative time %lld\n", 46 mName, mTargetTime - currentTime); 47 mCondition.waitRelative(mLock, mTargetTime - currentTime); 48 49 // check if we're done. if not (typically because 50 // someone extended our time while we were blocked) 51 // just loop again and sleep until new target time 52 currentTime = systemTime(SYSTEM_TIME_MONOTONIC); 53 if (currentTime >= mTargetTime) { 54 mQosObject->exit(); 55 mTargetTime = 0; 56 } else { 57 ALOGV("threadLoop [%s] timeout extended\n"); 58 } 59 } 60 } 61 return false; 62 } 63 64 void TimedQosManager::requestTimedQos(nsecs_t reltime) 65 { 66 AutoMutex lock(mLock); 67 nsecs_t targetTime = systemTime() + reltime; 68 69 /* new target time should always be ahead of current one */ 70 assert(mTargetTime <= targetTime); 71 mTargetTime = targetTime; 72 ALOGV("threadLoop [%s] requesting reltime %lld, mTargetTime set to %lld\n", 73 mName, reltime, mTargetTime); 74 75 /* wake the Thread. if it's already waiting on a different 76 * timeout, this will just wake it early and it'll wait again. 77 */ 78 mCondition.signal(Condition::WAKE_UP_ALL); 79 } 80