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 WATCHDOG_SERVER_SRC_PROCPIDSTAT_H_ 18 #define 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 uint32_t pid = 0; 47 std::string comm = ""; 48 std::string state = ""; 49 uint32_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 PidStat process = {}; // Aggregated stats across all the threads 59 std::unordered_map<uint32_t, PidStat> threads; // Per-thread stat including the main thread 60 }; 61 62 // Collector/parser for `/proc/[pid]/stat`, `/proc/[pid]/task/[tid]/stat` and /proc/[pid]/status` 63 // files. 64 class ProcPidStat : public RefBase { 65 public: 66 explicit ProcPidStat(const std::string& path = kProcDirPath) : 67 mLastProcessStats({}), mPath(path) { 68 std::string pidStatPath = StringPrintf((mPath + kStatFileFormat).c_str(), PID_FOR_INIT); 69 std::string tidStatPath = StringPrintf((mPath + kTaskDirFormat + kStatFileFormat).c_str(), 70 PID_FOR_INIT, PID_FOR_INIT); 71 std::string pidStatusPath = StringPrintf((mPath + kStatusFileFormat).c_str(), PID_FOR_INIT); 72 73 mEnabled = !access(pidStatPath.c_str(), R_OK) && !access(tidStatPath.c_str(), R_OK) && 74 !access(pidStatusPath.c_str(), R_OK); 75 } 76 ~ProcPidStat()77 virtual ~ProcPidStat() {} 78 79 // Collects pid info delta since the last collection. 80 virtual android::base::Result<std::vector<ProcessStats>> collect(); 81 82 // Called by IoPerfCollection and tests. enabled()83 virtual bool enabled() { return mEnabled; } 84 dirPath()85 virtual std::string dirPath() { return mPath; } 86 87 private: 88 // Reads the contents of the below files: 89 // 1. Pid stat file at |mPath| + |kStatFileFormat| 90 // 2. Tid stat file at |mPath| + |kTaskDirFormat| + |kStatFileFormat| 91 android::base::Result<std::unordered_map<uint32_t, ProcessStats>> getProcessStatsLocked() const; 92 93 // Reads the tgid and real UID for the given PID from |mPath| + |kStatusFileFormat|. 94 android::base::Result<void> getPidStatusLocked(ProcessStats* processStats) const; 95 96 // Makes sure only one collection is running at any given time. 97 Mutex mMutex; 98 99 // Last dump of per-process stats. Useful for calculating the delta and identifying PID/TID 100 // reuse. 101 std::unordered_map<uint32_t, ProcessStats> mLastProcessStats GUARDED_BY(mMutex); 102 103 // True if the below files are accessible: 104 // 1. Pid stat file at |mPath| + |kTaskStatFileFormat| 105 // 2. Tid stat file at |mPath| + |kTaskDirFormat| + |kStatFileFormat| 106 // 3. Pid status file at |mPath| + |kStatusFileFormat| 107 // Otherwise, set to false. 108 bool mEnabled; 109 110 // Proc directory path. Default value is |kProcDirPath|. 111 // Updated by tests to point to a different location when needed. 112 std::string mPath; 113 114 FRIEND_TEST(IoPerfCollectionTest, TestValidProcPidContents); 115 FRIEND_TEST(ProcPidStatTest, TestValidStatFiles); 116 FRIEND_TEST(ProcPidStatTest, TestHandlesProcessTerminationBetweenScanningAndParsing); 117 FRIEND_TEST(ProcPidStatTest, TestHandlesPidTidReuse); 118 }; 119 120 } // namespace watchdog 121 } // namespace automotive 122 } // namespace android 123 124 #endif // WATCHDOG_SERVER_SRC_PROCPIDSTAT_H_ 125