diff options
-rw-r--r-- | lmkd/Android.bp | 15 | ||||
-rw-r--r-- | lmkd/include/liblmkd_utils.h | 54 | ||||
-rw-r--r-- | lmkd/include/lmkd.h | 147 | ||||
-rw-r--r-- | lmkd/liblmkd_utils.c | 76 | ||||
-rw-r--r-- | lmkd/lmkd.c | 100 |
5 files changed, 343 insertions, 49 deletions
diff --git a/lmkd/Android.bp b/lmkd/Android.bp index 76d308a3c..d172755bd 100644 --- a/lmkd/Android.bp +++ b/lmkd/Android.bp | |||
@@ -6,6 +6,7 @@ cc_binary { | |||
6 | "liblog", | 6 | "liblog", |
7 | "libcutils", | 7 | "libcutils", |
8 | ], | 8 | ], |
9 | local_include_dirs: ["include"], | ||
9 | cflags: ["-Werror"], | 10 | cflags: ["-Werror"], |
10 | 11 | ||
11 | init_rc: ["lmkd.rc"], | 12 | init_rc: ["lmkd.rc"], |
@@ -18,3 +19,17 @@ cc_binary { | |||
18 | }, | 19 | }, |
19 | }, | 20 | }, |
20 | } | 21 | } |
22 | |||
23 | cc_library_static { | ||
24 | name: "liblmkd_utils", | ||
25 | srcs: ["liblmkd_utils.c"], | ||
26 | shared_libs: [ | ||
27 | "libcutils", | ||
28 | ], | ||
29 | export_include_dirs: ["include"], | ||
30 | cppflags: [ | ||
31 | "-g", | ||
32 | "-Wall", | ||
33 | "-Werror", | ||
34 | ] | ||
35 | } | ||
diff --git a/lmkd/include/liblmkd_utils.h b/lmkd/include/liblmkd_utils.h new file mode 100644 index 000000000..72e3f4a2b --- /dev/null +++ b/lmkd/include/liblmkd_utils.h | |||
@@ -0,0 +1,54 @@ | |||
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 _LIBLMKD_UTILS_H_ | ||
18 | #define _LIBLMKD_UTILS_H_ | ||
19 | |||
20 | #include <sys/cdefs.h> | ||
21 | #include <sys/types.h> | ||
22 | |||
23 | #include <lmkd.h> | ||
24 | |||
25 | __BEGIN_DECLS | ||
26 | |||
27 | /* | ||
28 | * Connects to lmkd process and returns socket handle. | ||
29 | * On success returns socket handle. | ||
30 | * On error, -1 is returned, and errno is set appropriately. | ||
31 | */ | ||
32 | int lmkd_connect(); | ||
33 | |||
34 | /* | ||
35 | * Registers a process with lmkd and sets its oomadj score. | ||
36 | * On success returns 0. | ||
37 | * On error, -1 is returned. | ||
38 | * In the case of error errno is set appropriately. | ||
39 | */ | ||
40 | int lmkd_register_proc(int sock, struct lmk_procprio *params); | ||
41 | |||
42 | /* | ||
43 | * Creates memcg directory for given process. | ||
44 | * On success returns 0. | ||
45 | * -1 is returned if path creation failed. | ||
46 | * -2 is returned if tasks file open operation failed. | ||
47 | * -3 is returned if tasks file write operation failed. | ||
48 | * In the case of error errno is set appropriately. | ||
49 | */ | ||
50 | int create_memcg(uid_t uid, pid_t pid); | ||
51 | |||
52 | __END_DECLS | ||
53 | |||
54 | #endif /* _LIBLMKD_UTILS_H_ */ | ||
diff --git a/lmkd/include/lmkd.h b/lmkd/include/lmkd.h new file mode 100644 index 000000000..fe6364d82 --- /dev/null +++ b/lmkd/include/lmkd.h | |||
@@ -0,0 +1,147 @@ | |||
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 | }; | ||
34 | |||
35 | /* | ||
36 | * Max number of targets in LMK_TARGET command. | ||
37 | */ | ||
38 | #define MAX_TARGETS 6 | ||
39 | |||
40 | /* | ||
41 | * Max packet length in bytes. | ||
42 | * Longest packet is LMK_TARGET followed by MAX_TARGETS | ||
43 | * of minfree and oom_adj_score values | ||
44 | */ | ||
45 | #define CTRL_PACKET_MAX_SIZE (sizeof(int) * (MAX_TARGETS * 2 + 1)) | ||
46 | |||
47 | /* LMKD packet - first int is lmk_cmd followed by payload */ | ||
48 | typedef int LMKD_CTRL_PACKET[CTRL_PACKET_MAX_SIZE / sizeof(int)]; | ||
49 | |||
50 | /* Get LMKD packet command */ | ||
51 | inline enum lmk_cmd lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack) { | ||
52 | return (enum lmk_cmd)ntohl(pack[0]); | ||
53 | } | ||
54 | |||
55 | /* LMK_TARGET packet payload */ | ||
56 | struct lmk_target { | ||
57 | int minfree; | ||
58 | int oom_adj_score; | ||
59 | }; | ||
60 | |||
61 | /* | ||
62 | * For LMK_TARGET packet get target_idx-th payload. | ||
63 | * Warning: no checks performed, caller should ensure valid parameters. | ||
64 | */ | ||
65 | inline void lmkd_pack_get_target(LMKD_CTRL_PACKET packet, | ||
66 | int target_idx, struct lmk_target *target) { | ||
67 | target->minfree = ntohl(packet[target_idx * 2 + 1]); | ||
68 | target->oom_adj_score = ntohl(packet[target_idx * 2 + 2]); | ||
69 | } | ||
70 | |||
71 | /* | ||
72 | * Prepare LMK_TARGET packet and return packet size in bytes. | ||
73 | * Warning: no checks performed, caller should ensure valid parameters. | ||
74 | */ | ||
75 | inline size_t lmkd_pack_set_target(LMKD_CTRL_PACKET packet, | ||
76 | struct lmk_target *targets, | ||
77 | size_t target_cnt) { | ||
78 | int idx = 0; | ||
79 | packet[idx++] = htonl(LMK_TARGET); | ||
80 | while (target_cnt) { | ||
81 | packet[idx++] = htonl(targets->minfree); | ||
82 | packet[idx++] = htonl(targets->oom_adj_score); | ||
83 | targets++; | ||
84 | target_cnt--; | ||
85 | } | ||
86 | return idx * sizeof(int); | ||
87 | } | ||
88 | |||
89 | /* LMK_PROCPRIO packet payload */ | ||
90 | struct lmk_procprio { | ||
91 | pid_t pid; | ||
92 | uid_t uid; | ||
93 | int oomadj; | ||
94 | }; | ||
95 | |||
96 | /* | ||
97 | * For LMK_PROCPRIO packet get its payload. | ||
98 | * Warning: no checks performed, caller should ensure valid parameters. | ||
99 | */ | ||
100 | inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet, | ||
101 | struct lmk_procprio *params) { | ||
102 | params->pid = (pid_t)ntohl(packet[1]); | ||
103 | params->uid = (uid_t)ntohl(packet[2]); | ||
104 | params->oomadj = ntohl(packet[3]); | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * Prepare LMK_PROCPRIO packet and return packet size in bytes. | ||
109 | * Warning: no checks performed, caller should ensure valid parameters. | ||
110 | */ | ||
111 | inline size_t lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet, | ||
112 | struct lmk_procprio *params) { | ||
113 | packet[0] = htonl(LMK_PROCPRIO); | ||
114 | packet[1] = htonl(params->pid); | ||
115 | packet[2] = htonl(params->uid); | ||
116 | packet[3] = htonl(params->oomadj); | ||
117 | return 4 * sizeof(int); | ||
118 | } | ||
119 | |||
120 | /* LMK_PROCREMOVE packet payload */ | ||
121 | struct lmk_procremove { | ||
122 | pid_t pid; | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * For LMK_PROCREMOVE packet get its payload. | ||
127 | * Warning: no checks performed, caller should ensure valid parameters. | ||
128 | */ | ||
129 | inline void lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet, | ||
130 | struct lmk_procremove *params) { | ||
131 | params->pid = (pid_t)ntohl(packet[1]); | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * Prepare LMK_PROCREMOVE packet and return packet size in bytes. | ||
136 | * Warning: no checks performed, caller should ensure valid parameters. | ||
137 | */ | ||
138 | inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet, | ||
139 | struct lmk_procprio *params) { | ||
140 | packet[0] = htonl(LMK_PROCREMOVE); | ||
141 | packet[1] = htonl(params->pid); | ||
142 | return 2 * sizeof(int); | ||
143 | } | ||
144 | |||
145 | __END_DECLS | ||
146 | |||
147 | #endif /* _LMKD_H_ */ | ||
diff --git a/lmkd/liblmkd_utils.c b/lmkd/liblmkd_utils.c new file mode 100644 index 000000000..fa3b7a920 --- /dev/null +++ b/lmkd/liblmkd_utils.c | |||
@@ -0,0 +1,76 @@ | |||
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 | #include <errno.h> | ||
18 | #include <fcntl.h> | ||
19 | #include <sys/cdefs.h> | ||
20 | #include <sys/stat.h> | ||
21 | #include <sys/types.h> | ||
22 | #include <stdio.h> | ||
23 | #include <unistd.h> | ||
24 | |||
25 | #include <liblmkd_utils.h> | ||
26 | #include <cutils/sockets.h> | ||
27 | |||
28 | int lmkd_connect() { | ||
29 | return socket_local_client("lmkd", | ||
30 | ANDROID_SOCKET_NAMESPACE_RESERVED, | ||
31 | SOCK_SEQPACKET); | ||
32 | } | ||
33 | |||
34 | int lmkd_register_proc(int sock, struct lmk_procprio *params) { | ||
35 | LMKD_CTRL_PACKET packet; | ||
36 | size_t size; | ||
37 | int ret; | ||
38 | |||
39 | size = lmkd_pack_set_procprio(packet, params); | ||
40 | ret = TEMP_FAILURE_RETRY(write(sock, packet, size)); | ||
41 | |||
42 | return (ret < 0) ? -1 : 0; | ||
43 | } | ||
44 | |||
45 | int create_memcg(uid_t uid, pid_t pid) { | ||
46 | char buf[256]; | ||
47 | int tasks_file; | ||
48 | int written; | ||
49 | |||
50 | snprintf(buf, sizeof(buf), "/dev/memcg/apps/uid_%u", uid); | ||
51 | if (mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 && | ||
52 | errno != EEXIST) { | ||
53 | return -1; | ||
54 | } | ||
55 | |||
56 | snprintf(buf, sizeof(buf), "/dev/memcg/apps/uid_%u/pid_%u", uid, pid); | ||
57 | if (mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0 && | ||
58 | errno != EEXIST) { | ||
59 | return -1; | ||
60 | } | ||
61 | |||
62 | snprintf(buf, sizeof(buf), "/dev/memcg/apps/uid_%u/pid_%u/tasks", uid, pid); | ||
63 | tasks_file = open(buf, O_WRONLY); | ||
64 | if (tasks_file < 0) { | ||
65 | return -2; | ||
66 | } | ||
67 | written = snprintf(buf, sizeof(buf), "%u", pid); | ||
68 | if (__predict_false(written >= (int)sizeof(buf))) { | ||
69 | written = sizeof(buf) - 1; | ||
70 | } | ||
71 | written = TEMP_FAILURE_RETRY(write(tasks_file, buf, written)); | ||
72 | close(tasks_file); | ||
73 | |||
74 | return (written < 0) ? -3 : 0; | ||
75 | } | ||
76 | |||
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c index 2a7fedb44..45fa863b2 100644 --- a/lmkd/lmkd.c +++ b/lmkd/lmkd.c | |||
@@ -16,7 +16,6 @@ | |||
16 | 16 | ||
17 | #define LOG_TAG "lowmemorykiller" | 17 | #define LOG_TAG "lowmemorykiller" |
18 | 18 | ||
19 | #include <arpa/inet.h> | ||
20 | #include <errno.h> | 19 | #include <errno.h> |
21 | #include <inttypes.h> | 20 | #include <inttypes.h> |
22 | #include <sched.h> | 21 | #include <sched.h> |
@@ -34,6 +33,7 @@ | |||
34 | 33 | ||
35 | #include <cutils/properties.h> | 34 | #include <cutils/properties.h> |
36 | #include <cutils/sockets.h> | 35 | #include <cutils/sockets.h> |
36 | #include <lmkd.h> | ||
37 | #include <log/log.h> | 37 | #include <log/log.h> |
38 | 38 | ||
39 | /* | 39 | /* |
@@ -71,19 +71,6 @@ | |||
71 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) | 71 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) |
72 | #define EIGHT_MEGA (1 << 23) | 72 | #define EIGHT_MEGA (1 << 23) |
73 | 73 | ||
74 | enum lmk_cmd { | ||
75 | LMK_TARGET, | ||
76 | LMK_PROCPRIO, | ||
77 | LMK_PROCREMOVE, | ||
78 | }; | ||
79 | |||
80 | #define MAX_TARGETS 6 | ||
81 | /* | ||
82 | * longest is LMK_TARGET followed by MAX_TARGETS each minfree and minkillprio | ||
83 | * values | ||
84 | */ | ||
85 | #define CTRL_PACKET_MAX (sizeof(int) * (MAX_TARGETS * 2 + 1)) | ||
86 | |||
87 | /* default to old in-kernel interface if no memory pressure events */ | 74 | /* default to old in-kernel interface if no memory pressure events */ |
88 | static int use_inkernel_interface = 1; | 75 | static int use_inkernel_interface = 1; |
89 | static bool has_inkernel_module; | 76 | static bool has_inkernel_module; |
@@ -300,45 +287,49 @@ static void writefilestring(const char *path, char *s) { | |||
300 | close(fd); | 287 | close(fd); |
301 | } | 288 | } |
302 | 289 | ||
303 | static void cmd_procprio(int pid, int uid, int oomadj) { | 290 | static void cmd_procprio(LMKD_CTRL_PACKET packet) { |
304 | struct proc *procp; | 291 | struct proc *procp; |
305 | char path[80]; | 292 | char path[80]; |
306 | char val[20]; | 293 | char val[20]; |
307 | int soft_limit_mult; | 294 | int soft_limit_mult; |
295 | struct lmk_procprio params; | ||
296 | |||
297 | lmkd_pack_get_procprio(packet, ¶ms); | ||
308 | 298 | ||
309 | if (oomadj < OOM_SCORE_ADJ_MIN || oomadj > OOM_SCORE_ADJ_MAX) { | 299 | if (params.oomadj < OOM_SCORE_ADJ_MIN || |
310 | ALOGE("Invalid PROCPRIO oomadj argument %d", oomadj); | 300 | params.oomadj > OOM_SCORE_ADJ_MAX) { |
301 | ALOGE("Invalid PROCPRIO oomadj argument %d", params.oomadj); | ||
311 | return; | 302 | return; |
312 | } | 303 | } |
313 | 304 | ||
314 | snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", pid); | 305 | snprintf(path, sizeof(path), "/proc/%d/oom_score_adj", params.pid); |
315 | snprintf(val, sizeof(val), "%d", oomadj); | 306 | snprintf(val, sizeof(val), "%d", params.oomadj); |
316 | writefilestring(path, val); | 307 | writefilestring(path, val); |
317 | 308 | ||
318 | if (use_inkernel_interface) | 309 | if (use_inkernel_interface) |
319 | return; | 310 | return; |
320 | 311 | ||
321 | if (oomadj >= 900) { | 312 | if (params.oomadj >= 900) { |
322 | soft_limit_mult = 0; | 313 | soft_limit_mult = 0; |
323 | } else if (oomadj >= 800) { | 314 | } else if (params.oomadj >= 800) { |
324 | soft_limit_mult = 0; | 315 | soft_limit_mult = 0; |
325 | } else if (oomadj >= 700) { | 316 | } else if (params.oomadj >= 700) { |
326 | soft_limit_mult = 0; | 317 | soft_limit_mult = 0; |
327 | } else if (oomadj >= 600) { | 318 | } else if (params.oomadj >= 600) { |
328 | // Launcher should be perceptible, don't kill it. | 319 | // Launcher should be perceptible, don't kill it. |
329 | oomadj = 200; | 320 | params.oomadj = 200; |
330 | soft_limit_mult = 1; | 321 | soft_limit_mult = 1; |
331 | } else if (oomadj >= 500) { | 322 | } else if (params.oomadj >= 500) { |
332 | soft_limit_mult = 0; | 323 | soft_limit_mult = 0; |
333 | } else if (oomadj >= 400) { | 324 | } else if (params.oomadj >= 400) { |
334 | soft_limit_mult = 0; | 325 | soft_limit_mult = 0; |
335 | } else if (oomadj >= 300) { | 326 | } else if (params.oomadj >= 300) { |
336 | soft_limit_mult = 1; | 327 | soft_limit_mult = 1; |
337 | } else if (oomadj >= 200) { | 328 | } else if (params.oomadj >= 200) { |
338 | soft_limit_mult = 2; | 329 | soft_limit_mult = 2; |
339 | } else if (oomadj >= 100) { | 330 | } else if (params.oomadj >= 100) { |
340 | soft_limit_mult = 10; | 331 | soft_limit_mult = 10; |
341 | } else if (oomadj >= 0) { | 332 | } else if (params.oomadj >= 0) { |
342 | soft_limit_mult = 20; | 333 | soft_limit_mult = 20; |
343 | } else { | 334 | } else { |
344 | // Persistent processes will have a large | 335 | // Persistent processes will have a large |
@@ -346,11 +337,13 @@ static void cmd_procprio(int pid, int uid, int oomadj) { | |||
346 | soft_limit_mult = 64; | 337 | soft_limit_mult = 64; |
347 | } | 338 | } |
348 | 339 | ||
349 | snprintf(path, sizeof(path), "/dev/memcg/apps/uid_%d/pid_%d/memory.soft_limit_in_bytes", uid, pid); | 340 | snprintf(path, sizeof(path), |
341 | "/dev/memcg/apps/uid_%d/pid_%d/memory.soft_limit_in_bytes", | ||
342 | params.uid, params.pid); | ||
350 | snprintf(val, sizeof(val), "%d", soft_limit_mult * EIGHT_MEGA); | 343 | snprintf(val, sizeof(val), "%d", soft_limit_mult * EIGHT_MEGA); |
351 | writefilestring(path, val); | 344 | writefilestring(path, val); |
352 | 345 | ||
353 | procp = pid_lookup(pid); | 346 | procp = pid_lookup(params.pid); |
354 | if (!procp) { | 347 | if (!procp) { |
355 | procp = malloc(sizeof(struct proc)); | 348 | procp = malloc(sizeof(struct proc)); |
356 | if (!procp) { | 349 | if (!procp) { |
@@ -358,33 +351,38 @@ static void cmd_procprio(int pid, int uid, int oomadj) { | |||
358 | return; | 351 | return; |
359 | } | 352 | } |
360 | 353 | ||
361 | procp->pid = pid; | 354 | procp->pid = params.pid; |
362 | procp->uid = uid; | 355 | procp->uid = params.uid; |
363 | procp->oomadj = oomadj; | 356 | procp->oomadj = params.oomadj; |
364 | proc_insert(procp); | 357 | proc_insert(procp); |
365 | } else { | 358 | } else { |
366 | proc_unslot(procp); | 359 | proc_unslot(procp); |
367 | procp->oomadj = oomadj; | 360 | procp->oomadj = params.oomadj; |
368 | proc_slot(procp); | 361 | proc_slot(procp); |
369 | } | 362 | } |
370 | } | 363 | } |
371 | 364 | ||
372 | static void cmd_procremove(int pid) { | 365 | static void cmd_procremove(LMKD_CTRL_PACKET packet) { |
366 | struct lmk_procremove params; | ||
367 | |||
373 | if (use_inkernel_interface) | 368 | if (use_inkernel_interface) |
374 | return; | 369 | return; |
375 | 370 | ||
376 | pid_remove(pid); | 371 | lmkd_pack_get_procremove(packet, ¶ms); |
372 | pid_remove(params.pid); | ||
377 | } | 373 | } |
378 | 374 | ||
379 | static void cmd_target(int ntargets, int *params) { | 375 | static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) { |
380 | int i; | 376 | int i; |
377 | struct lmk_target target; | ||
381 | 378 | ||
382 | if (ntargets > (int)ARRAY_SIZE(lowmem_adj)) | 379 | if (ntargets > (int)ARRAY_SIZE(lowmem_adj)) |
383 | return; | 380 | return; |
384 | 381 | ||
385 | for (i = 0; i < ntargets; i++) { | 382 | for (i = 0; i < ntargets; i++) { |
386 | lowmem_minfree[i] = ntohl(*params++); | 383 | lmkd_pack_get_target(packet, i, &target); |
387 | lowmem_adj[i] = ntohl(*params++); | 384 | lowmem_minfree[i] = target.minfree; |
385 | lowmem_adj[i] = target.oom_adj_score; | ||
388 | } | 386 | } |
389 | 387 | ||
390 | lowmem_targets_size = ntargets; | 388 | lowmem_targets_size = ntargets; |
@@ -445,38 +443,42 @@ static int ctrl_data_read(int dsock_idx, char *buf, size_t bufsz) { | |||
445 | } | 443 | } |
446 | 444 | ||
447 | static void ctrl_command_handler(int dsock_idx) { | 445 | static void ctrl_command_handler(int dsock_idx) { |
448 | int ibuf[CTRL_PACKET_MAX / sizeof(int)]; | 446 | LMKD_CTRL_PACKET packet; |
449 | int len; | 447 | int len; |
450 | int cmd = -1; | 448 | enum lmk_cmd cmd; |
451 | int nargs; | 449 | int nargs; |
452 | int targets; | 450 | int targets; |
453 | 451 | ||
454 | len = ctrl_data_read(dsock_idx, (char *)ibuf, CTRL_PACKET_MAX); | 452 | len = ctrl_data_read(dsock_idx, (char *)packet, CTRL_PACKET_MAX_SIZE); |
455 | if (len <= 0) | 453 | if (len <= 0) |
456 | return; | 454 | return; |
457 | 455 | ||
456 | if (len < (int)sizeof(int)) { | ||
457 | ALOGE("Wrong control socket read length len=%d", len); | ||
458 | return; | ||
459 | } | ||
460 | |||
461 | cmd = lmkd_pack_get_cmd(packet); | ||
458 | nargs = len / sizeof(int) - 1; | 462 | nargs = len / sizeof(int) - 1; |
459 | if (nargs < 0) | 463 | if (nargs < 0) |
460 | goto wronglen; | 464 | goto wronglen; |
461 | 465 | ||
462 | cmd = ntohl(ibuf[0]); | ||
463 | |||
464 | switch(cmd) { | 466 | switch(cmd) { |
465 | case LMK_TARGET: | 467 | case LMK_TARGET: |
466 | targets = nargs / 2; | 468 | targets = nargs / 2; |
467 | if (nargs & 0x1 || targets > (int)ARRAY_SIZE(lowmem_adj)) | 469 | if (nargs & 0x1 || targets > (int)ARRAY_SIZE(lowmem_adj)) |
468 | goto wronglen; | 470 | goto wronglen; |
469 | cmd_target(targets, &ibuf[1]); | 471 | cmd_target(targets, packet); |
470 | break; | 472 | break; |
471 | case LMK_PROCPRIO: | 473 | case LMK_PROCPRIO: |
472 | if (nargs != 3) | 474 | if (nargs != 3) |
473 | goto wronglen; | 475 | goto wronglen; |
474 | cmd_procprio(ntohl(ibuf[1]), ntohl(ibuf[2]), ntohl(ibuf[3])); | 476 | cmd_procprio(packet); |
475 | break; | 477 | break; |
476 | case LMK_PROCREMOVE: | 478 | case LMK_PROCREMOVE: |
477 | if (nargs != 1) | 479 | if (nargs != 1) |
478 | goto wronglen; | 480 | goto wronglen; |
479 | cmd_procremove(ntohl(ibuf[1])); | 481 | cmd_procremove(packet); |
480 | break; | 482 | break; |
481 | default: | 483 | default: |
482 | ALOGE("Received unknown command code %d", cmd); | 484 | ALOGE("Received unknown command code %d", cmd); |