• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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