1 /* 2 * Copyright (c) 2020, 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 specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef CPP_WATCHDOG_SERVER_SRC_UIDPROCSTATSCOLLECTOR_H_ 18 #define CPP_WATCHDOG_SERVER_SRC_UIDPROCSTATSCOLLECTOR_H_ 19 20 #include <android-base/result.h> 21 #include <android-base/stringprintf.h> 22 #include <gtest/gtest_prod.h> 23 #include <utils/Mutex.h> 24 #include <utils/RefBase.h> 25 26 #include <inttypes.h> 27 #include <stdint.h> 28 #include <unistd.h> 29 30 #include <string> 31 #include <unordered_map> 32 #include <vector> 33 34 namespace android { 35 namespace automotive { 36 namespace watchdog { 37 38 using ::android::base::StringPrintf; 39 40 #define PID_FOR_INIT 1 41 42 constexpr const char kProcDirPath[] = "/proc"; 43 constexpr const char kStatFileFormat[] = "/%" PRIu32 "/stat"; 44 constexpr const char kTaskDirFormat[] = "/%" PRIu32 "/task"; 45 constexpr const char kStatusFileFormat[] = "/%" PRIu32 "/status"; 46 constexpr const char kTimeInStateFormat[] = "/%" PRIu32 "/time_in_state"; 47 // Per-pid/tid stats. 48 // The int64_t type is used due to AIDL limitations representing long field values. 49 struct PidStat { 50 std::string comm = ""; 51 std::string state = ""; 52 int64_t startTimeMillis = 0; 53 int64_t cpuTimeMillis = 0; 54 uint64_t majorFaults = 0; 55 }; 56 57 // Per-process stats. 58 struct ProcessStats { 59 std::string comm = ""; 60 int64_t startTimeMillis = 0; // Useful when identifying PID reuse 61 int64_t cpuTimeMillis = 0; 62 // Stats in below fields are aggregated across all threads 63 uint64_t totalCpuCycles = 0; 64 uint64_t totalMajorFaults = 0; 65 int totalTasksCount = 0; 66 int ioBlockedTasksCount = 0; 67 std::unordered_map<pid_t, uint64_t> cpuCyclesByTid = {}; 68 std::string toString() const; 69 }; 70 71 // Per-UID stats. 72 struct UidProcStats { 73 int64_t cpuTimeMillis = 0; 74 uint64_t cpuCycles = 0; 75 uint64_t totalMajorFaults = 0; 76 int totalTasksCount = 0; 77 int ioBlockedTasksCount = 0; 78 std::unordered_map<pid_t, ProcessStats> processStatsByPid = {}; 79 std::string toString() const; 80 }; 81 82 // Collector/parser for `/proc/[pid]/stat`, `/proc/[pid]/task/[tid]/stat` and /proc/[pid]/status` 83 // files. 84 class UidProcStatsCollectorInterface : public RefBase { 85 public: 86 // Initializes the collector. 87 virtual void init() = 0; 88 // Collects the per-uid stats from /proc directory. 89 virtual android::base::Result<void> collect() = 0; 90 // Returns the latest per-uid process stats. 91 virtual const std::unordered_map<uid_t, UidProcStats> latestStats() const = 0; 92 // Returns the delta of per-uid process stats since the last before collection. 93 virtual const std::unordered_map<uid_t, UidProcStats> deltaStats() const = 0; 94 // Returns true only when the /proc files for the init process are accessible. 95 virtual bool enabled() const = 0; 96 // Returns the /proc files common ancestor directory path. 97 virtual const std::string dirPath() const = 0; 98 }; 99 100 class UidProcStatsCollector final : public UidProcStatsCollectorInterface { 101 public: 102 explicit UidProcStatsCollector(const std::string& path = kProcDirPath) : sysconf(_SC_CLK_TCK)103 mMillisPerClockTick(1000 / sysconf(_SC_CLK_TCK)), 104 mPath(path), 105 mLatestStats({}), 106 mDeltaStats({}) {} 107 ~UidProcStatsCollector()108 ~UidProcStatsCollector() {} 109 110 void init() override; 111 112 android::base::Result<void> collect() override; 113 latestStats()114 const std::unordered_map<uid_t, UidProcStats> latestStats() const { 115 Mutex::Autolock lock(mMutex); 116 return mLatestStats; 117 } 118 deltaStats()119 const std::unordered_map<uid_t, UidProcStats> deltaStats() const { 120 Mutex::Autolock lock(mMutex); 121 return mDeltaStats; 122 } 123 enabled()124 bool enabled() const { 125 Mutex::Autolock lock(mMutex); 126 return mEnabled; 127 } 128 dirPath()129 const std::string dirPath() const { return mPath; } 130 131 static android::base::Result<PidStat> readStatFileForPid(pid_t pid); 132 133 static android::base::Result<std::tuple<uid_t, pid_t>> readPidStatusFileForPid(pid_t pid); 134 135 private: 136 android::base::Result<std::unordered_map<uid_t, UidProcStats>> readUidProcStatsLocked() const; 137 138 // Reads the contents of the below files: 139 // 1. Pid stat file at |mPath| + |kStatFileFormat| 140 // 2. Aggregated per-process status at |mPath| + |kStatusFileFormat| 141 // 3. Tid stat file at |mPath| + |kTaskDirFormat| + |kStatFileFormat| 142 android::base::Result<std::tuple<uid_t, ProcessStats>> readProcessStatsLocked(pid_t pid) const; 143 144 // Number of milliseconds per clock cycle. 145 int32_t mMillisPerClockTick; 146 147 // Proc directory path. Default value is |kProcDirPath|. 148 // Updated by tests to point to a different location when needed. 149 std::string mPath; 150 151 // Makes sure only one collection is running at any given time. 152 mutable Mutex mMutex; 153 154 // True if the below files are accessible: 155 // 1. Pid stat file at |mPath| + |kTaskStatFileFormat| 156 // 2. Tid stat file at |mPath| + |kTaskDirFormat| + |kStatFileFormat| 157 // 3. Pid status file at |mPath| + |kStatusFileFormat| 158 // Otherwise, set to false. 159 bool mEnabled GUARDED_BY(mMutex); 160 161 // True if the tid time_in_state file at 162 // |mPath| + |kTaskDirFormat| + |kTimeInStateFormat| is available. 163 bool mTimeInStateEnabled GUARDED_BY(mMutex); 164 165 // Latest dump of per-UID stats. 166 std::unordered_map<uid_t, UidProcStats> mLatestStats GUARDED_BY(mMutex); 167 168 // Latest delta of per-uid stats. 169 std::unordered_map<uid_t, UidProcStats> mDeltaStats GUARDED_BY(mMutex); 170 171 FRIEND_TEST(PerformanceProfilerTest, TestValidProcPidContents); 172 FRIEND_TEST(UidProcStatsCollectorTest, TestValidStatFiles); 173 FRIEND_TEST(UidProcStatsCollectorTest, TestHandlesProcessTerminationBetweenScanningAndParsing); 174 FRIEND_TEST(UidProcStatsCollectorTest, TestHandlesPidTidReuse); 175 }; 176 177 } // namespace watchdog 178 } // namespace automotive 179 } // namespace android 180 181 #endif // CPP_WATCHDOG_SERVER_SRC_UIDPROCSTATSCOLLECTOR_H_ 182