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_PROCPIDSTAT_H_ 18 #define CPP_WATCHDOG_SERVER_SRC_PROCPIDSTAT_H_ 19 20 #include <android-base/result.h> 21 #include <android-base/stringprintf.h> 22 #include <gtest/gtest_prod.h> 23 #include <inttypes.h> 24 #include <stdint.h> 25 #include <utils/Mutex.h> 26 #include <utils/RefBase.h> 27 28 #include <string> 29 #include <unordered_map> 30 #include <vector> 31 32 namespace android { 33 namespace automotive { 34 namespace watchdog { 35 36 using ::android::base::StringPrintf; 37 38 #define PID_FOR_INIT 1 39 40 constexpr const char* kProcDirPath = "/proc"; 41 constexpr const char* kStatFileFormat = "/%" PRIu32 "/stat"; 42 constexpr const char* kTaskDirFormat = "/%" PRIu32 "/task"; 43 constexpr const char* kStatusFileFormat = "/%" PRIu32 "/status"; 44 45 struct PidStat { 46 pid_t pid = 0; 47 std::string comm = ""; 48 std::string state = ""; 49 pid_t ppid = 0; 50 uint64_t majorFaults = 0; 51 uint32_t numThreads = 0; 52 uint64_t startTime = 0; // Useful when identifying PID/TID reuse 53 }; 54 55 struct ProcessStats { 56 int64_t tgid = -1; // -1 indicates a failure to read this value 57 int64_t uid = -1; // -1 indicates a failure to read this value 58 uint64_t vmPeakKb = 0; 59 uint64_t vmSizeKb = 0; 60 uint64_t vmHwmKb = 0; 61 uint64_t vmRssKb = 0; 62 PidStat process = {}; // Aggregated stats across all the threads 63 std::unordered_map<pid_t, PidStat> threads; // Per-thread stat including the main thread 64 }; 65 66 // Collector/parser for `/proc/[pid]/stat`, `/proc/[pid]/task/[tid]/stat` and /proc/[pid]/status` 67 // files. 68 class ProcPidStat : public RefBase { 69 public: 70 explicit ProcPidStat(const std::string& path = kProcDirPath) : 71 mLatestProcessStats({}), 72 mPath(path) { 73 std::string pidStatPath = StringPrintf((mPath + kStatFileFormat).c_str(), PID_FOR_INIT); 74 std::string tidStatPath = StringPrintf((mPath + kTaskDirFormat + kStatFileFormat).c_str(), 75 PID_FOR_INIT, PID_FOR_INIT); 76 std::string pidStatusPath = StringPrintf((mPath + kStatusFileFormat).c_str(), PID_FOR_INIT); 77 78 mEnabled = !access(pidStatPath.c_str(), R_OK) && !access(tidStatPath.c_str(), R_OK) && 79 !access(pidStatusPath.c_str(), R_OK); 80 } 81 ~ProcPidStat()82 virtual ~ProcPidStat() {} 83 84 // Collects per-process stats. 85 virtual android::base::Result<void> collect(); 86 87 // Returns the latest per-process stats collected. latestStats()88 virtual const std::unordered_map<pid_t, ProcessStats> latestStats() const { 89 Mutex::Autolock lock(mMutex); 90 return mLatestProcessStats; 91 } 92 93 // Returns the delta of per-process stats since the last before collection. deltaStats()94 virtual const std::vector<ProcessStats> deltaStats() const { 95 Mutex::Autolock lock(mMutex); 96 return mDeltaProcessStats; 97 } 98 99 // Called by WatchdogPerfService and tests. enabled()100 virtual bool enabled() { return mEnabled; } 101 dirPath()102 virtual std::string dirPath() { return mPath; } 103 104 private: 105 // Reads the contents of the below files: 106 // 1. Pid stat file at |mPath| + |kStatFileFormat| 107 // 2. Aggregated per-process status at |mPath| + |kStatusFileFormat| 108 // 3. Tid stat file at |mPath| + |kTaskDirFormat| + |kStatFileFormat| 109 android::base::Result<std::unordered_map<pid_t, ProcessStats>> getProcessStatsLocked() const; 110 111 // Makes sure only one collection is running at any given time. 112 mutable Mutex mMutex; 113 114 // Latest dump of per-process stats. Useful for calculating the delta and identifying PID/TID 115 // reuse. 116 std::unordered_map<pid_t, ProcessStats> mLatestProcessStats GUARDED_BY(mMutex); 117 118 // Latest delta of per-process stats. 119 std::vector<ProcessStats> mDeltaProcessStats GUARDED_BY(mMutex); 120 121 // True if the below files are accessible: 122 // 1. Pid stat file at |mPath| + |kTaskStatFileFormat| 123 // 2. Tid stat file at |mPath| + |kTaskDirFormat| + |kStatFileFormat| 124 // 3. Pid status file at |mPath| + |kStatusFileFormat| 125 // Otherwise, set to false. 126 bool mEnabled; 127 128 // Proc directory path. Default value is |kProcDirPath|. 129 // Updated by tests to point to a different location when needed. 130 std::string mPath; 131 132 FRIEND_TEST(IoPerfCollectionTest, TestValidProcPidContents); 133 FRIEND_TEST(ProcPidStatTest, TestValidStatFiles); 134 FRIEND_TEST(ProcPidStatTest, TestHandlesProcessTerminationBetweenScanningAndParsing); 135 FRIEND_TEST(ProcPidStatTest, TestHandlesPidTidReuse); 136 }; 137 138 } // namespace watchdog 139 } // namespace automotive 140 } // namespace android 141 142 #endif // CPP_WATCHDOG_SERVER_SRC_PROCPIDSTAT_H_ 143