• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 _LMKD_H_
18 #define _LMKD_H_
19 
20 #include <arpa/inet.h>
21 #include <sys/cdefs.h>
22 #include <sys/types.h>
23 
24 __BEGIN_DECLS
25 
26 /*
27  * Supported LMKD commands
28  */
29 enum lmk_cmd {
30     LMK_TARGET = 0,         /* Associate minfree with oom_adj_score */
31     LMK_PROCPRIO,           /* Register a process and set its oom_adj_score */
32     LMK_PROCREMOVE,         /* Unregister a process */
33     LMK_PROCPURGE,          /* Purge all registered processes */
34     LMK_GETKILLCNT,         /* Get number of kills */
35     LMK_SUBSCRIBE,          /* Subscribe for asynchronous events */
36     LMK_PROCKILL,           /* Unsolicited msg to subscribed clients on proc kills */
37     LMK_UPDATE_PROPS,       /* Reinit properties */
38     LMK_STAT_KILL_OCCURRED, /* Unsolicited msg to subscribed clients on proc kills for statsd log */
39     LMK_START_MONITORING,   /* Start psi monitoring if it was skipped earlier */
40     LMK_BOOT_COMPLETED,     /* Notify LMKD boot is completed */
41     LMK_PROCS_PRIO,         /* Register processes and set the same oom_adj_score */
42 };
43 
44 /*
45  * Max number of targets in LMK_TARGET command.
46  */
47 #define MAX_TARGETS 6
48 
49 /*
50  * Max packet length in bytes.
51  * Longest packet is LMK_TARGET followed by MAX_TARGETS
52  * of minfree and oom_adj_score values
53  */
54 #define CTRL_PACKET_MAX_SIZE (sizeof(int) * (MAX_TARGETS * 2 + 1))
55 
56 /* LMKD packet - first int is lmk_cmd followed by payload */
57 typedef int LMKD_CTRL_PACKET[CTRL_PACKET_MAX_SIZE / sizeof(int)];
58 
59 /* Get LMKD packet command */
lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack)60 static inline enum lmk_cmd lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack) {
61     return (enum lmk_cmd)ntohl(pack[0]);
62 }
63 
64 /* LMK_TARGET packet payload */
65 struct lmk_target {
66     int minfree;
67     int oom_adj_score;
68 };
69 
70 /*
71  * For LMK_TARGET packet get target_idx-th payload.
72  * Warning: no checks performed, caller should ensure valid parameters.
73  */
lmkd_pack_get_target(LMKD_CTRL_PACKET packet,int target_idx,struct lmk_target * target)74 static inline void lmkd_pack_get_target(LMKD_CTRL_PACKET packet, int target_idx,
75                                         struct lmk_target* target) {
76     target->minfree = ntohl(packet[target_idx * 2 + 1]);
77     target->oom_adj_score = ntohl(packet[target_idx * 2 + 2]);
78 }
79 
80 /*
81  * Prepare LMK_TARGET packet and return packet size in bytes.
82  * Warning: no checks performed, caller should ensure valid parameters.
83  */
lmkd_pack_set_target(LMKD_CTRL_PACKET packet,struct lmk_target * targets,size_t target_cnt)84 static inline size_t lmkd_pack_set_target(LMKD_CTRL_PACKET packet, struct lmk_target* targets,
85                                           size_t target_cnt) {
86     int idx = 0;
87     packet[idx++] = htonl(LMK_TARGET);
88     while (target_cnt) {
89         packet[idx++] = htonl(targets->minfree);
90         packet[idx++] = htonl(targets->oom_adj_score);
91         targets++;
92         target_cnt--;
93     }
94     return idx * sizeof(int);
95 }
96 
97 /* Process types for lmk_procprio.ptype */
98 enum proc_type {
99     PROC_TYPE_FIRST,
100     PROC_TYPE_APP = PROC_TYPE_FIRST,
101     PROC_TYPE_SERVICE,
102     PROC_TYPE_COUNT,
103 };
104 
105 /* LMK_PROCPRIO packet payload */
106 struct lmk_procprio {
107     pid_t pid;
108     uid_t uid;
109     int oomadj;
110     enum proc_type ptype;
111 };
112 #define LMK_PROCPRIO_FIELD_COUNT 4
113 #define LMK_PROCPRIO_SIZE (LMK_PROCPRIO_FIELD_COUNT * sizeof(int))
114 
115 /*
116  * For LMK_PROCPRIO packet get its payload.
117  * Warning: no checks performed, caller should ensure valid parameters.
118  */
lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet,int field_count,struct lmk_procprio * params)119 static inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet, int field_count,
120                                           struct lmk_procprio* params) {
121     params->pid = (pid_t)ntohl(packet[1]);
122     params->uid = (uid_t)ntohl(packet[2]);
123     params->oomadj = ntohl(packet[3]);
124     /* if field is missing assume PROC_TYPE_APP for backward compatibility */
125     params->ptype = field_count > 3 ? (enum proc_type)ntohl(packet[4]) : PROC_TYPE_APP;
126 }
127 
128 /*
129  * Prepare LMK_PROCPRIO packet and return packet size in bytes.
130  * Warning: no checks performed, caller should ensure valid parameters.
131  */
lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet,struct lmk_procprio * params)132 static inline size_t lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet, struct lmk_procprio* params) {
133     packet[0] = htonl(LMK_PROCPRIO);
134     packet[1] = htonl(params->pid);
135     packet[2] = htonl(params->uid);
136     packet[3] = htonl(params->oomadj);
137     packet[4] = htonl((int)params->ptype);
138     return 5 * sizeof(int);
139 }
140 
141 /* LMK_PROCREMOVE packet payload */
142 struct lmk_procremove {
143     pid_t pid;
144 };
145 
146 /*
147  * For LMK_PROCREMOVE packet get its payload.
148  * Warning: no checks performed, caller should ensure valid parameters.
149  */
lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet,struct lmk_procremove * params)150 static inline void lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet,
151                                             struct lmk_procremove* params) {
152     params->pid = (pid_t)ntohl(packet[1]);
153 }
154 
155 /*
156  * Prepare LMK_PROCREMOVE packet and return packet size in bytes.
157  * Warning: no checks performed, caller should ensure valid parameters.
158  */
lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,struct lmk_procremove * params)159 static inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,
160                                               struct lmk_procremove* params) {
161     packet[0] = htonl(LMK_PROCREMOVE);
162     packet[1] = htonl(params->pid);
163     return 2 * sizeof(int);
164 }
165 
166 /*
167  * Prepare LMK_PROCPURGE packet and return packet size in bytes.
168  * Warning: no checks performed, caller should ensure valid parameters.
169  */
lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet)170 static inline size_t lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet) {
171     packet[0] = htonl(LMK_PROCPURGE);
172     return sizeof(int);
173 }
174 
175 /* LMK_GETKILLCNT packet payload */
176 struct lmk_getkillcnt {
177     int min_oomadj;
178     int max_oomadj;
179 };
180 
181 /*
182  * For LMK_GETKILLCNT packet get its payload.
183  * Warning: no checks performed, caller should ensure valid parameters.
184  */
lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,struct lmk_getkillcnt * params)185 static inline void lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,
186                                             struct lmk_getkillcnt* params) {
187     params->min_oomadj = ntohl(packet[1]);
188     params->max_oomadj = ntohl(packet[2]);
189 }
190 
191 /*
192  * Prepare LMK_GETKILLCNT packet and return packet size in bytes.
193  * Warning: no checks performed, caller should ensure valid parameters.
194  */
lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,struct lmk_getkillcnt * params)195 static inline size_t lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,
196                                               struct lmk_getkillcnt* params) {
197     packet[0] = htonl(LMK_GETKILLCNT);
198     packet[1] = htonl(params->min_oomadj);
199     packet[2] = htonl(params->max_oomadj);
200     return 3 * sizeof(int);
201 }
202 
203 /*
204  * Prepare LMK_GETKILLCNT reply packet and return packet size in bytes.
205  * Warning: no checks performed, caller should ensure valid parameters.
206  */
lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet,int kill_cnt)207 static inline size_t lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet, int kill_cnt) {
208     packet[0] = htonl(LMK_GETKILLCNT);
209     packet[1] = htonl(kill_cnt);
210     return 2 * sizeof(int);
211 }
212 
213 /* Types of asynchronous events sent from lmkd to its clients */
214 enum async_event_type {
215     LMK_ASYNC_EVENT_FIRST,
216     LMK_ASYNC_EVENT_KILL = LMK_ASYNC_EVENT_FIRST,
217     LMK_ASYNC_EVENT_STAT,
218     LMK_ASYNC_EVENT_COUNT,
219 };
220 
221 /* LMK_SUBSCRIBE packet payload */
222 struct lmk_subscribe {
223     enum async_event_type evt_type;
224 };
225 
226 /*
227  * For LMK_SUBSCRIBE packet get its payload.
228  * Warning: no checks performed, caller should ensure valid parameters.
229  */
lmkd_pack_get_subscribe(LMKD_CTRL_PACKET packet,struct lmk_subscribe * params)230 static inline void lmkd_pack_get_subscribe(LMKD_CTRL_PACKET packet, struct lmk_subscribe* params) {
231     params->evt_type = (enum async_event_type)ntohl(packet[1]);
232 }
233 
234 /**
235  * Prepare LMK_SUBSCRIBE packet and return packet size in bytes.
236  * Warning: no checks performed, caller should ensure valid parameters.
237  */
lmkd_pack_set_subscribe(LMKD_CTRL_PACKET packet,enum async_event_type evt_type)238 static inline size_t lmkd_pack_set_subscribe(LMKD_CTRL_PACKET packet, enum async_event_type evt_type) {
239     packet[0] = htonl(LMK_SUBSCRIBE);
240     packet[1] = htonl((int)evt_type);
241     return 2 * sizeof(int);
242 }
243 
244 /**
245  * Prepare LMK_PROCKILL unsolicited packet and return packet size in bytes.
246  * Warning: no checks performed, caller should ensure valid parameters.
247  */
lmkd_pack_set_prockills(LMKD_CTRL_PACKET packet,pid_t pid,uid_t uid)248 static inline size_t lmkd_pack_set_prockills(LMKD_CTRL_PACKET packet, pid_t pid, uid_t uid) {
249     packet[0] = htonl(LMK_PROCKILL);
250     packet[1] = htonl(pid);
251     packet[2] = htonl(uid);
252     return 3 * sizeof(int);
253 }
254 
255 /*
256  * Prepare LMK_UPDATE_PROPS packet and return packet size in bytes.
257  * Warning: no checks performed, caller should ensure valid parameters.
258  */
lmkd_pack_set_update_props(LMKD_CTRL_PACKET packet)259 static inline size_t lmkd_pack_set_update_props(LMKD_CTRL_PACKET packet) {
260     packet[0] = htonl(LMK_UPDATE_PROPS);
261     return sizeof(int);
262 }
263 
264 /*
265  * Prepare LMK_START_MONITORING packet and return packet size in bytes.
266  * Warning: no checks performed, caller should ensure valid parameters.
267  */
lmkd_pack_start_monitoring(LMKD_CTRL_PACKET packet)268 static inline size_t lmkd_pack_start_monitoring(LMKD_CTRL_PACKET packet) {
269     packet[0] = htonl(LMK_START_MONITORING);
270     return sizeof(int);
271 }
272 
273 /*
274  * Prepare LMK_UPDATE_PROPS reply packet and return packet size in bytes.
275  * Warning: no checks performed, caller should ensure valid parameters.
276  */
lmkd_pack_set_update_props_repl(LMKD_CTRL_PACKET packet,int result)277 static inline size_t lmkd_pack_set_update_props_repl(LMKD_CTRL_PACKET packet, int result) {
278     packet[0] = htonl(LMK_UPDATE_PROPS);
279     packet[1] = htonl(result);
280     return 2 * sizeof(int);
281 }
282 
283 /* LMK_UPDATE_PROPS reply payload */
284 struct lmk_update_props_reply {
285     int result;
286 };
287 
288 /*
289  * For LMK_UPDATE_PROPS reply payload.
290  * Warning: no checks performed, caller should ensure valid parameters.
291  */
lmkd_pack_get_update_props_repl(LMKD_CTRL_PACKET packet,struct lmk_update_props_reply * params)292 static inline void lmkd_pack_get_update_props_repl(LMKD_CTRL_PACKET packet,
293                                           struct lmk_update_props_reply* params) {
294     params->result = ntohl(packet[1]);
295 }
296 
297 /*
298  * Prepare LMK_BOOT_COMPLETED packet and return packet size in bytes.
299  * Warning: no checks performed, caller should ensure valid parameters.
300  */
lmkd_pack_set_boot_completed_notif(LMKD_CTRL_PACKET packet)301 static inline size_t lmkd_pack_set_boot_completed_notif(LMKD_CTRL_PACKET packet) {
302     packet[0] = htonl(LMK_BOOT_COMPLETED);
303     return sizeof(int);
304 }
305 
306 /*
307  * Prepare LMK_BOOT_COMPLETED reply packet and return packet size in bytes.
308  * Warning: no checks performed, caller should ensure valid parameters.
309  */
lmkd_pack_set_boot_completed_notif_repl(LMKD_CTRL_PACKET packet,int result)310 static inline size_t lmkd_pack_set_boot_completed_notif_repl(LMKD_CTRL_PACKET packet, int result) {
311     packet[0] = htonl(LMK_BOOT_COMPLETED);
312     packet[1] = htonl(result);
313     return 2 * sizeof(int);
314 }
315 
316 /* LMK_BOOT_COMPLETED reply payload */
317 struct lmk_boot_completed_notif_reply {
318     int result;
319 };
320 
321 /*
322  * For LMK_BOOT_COMPLETED reply payload.
323  * Warning: no checks performed, caller should ensure valid parameters.
324  */
lmkd_pack_get_boot_completed_notif_repl(LMKD_CTRL_PACKET packet,struct lmk_boot_completed_notif_reply * params)325 static inline void lmkd_pack_get_boot_completed_notif_repl(
326         LMKD_CTRL_PACKET packet, struct lmk_boot_completed_notif_reply* params) {
327     params->result = ntohl(packet[1]);
328 }
329 
330 #define PROCS_PRIO_MAX_RECORD_COUNT (CTRL_PACKET_MAX_SIZE / LMK_PROCPRIO_SIZE)
331 
332 struct lmk_procs_prio {
333     struct lmk_procprio procs[PROCS_PRIO_MAX_RECORD_COUNT];
334 };
335 
336 /*
337  * For LMK_PROCS_PRIO packet get its payload.
338  * Warning: no checks performed, caller should ensure valid parameters.
339  */
lmkd_pack_get_procs_prio(LMKD_CTRL_PACKET packet,struct lmk_procs_prio * params,const int field_count)340 static inline int lmkd_pack_get_procs_prio(LMKD_CTRL_PACKET packet, struct lmk_procs_prio* params,
341                                            const int field_count) {
342     if (field_count < LMK_PROCPRIO_FIELD_COUNT || (field_count % LMK_PROCPRIO_FIELD_COUNT) != 0)
343         return -1;
344     const int procs_count = (field_count / LMK_PROCPRIO_FIELD_COUNT);
345 
346     /* Start packet at 1 since 0 is cmd type */
347     int packetIdx = 1;
348     for (int procs_idx = 0; procs_idx < procs_count; procs_idx++) {
349         params->procs[procs_idx].pid = (pid_t)ntohl(packet[packetIdx++]);
350         params->procs[procs_idx].uid = (uid_t)ntohl(packet[packetIdx++]);
351         params->procs[procs_idx].oomadj = ntohl(packet[packetIdx++]);
352         params->procs[procs_idx].ptype = (enum proc_type)ntohl(packet[packetIdx++]);
353     }
354 
355     return procs_count;
356 }
357 
358 /*
359  * Prepare LMK_PROCS_PRIO packet and return packet size in bytes.
360  * Warning: no checks performed, caller should ensure valid parameters.
361  */
lmkd_pack_set_procs_prio(LMKD_CTRL_PACKET packet,struct lmk_procs_prio * params,const int procs_count)362 static inline size_t lmkd_pack_set_procs_prio(LMKD_CTRL_PACKET packet,
363                                               struct lmk_procs_prio* params,
364                                               const int procs_count) {
365     packet[0] = htonl(LMK_PROCS_PRIO);
366     int packetIdx = 1;
367 
368     for (int i = 0; i < procs_count; i++) {
369         packet[packetIdx++] = htonl(params->procs[i].pid);
370         packet[packetIdx++] = htonl(params->procs[i].uid);
371         packet[packetIdx++] = htonl(params->procs[i].oomadj);
372         packet[packetIdx++] = htonl((int)params->procs[i].ptype);
373     }
374 
375     return packetIdx * sizeof(int);
376 }
377 
378 __END_DECLS
379 
380 #endif /* _LMKD_H_ */
381