1 /*
2 * Copyright 2018 Google, Inc
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 _STATSLOG_H_
18 #define _STATSLOG_H_
19
20 #include <lmkd.h>
21
22 #include <assert.h>
23 #include <inttypes.h>
24 #include <stdbool.h>
25 #include <sys/cdefs.h>
26 #include <sys/types.h>
27
28 #include <cutils/properties.h>
29
30 __BEGIN_DECLS
31
32 #define MAX_TASKNAME_LEN 128
33
34 /*
35 * Max LMKD reply packet length in bytes
36 * Notes about size calculation:
37 * 4 bytes for packet type
38 * 88 bytes for the LmkKillOccurred fields: memory_stat + kill_stat
39 * 2 bytes for process name string size
40 * MAX_TASKNAME_LEN bytes for the process name string
41 *
42 * Must be in sync with LmkdConnection.java
43 */
44 #define LMKD_REPLY_MAX_SIZE 222
45
46 /* LMK_MEMORY_STATS packet payload */
47 struct memory_stat {
48 int64_t pgfault;
49 int64_t pgmajfault;
50 int64_t rss_in_bytes;
51 int64_t cache_in_bytes;
52 int64_t swap_in_bytes;
53 int64_t process_start_time_ns;
54 };
55
56 // If you update this, also update the corresponding stats enum mapping and LmkdStatsReporter.java
57 enum kill_reasons {
58 NONE = -1, /* To denote no kill condition */
59 PRESSURE_AFTER_KILL = 0,
60 NOT_RESPONDING,
61 LOW_SWAP_AND_THRASHING,
62 LOW_MEM_AND_SWAP,
63 LOW_MEM_AND_THRASHING,
64 DIRECT_RECL_AND_THRASHING,
65 LOW_MEM_AND_SWAP_UTIL,
66 LOW_FILECACHE_AFTER_THRASHING,
67 LOW_MEM,
68 DIRECT_RECL_STUCK,
69 KILL_REASON_COUNT
70 };
71
72 /* LMK_KILL_STAT packet payload */
73 struct kill_stat {
74 int32_t uid;
75 const char *taskname;
76 enum kill_reasons kill_reason;
77 int32_t oom_score;
78 int32_t min_oom_score;
79 int64_t free_mem_kb;
80 int64_t free_swap_kb;
81 int32_t thrashing;
82 int32_t max_thrashing;
83 };
84
85 /* LMKD reply packet to hold data for the LmkKillOccurred statsd atom */
86 typedef char LMK_KILL_OCCURRED_PACKET[LMKD_REPLY_MAX_SIZE];
87
88 #ifdef LMKD_LOG_STATS
89
90 #define PROC_STAT_FILE_PATH "/proc/%d/stat"
91 #define PROC_STAT_BUFFER_SIZE 1024
92 #define BYTES_IN_KILOBYTE 1024
93
94 /**
95 * Produces packet with the event when LMKD kills a process to reduce memory pressure.
96 * Code: LMK_KILL_OCCURRED = 51
97 */
98 size_t lmkd_pack_set_kill_occurred(LMK_KILL_OCCURRED_PACKET packet,
99 struct kill_stat *kill_st,
100 struct memory_stat *mem_st);
101
102 /**
103 * Reads memory stats used to log the statsd atom. Returns non-null ptr on success.
104 */
105 struct memory_stat *stats_read_memory_stat(bool per_app_memcg, int pid, uid_t uid,
106 int64_t rss_bytes, int64_t swap_bytes);
107
108 /**
109 * Registers a process taskname by pid, while it is still alive.
110 */
111 void stats_store_taskname(int pid, const char* taskname);
112
113 /**
114 * Unregister all process tasknames.
115 */
116 void stats_purge_tasknames();
117
118 /**
119 * Unregister a process taskname, e.g. after it has been killed.
120 */
121 void stats_remove_taskname(int pid);
122
123 const char* stats_get_task_name(int pid);
124
125 #else /* LMKD_LOG_STATS */
126
127 static inline size_t
lmkd_pack_set_kill_occurred(LMK_KILL_OCCURRED_PACKET packet __unused,struct kill_stat * kill_st __unused,struct memory_stat * mem_st __unused)128 lmkd_pack_set_kill_occurred(LMK_KILL_OCCURRED_PACKET packet __unused,
129 struct kill_stat *kill_st __unused,
130 struct memory_stat *mem_st __unused) {
131 return -EINVAL;
132 }
133
stats_read_memory_stat(bool per_app_memcg __unused,int pid __unused,uid_t uid __unused,int64_t rss_bytes __unused,int64_t swap_bytes __unused)134 static inline struct memory_stat *stats_read_memory_stat(bool per_app_memcg __unused,
135 int pid __unused, uid_t uid __unused,
136 int64_t rss_bytes __unused, int64_t swap_bytes __unused) {
137 return NULL;
138 }
139
stats_store_taskname(int pid __unused,const char * taskname __unused)140 static inline void stats_store_taskname(int pid __unused, const char* taskname __unused) {}
141
stats_purge_tasknames()142 static inline void stats_purge_tasknames() {}
143
stats_remove_taskname(int pid __unused)144 static inline void stats_remove_taskname(int pid __unused) {}
145
stats_get_task_name(int pid __unused)146 static inline const char* stats_get_task_name(int pid __unused) { return NULL; }
147
148 #endif /* LMKD_LOG_STATS */
149
150 __END_DECLS
151
152 #endif /* _STATSLOG_H_ */
153