1 /*
2  * Copyright (C) 2018 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  *      https://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  /*
18   * rss_hwm_reset clears the RSS high-water mark counters for all currently
19   * running processes. It writes "5" to /proc/PID/clear_refs for every PID.
20   *
21   * It runs in its own process becuase dac_override capability is required
22   * in order to write to other processes' clear_refs.
23   *
24   * It is invoked from a system service by flipping sys.rss_hwm_reset.on
25   * property to "1".
26   */
27 
28 #define LOG_TAG "rss_hwm_reset"
29 
30 #include <dirent.h>
31 
32 #include <string>
33 
34 #include <android-base/file.h>
35 #include <android-base/stringprintf.h>
36 #include <log/log.h>
37 
38 namespace {
39 // Resets RSS HWM counter for the selected process by writing 5 to
40 // /proc/PID/clear_refs.
reset_rss_hwm(const char * pid)41 void reset_rss_hwm(const char* pid) {
42     std::string clear_refs_path =
43             ::android::base::StringPrintf("/proc/%s/clear_refs", pid);
44     ::android::base::WriteStringToFile("5", clear_refs_path);
45 }
46 }
47 
48 // Clears RSS HWM counters for all currently running processes.
main(int,char **)49 int main(int /* argc */, char** /* argv[] */) {
50     DIR* dirp = opendir("/proc");
51     if (dirp == nullptr) {
52         ALOGE("unable to read /proc");
53         return 1;
54     }
55     struct dirent* entry;
56     while ((entry = readdir(dirp)) != nullptr) {
57         // Skip entries that are not directories.
58         if (entry->d_type != DT_DIR) continue;
59         // Skip entries that do not contain only numbers.
60         const char* pid = entry->d_name;
61         while (*pid) {
62             if (*pid < '0' || *pid > '9') break;
63             pid++;
64         }
65         if (*pid != 0) continue;
66 
67         pid = entry->d_name;
68         reset_rss_hwm(pid);
69     }
70     closedir(dirp);
71     return 0;
72 }
73