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 
enter()13 void SysfsQosObject::enter()
14 {
15     sysfs_write(mNodeName, mEnterCmd);
16 }
17 
exit()18 void SysfsQosObject::exit()
19 {
20     sysfs_write(mNodeName, mExitCmd);
21 }
22 
threadLoop()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 
requestTimedQos(nsecs_t reltime)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