1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specic language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_LIBPERFMGR_NODELOOPERTHREAD_H_ 18 #define ANDROID_LIBPERFMGR_NODELOOPERTHREAD_H_ 19 20 #include <utils/Thread.h> 21 22 #include <cstddef> 23 #include <memory> 24 #include <string> 25 #include <utility> 26 #include <vector> 27 28 #include "perfmgr/Node.h" 29 30 namespace android { 31 namespace perfmgr { 32 33 // The NodeAction specifies the sysfs node, the value to be assigned, and the 34 // timeout for this action: 35 struct NodeAction { NodeActionNodeAction36 NodeAction(std::size_t node_index, std::size_t value_index, 37 std::chrono::milliseconds timeout_ms) 38 : node_index(node_index), 39 value_index(value_index), 40 timeout_ms(timeout_ms) {} 41 std::size_t node_index; 42 std::size_t value_index; 43 std::chrono::milliseconds timeout_ms; // 0ms for forever 44 }; 45 46 // The NodeLooperThread is responsible for managing each of the sysfs nodes 47 // specified in the configuration. At initialization, the NodeLooperThrea holds 48 // a vector containing the nodes defined in the configuration. The NodeManager 49 // gets powerhint requests and cancellations from the HintManager, maintains 50 // state about the current set of powerhint requests on each sysfs node, and 51 // decides how to apply the requests. The NodeLooperThread contains a ThreadLoop 52 // to maintain the sysfs nodes, and that thread is woken up both to handle 53 // powerhint requests and when the timeout expires for an in-progress powerhint. 54 class NodeLooperThread : public ::android::Thread { 55 public: NodeLooperThread(std::vector<std::unique_ptr<Node>> nodes)56 explicit NodeLooperThread(std::vector<std::unique_ptr<Node>> nodes) 57 : Thread(false), nodes_(std::move(nodes)) {} ~NodeLooperThread()58 virtual ~NodeLooperThread() { Stop(); } 59 60 // Need call Stop() as the threadloop will hold a strong pointer 61 // itself and wait for Condition fired or timeout (60s) before 62 // the out looper can call deconstructor to Stop() thread 63 void Stop(); 64 65 // Return true when successfully adds request from actions for the hint_type 66 // in each individual node. Return false if any of the actions has either 67 // invalid node index or value index. 68 bool Request(const std::vector<NodeAction>& actions, 69 const std::string& hint_type); 70 // Return when successfully cancels request from actions for the hint_type 71 // in each individual node. Return false if any of the actions has invalid 72 // node index. 73 bool Cancel(const std::vector<NodeAction>& actions, 74 const std::string& hint_type); 75 76 // Dump all nodes to fd 77 void DumpToFd(int fd); 78 79 // Return true when successfully started the looper thread 80 bool Start(); 81 82 private: 83 NodeLooperThread(NodeLooperThread const&) = delete; 84 void operator=(NodeLooperThread const&) = delete; 85 bool threadLoop() override; 86 87 static constexpr auto kMaxUpdatePeriod = std::chrono::milliseconds::max(); 88 89 std::vector<std::unique_ptr<Node>> nodes_; // parsed from Config 90 91 // conditional variable from C++ standard library can be affected by wall 92 // time change as it is using CLOCK_REAL (b/35756266). The component should 93 // not be impacted by wall time, thus need use Android specific Condition 94 // class for waking up threadloop. 95 ::android::Condition wake_cond_; 96 97 // lock to protect nodes_ 98 ::android::Mutex lock_; 99 }; 100 101 } // namespace perfmgr 102 } // namespace android 103 104 #endif // ANDROID_LIBPERFMGR_NODELOOPERTHREAD_H_ 105