Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 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 <assert.h> |
| 18 | #include <errno.h> |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 19 | #include <log/log_id.h> |
Yao Chen | 389aee1 | 2018-05-02 11:19:27 -0700 | [diff] [blame] | 20 | #include <stats_event_list.h> |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 21 | #include <statslog.h> |
| 22 | #include <stdlib.h> |
| 23 | #include <string.h> |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 24 | #include <stdlib.h> |
| 25 | #include <string.h> |
Yao Chen | 389aee1 | 2018-05-02 11:19:27 -0700 | [diff] [blame] | 26 | #include <time.h> |
| 27 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 28 | #ifdef LMKD_LOG_STATS |
| 29 | |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 30 | #define LINE_MAX 128 |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 31 | #define STRINGIFY(x) STRINGIFY_INTERNAL(x) |
| 32 | #define STRINGIFY_INTERNAL(x) #x |
| 33 | |
| 34 | static bool enable_stats_log; |
| 35 | static android_log_context log_ctx; |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 36 | |
| 37 | struct proc { |
| 38 | int pid; |
| 39 | char taskname[LINE_MAX]; |
| 40 | struct proc* pidhash_next; |
| 41 | }; |
| 42 | |
| 43 | #define PIDHASH_SZ 1024 |
| 44 | static struct proc** pidhash = NULL; |
| 45 | #define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1)) |
| 46 | |
Yao Chen | 389aee1 | 2018-05-02 11:19:27 -0700 | [diff] [blame] | 47 | static int64_t getElapsedRealTimeNs() { |
| 48 | struct timespec t; |
| 49 | t.tv_sec = t.tv_nsec = 0; |
| 50 | clock_gettime(CLOCK_BOOTTIME, &t); |
| 51 | return (int64_t)t.tv_sec * 1000000000LL + t.tv_nsec; |
| 52 | } |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 53 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 54 | void statslog_init() { |
| 55 | enable_stats_log = property_get_bool("ro.lmk.log_stats", false); |
| 56 | |
| 57 | if (enable_stats_log) { |
| 58 | log_ctx = create_android_logger(kStatsEventTag); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | void statslog_destroy() { |
| 63 | if (log_ctx) { |
| 64 | android_log_destroy(&log_ctx); |
| 65 | } |
| 66 | } |
| 67 | |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 68 | /** |
| 69 | * Logs the change in LMKD state which is used as start/stop boundaries for logging |
| 70 | * LMK_KILL_OCCURRED event. |
| 71 | * Code: LMK_STATE_CHANGED = 54 |
| 72 | */ |
| 73 | int |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 74 | stats_write_lmk_state_changed(int32_t code, int32_t state) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 75 | int ret = -EINVAL; |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 76 | |
| 77 | if (!enable_stats_log) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 78 | return ret; |
| 79 | } |
| 80 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 81 | assert(log_ctx != NULL); |
| 82 | if (!log_ctx) { |
Yao Chen | 389aee1 | 2018-05-02 11:19:27 -0700 | [diff] [blame] | 83 | return ret; |
| 84 | } |
| 85 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 86 | reset_log_context(log_ctx); |
| 87 | |
| 88 | if ((ret = android_log_write_int64(log_ctx, getElapsedRealTimeNs())) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 89 | return ret; |
| 90 | } |
| 91 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 92 | if ((ret = android_log_write_int32(log_ctx, code)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 93 | return ret; |
| 94 | } |
Yao Chen | 389aee1 | 2018-05-02 11:19:27 -0700 | [diff] [blame] | 95 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 96 | if ((ret = android_log_write_int32(log_ctx, state)) < 0) { |
| 97 | return ret; |
| 98 | } |
| 99 | |
| 100 | return write_to_logger(log_ctx, LOG_ID_STATS); |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 101 | } |
| 102 | |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 103 | static struct proc* pid_lookup(int pid) { |
| 104 | struct proc* procp; |
| 105 | |
| 106 | if (!pidhash) return NULL; |
| 107 | |
| 108 | for (procp = pidhash[pid_hashfn(pid)]; procp && procp->pid != pid; procp = procp->pidhash_next) |
| 109 | ; |
| 110 | |
| 111 | return procp; |
| 112 | } |
| 113 | |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 114 | /** |
| 115 | * Logs the event when LMKD kills a process to reduce memory pressure. |
| 116 | * Code: LMK_KILL_OCCURRED = 51 |
| 117 | */ |
| 118 | int |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 119 | stats_write_lmk_kill_occurred(int32_t code, int32_t uid, char const* process_name, |
| 120 | int32_t oom_score, int32_t min_oom_score, int tasksize, |
| 121 | struct memory_stat *mem_st) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 122 | int ret = -EINVAL; |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 123 | if (!enable_stats_log) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 124 | return ret; |
| 125 | } |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 126 | if (!log_ctx) { |
| 127 | return ret; |
| 128 | } |
| 129 | reset_log_context(log_ctx); |
Yao Chen | 389aee1 | 2018-05-02 11:19:27 -0700 | [diff] [blame] | 130 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 131 | if ((ret = android_log_write_int64(log_ctx, getElapsedRealTimeNs())) < 0) { |
Yao Chen | 389aee1 | 2018-05-02 11:19:27 -0700 | [diff] [blame] | 132 | return ret; |
| 133 | } |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 134 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 135 | if ((ret = android_log_write_int32(log_ctx, code)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 136 | return ret; |
| 137 | } |
| 138 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 139 | if ((ret = android_log_write_int32(log_ctx, uid)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 140 | return ret; |
| 141 | } |
| 142 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 143 | if ((ret = android_log_write_string8(log_ctx, (process_name == NULL) ? "" : process_name)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 144 | return ret; |
| 145 | } |
| 146 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 147 | if ((ret = android_log_write_int32(log_ctx, oom_score)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 148 | return ret; |
| 149 | } |
| 150 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 151 | if ((ret = android_log_write_int64(log_ctx, mem_st ? mem_st->pgfault : -1)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 152 | return ret; |
| 153 | } |
| 154 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 155 | if ((ret = android_log_write_int64(log_ctx, mem_st ? mem_st->pgmajfault : -1)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 156 | return ret; |
| 157 | } |
| 158 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 159 | if ((ret = android_log_write_int64(log_ctx, mem_st ? mem_st->rss_in_bytes |
| 160 | : tasksize * BYTES_IN_KILOBYTE)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 161 | return ret; |
| 162 | } |
| 163 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 164 | if ((ret = android_log_write_int64(log_ctx, mem_st ? mem_st->cache_in_bytes : -1)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 165 | return ret; |
| 166 | } |
| 167 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 168 | if ((ret = android_log_write_int64(log_ctx, mem_st ? mem_st->swap_in_bytes : -1)) < 0) { |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 169 | return ret; |
| 170 | } |
| 171 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 172 | if ((ret = android_log_write_int64(log_ctx, mem_st ? mem_st->process_start_time_ns |
| 173 | : -1)) < 0) { |
Jim Blackler | 1417cdb | 2018-11-21 16:22:36 +0000 | [diff] [blame] | 174 | return ret; |
| 175 | } |
| 176 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 177 | if ((ret = android_log_write_int32(log_ctx, min_oom_score)) < 0) { |
Suren Baghdasaryan | ec5e4c6 | 2019-03-04 11:07:39 -0800 | [diff] [blame] | 178 | return ret; |
| 179 | } |
| 180 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 181 | return write_to_logger(log_ctx, LOG_ID_STATS); |
Rajeev Kumar | f0216a8 | 2018-01-24 14:40:36 -0800 | [diff] [blame] | 182 | } |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 183 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 184 | static int stats_write_lmk_kill_occurred_pid(int32_t code, int32_t uid, int pid, |
| 185 | int32_t oom_score, int32_t min_oom_score, int tasksize, |
| 186 | struct memory_stat *mem_st) { |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 187 | struct proc* proc = pid_lookup(pid); |
| 188 | if (!proc) return -EINVAL; |
| 189 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 190 | return stats_write_lmk_kill_occurred(code, uid, proc->taskname, oom_score, min_oom_score, |
| 191 | tasksize, mem_st); |
| 192 | } |
| 193 | |
| 194 | static void memory_stat_parse_line(char* line, struct memory_stat* mem_st) { |
| 195 | char key[LINE_MAX + 1]; |
| 196 | int64_t value; |
| 197 | |
| 198 | sscanf(line, "%" STRINGIFY(LINE_MAX) "s %" SCNd64 "", key, &value); |
| 199 | |
| 200 | if (strcmp(key, "total_") < 0) { |
| 201 | return; |
| 202 | } |
| 203 | |
| 204 | if (!strcmp(key, "total_pgfault")) |
| 205 | mem_st->pgfault = value; |
| 206 | else if (!strcmp(key, "total_pgmajfault")) |
| 207 | mem_st->pgmajfault = value; |
| 208 | else if (!strcmp(key, "total_rss")) |
| 209 | mem_st->rss_in_bytes = value; |
| 210 | else if (!strcmp(key, "total_cache")) |
| 211 | mem_st->cache_in_bytes = value; |
| 212 | else if (!strcmp(key, "total_swap")) |
| 213 | mem_st->swap_in_bytes = value; |
| 214 | } |
| 215 | |
| 216 | static int memory_stat_from_cgroup(struct memory_stat* mem_st, int pid, uid_t uid) { |
| 217 | FILE *fp; |
| 218 | char buf[PATH_MAX]; |
| 219 | |
| 220 | snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid); |
| 221 | |
| 222 | fp = fopen(buf, "r"); |
| 223 | |
| 224 | if (fp == NULL) { |
| 225 | return -1; |
| 226 | } |
| 227 | |
| 228 | while (fgets(buf, PAGE_SIZE, fp) != NULL) { |
| 229 | memory_stat_parse_line(buf, mem_st); |
| 230 | } |
| 231 | fclose(fp); |
| 232 | |
| 233 | return 0; |
| 234 | } |
| 235 | |
| 236 | static int memory_stat_from_procfs(struct memory_stat* mem_st, int pid) { |
| 237 | char path[PATH_MAX]; |
| 238 | char buffer[PROC_STAT_BUFFER_SIZE]; |
| 239 | int fd, ret; |
| 240 | |
| 241 | snprintf(path, sizeof(path), PROC_STAT_FILE_PATH, pid); |
| 242 | if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) { |
| 243 | return -1; |
| 244 | } |
| 245 | |
| 246 | ret = read(fd, buffer, sizeof(buffer)); |
| 247 | if (ret < 0) { |
| 248 | close(fd); |
| 249 | return -1; |
| 250 | } |
| 251 | close(fd); |
| 252 | |
| 253 | // field 10 is pgfault |
| 254 | // field 12 is pgmajfault |
| 255 | // field 22 is starttime |
| 256 | // field 24 is rss_in_pages |
| 257 | int64_t pgfault = 0, pgmajfault = 0, starttime = 0, rss_in_pages = 0; |
| 258 | if (sscanf(buffer, |
| 259 | "%*u %*s %*s %*d %*d %*d %*d %*d %*d %" SCNd64 " %*d " |
| 260 | "%" SCNd64 " %*d %*u %*u %*d %*d %*d %*d %*d %*d " |
| 261 | "%" SCNd64 " %*d %" SCNd64 "", |
| 262 | &pgfault, &pgmajfault, &starttime, &rss_in_pages) != 4) { |
| 263 | return -1; |
| 264 | } |
| 265 | mem_st->pgfault = pgfault; |
| 266 | mem_st->pgmajfault = pgmajfault; |
| 267 | mem_st->rss_in_bytes = (rss_in_pages * PAGE_SIZE); |
| 268 | mem_st->process_start_time_ns = starttime * (NS_PER_SEC / sysconf(_SC_CLK_TCK)); |
| 269 | |
| 270 | return 0; |
| 271 | } |
| 272 | |
| 273 | struct memory_stat *stats_read_memory_stat(bool per_app_memcg, int pid, uid_t uid) { |
| 274 | static struct memory_stat mem_st = {}; |
| 275 | |
| 276 | if (!enable_stats_log) { |
| 277 | return NULL; |
| 278 | } |
| 279 | |
| 280 | if (per_app_memcg) { |
| 281 | if (memory_stat_from_cgroup(&mem_st, pid, uid) == 0) { |
| 282 | return &mem_st; |
| 283 | } |
| 284 | } else { |
| 285 | if (memory_stat_from_procfs(&mem_st, pid) == 0) { |
| 286 | return &mem_st; |
| 287 | } |
| 288 | } |
| 289 | |
| 290 | return NULL; |
| 291 | } |
| 292 | |
| 293 | static void poll_kernel(int poll_fd) { |
| 294 | if (poll_fd == -1) { |
| 295 | // not waiting |
| 296 | return; |
| 297 | } |
| 298 | |
| 299 | while (1) { |
| 300 | char rd_buf[256]; |
| 301 | int bytes_read = |
| 302 | TEMP_FAILURE_RETRY(pread(poll_fd, (void*)rd_buf, sizeof(rd_buf), 0)); |
| 303 | if (bytes_read <= 0) break; |
| 304 | rd_buf[bytes_read] = '\0'; |
| 305 | |
| 306 | int64_t pid; |
| 307 | int64_t uid; |
| 308 | int64_t group_leader_pid; |
| 309 | int64_t rss_in_pages; |
| 310 | struct memory_stat mem_st = {}; |
| 311 | int16_t oom_score_adj; |
| 312 | int16_t min_score_adj; |
| 313 | int64_t starttime; |
| 314 | char* taskname = 0; |
| 315 | |
| 316 | int fields_read = sscanf(rd_buf, |
| 317 | "%" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 |
| 318 | " %" SCNd64 " %" SCNd16 " %" SCNd16 " %" SCNd64 "\n%m[^\n]", |
| 319 | &pid, &uid, &group_leader_pid, &mem_st.pgfault, |
| 320 | &mem_st.pgmajfault, &rss_in_pages, &oom_score_adj, |
| 321 | &min_score_adj, &starttime, &taskname); |
| 322 | |
| 323 | /* only the death of the group leader process is logged */ |
| 324 | if (fields_read == 10 && group_leader_pid == pid) { |
| 325 | mem_st.process_start_time_ns = starttime * (NS_PER_SEC / sysconf(_SC_CLK_TCK)); |
| 326 | mem_st.rss_in_bytes = rss_in_pages * PAGE_SIZE; |
| 327 | stats_write_lmk_kill_occurred_pid(LMK_KILL_OCCURRED, uid, pid, oom_score_adj, |
| 328 | min_score_adj, 0, &mem_st); |
| 329 | } |
| 330 | |
| 331 | free(taskname); |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | bool init_poll_kernel(struct kernel_poll_info *poll_info) { |
| 336 | if (!enable_stats_log) { |
| 337 | return false; |
| 338 | } |
| 339 | |
| 340 | poll_info->poll_fd = |
| 341 | TEMP_FAILURE_RETRY(open("/proc/lowmemorykiller", O_RDONLY | O_NONBLOCK | O_CLOEXEC)); |
| 342 | |
| 343 | if (poll_info->poll_fd < 0) { |
| 344 | ALOGE("kernel lmk event file could not be opened; errno=%d", errno); |
| 345 | return false; |
| 346 | } |
| 347 | poll_info->handler = poll_kernel; |
| 348 | |
| 349 | return true; |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 350 | } |
| 351 | |
| 352 | static void proc_insert(struct proc* procp) { |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 353 | if (!pidhash) { |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 354 | pidhash = calloc(PIDHASH_SZ, sizeof(struct proc)); |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 355 | } |
| 356 | |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 357 | int hval = pid_hashfn(procp->pid); |
| 358 | procp->pidhash_next = pidhash[hval]; |
| 359 | pidhash[hval] = procp; |
| 360 | } |
| 361 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 362 | void stats_remove_taskname(int pid, int poll_fd) { |
| 363 | if (!enable_stats_log || !pidhash) { |
| 364 | return; |
| 365 | } |
| 366 | |
| 367 | /* |
| 368 | * Perform an extra check before the pid is removed, after which it |
| 369 | * will be impossible for poll_kernel to get the taskname. poll_kernel() |
| 370 | * is potentially a long-running blocking function; however this method |
| 371 | * handles AMS requests but does not block AMS. |
| 372 | */ |
| 373 | poll_kernel(poll_fd); |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 374 | |
| 375 | int hval = pid_hashfn(pid); |
| 376 | struct proc* procp; |
| 377 | struct proc* prevp; |
| 378 | |
| 379 | for (procp = pidhash[hval], prevp = NULL; procp && procp->pid != pid; |
| 380 | procp = procp->pidhash_next) |
| 381 | prevp = procp; |
| 382 | |
| 383 | if (!procp) |
| 384 | return; |
| 385 | |
| 386 | if (!prevp) |
| 387 | pidhash[hval] = procp->pidhash_next; |
| 388 | else |
| 389 | prevp->pidhash_next = procp->pidhash_next; |
| 390 | |
| 391 | free(procp); |
| 392 | } |
| 393 | |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 394 | void stats_store_taskname(int pid, const char* taskname, int poll_fd) { |
| 395 | if (!enable_stats_log) { |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 396 | return; |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 397 | } |
| 398 | |
| 399 | struct proc* procp = pid_lookup(pid); |
| 400 | if (procp != NULL) { |
| 401 | if (strcmp(procp->taskname, taskname) == 0) { |
| 402 | return; |
| 403 | } |
| 404 | stats_remove_taskname(pid, poll_fd); |
| 405 | } |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 406 | procp = malloc(sizeof(struct proc)); |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 407 | procp->pid = pid; |
| 408 | strncpy(procp->taskname, taskname, LINE_MAX - 1); |
| 409 | procp->taskname[LINE_MAX - 1] = '\0'; |
| 410 | proc_insert(procp); |
| 411 | } |
| 412 | |
| 413 | void stats_purge_tasknames() { |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 414 | if (!enable_stats_log || !pidhash) { |
| 415 | return; |
| 416 | } |
| 417 | |
Jim Blackler | d2da814 | 2019-09-10 15:30:05 +0100 | [diff] [blame] | 418 | struct proc* procp; |
| 419 | struct proc* next; |
| 420 | int i; |
| 421 | for (i = 0; i < PIDHASH_SZ; i++) { |
| 422 | procp = pidhash[i]; |
| 423 | while (procp) { |
| 424 | next = procp->pidhash_next; |
| 425 | free(procp); |
| 426 | procp = next; |
| 427 | } |
| 428 | } |
| 429 | memset(pidhash, 0, PIDHASH_SZ * sizeof(struct proc)); |
| 430 | } |
Suren Baghdasaryan | b72c665 | 2019-09-04 19:12:29 -0700 | [diff] [blame] | 431 | |
| 432 | #endif /* LMKD_LOG_STATS */ |