util: kernel: Make getting further information from smaps files 94/276594/3
authorDongwoo Lee <dwoo08.lee@samsung.com>
Mon, 20 Jun 2022 11:16:27 +0000 (20:16 +0900)
committerDongwoo Lee <dwoo08.lee@samsung.com>
Wed, 29 Jun 2022 04:21:36 +0000 (13:21 +0900)
Now, kernel_get_thread_group_map_info() function can get gpu memory
information by retrieving section has the name of gpu device.

If the gpu memory information is not required, using smaps rather
harms performance, callee must specified whether gpu memory is
required, unless smaps_rollup is used if it is supported.

Change-Id: Ibe17aea337645ca6312df9472c252d962f158762
Signed-off-by: Dongwoo Lee <dwoo08.lee@samsung.com>
include/util/gpu-mem.h [new file with mode: 0644]
include/util/kernel.h
src/resource/resource-process-group.c
src/resource/resource-process.c
src/util/kernel.c

diff --git a/include/util/gpu-mem.h b/include/util/gpu-mem.h
new file mode 100644 (file)
index 0000000..bda0426
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * PASS
+ *
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __GPU_MEM_H__
+#define __GPU_MEM_H__
+
+struct gpu_mem_node {
+       char *name;
+       char *path;
+       char *node;
+};
+
+/* FIXME:
+ * Instead of iterative match, we can found the proper gpu memory node
+ * if pass-hal provides gpu information.
+ */
+static struct gpu_mem_node gpu_mem_nodes[] = {
+       { .name = "SGX", .path = "/dev/pvrsrvkm", .node = "Pss:" },
+       { .name = "MALI", .path = "/dev/mali", .node = "Size:"},
+       { .name = "KGSL", .path = "/dev/kgsl-3d0", .node = "Size:"},
+};
+
+static inline struct gpu_mem_node *get_gpu_mem_node(const char *name)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(gpu_mem_nodes); i++)
+               if (strstr(name, gpu_mem_nodes[i].path))
+                       return &gpu_mem_nodes[i];
+
+       return NULL;
+}
+
+#endif
index c640bd532b5000bcfe6701282dec365bbac76573..b3b9a3d6013c0b4570f60e64e37d7616ba16fe53 100644 (file)
@@ -40,6 +40,7 @@ struct proc_map_info {
        uint32_t pss;
        uint32_t swap;
        uint32_t swap_pss;
+       uint32_t gpu_mem;
 };
 
 enum {
@@ -65,5 +66,6 @@ int kernel_get_process_stat_fields(pid_t pid, char *buffer, int buf_len,
                                   char *stat_fields[PROCESS_STAT_FIELD_MAX]);
 int kernel_get_process_taskstats(struct taskstats *stats, int cmd_type, pid_t pid);
 int kernel_get_thread_group_taskstats(struct taskstats *stats, pid_t tgid, bool get_proc_info);
-int kernel_get_thread_group_map_info(struct proc_map_info *map_info, pid_t tgid);
+int
+kernel_get_thread_group_map_info(struct proc_map_info *map_info, pid_t tgid, bool include_gpu_mem);
 #endif
index 81565e01a6733a53d50c7014837a97d500f68914..752019414e6a1ecfe3610d71de4dbe1984b62ad2 100644 (file)
@@ -430,7 +430,7 @@ static int update_aggr_taskstats(struct process_group_context *ctx)
                        continue;
                }
 
-               ret = kernel_get_thread_group_map_info(&map_info, pid);
+               ret = kernel_get_thread_group_map_info(&map_info, pid, false);
                if (ret < 0) {
                        free(curr);
                        g_hash_table_iter_remove(&iter);
index beb3db309ec636cdbc3baf34c7023dcc14498d46..701e3a5236d49197bd5f568ca6994ffc4da86fb9 100644 (file)
@@ -351,7 +351,7 @@ static int process_setup_tgid(const struct resource *res,
        if (ret < 0)
                return ret;
 
-       ret = kernel_get_thread_group_map_info(&ctx->map_info, ctx->tgid);
+       ret = kernel_get_thread_group_map_info(&ctx->map_info, ctx->tgid, false);
        if (ret < 0)
                return ret;
 
@@ -385,7 +385,7 @@ static int process_prepare_update(struct resource *res)
        if (ret < 0)
                return ret;
 
-       ret = kernel_get_thread_group_map_info(&ctx->map_info, ctx->tgid);
+       ret = kernel_get_thread_group_map_info(&ctx->map_info, ctx->tgid, false);
        if (ret < 0)
                return ret;
 
index 2101535a113b02592651b461aaf8b7ec5a7224ff..2b60f3ec9a67e049606aeb628385a5b74ebc3271 100644 (file)
@@ -26,6 +26,7 @@
 #include <util/common.h>
 #include <util/log.h>
 #include <util/kernel.h>
+#include <util/gpu-mem.h>
 
 static int have_smaps_rollup;
 
@@ -410,26 +411,65 @@ int kernel_get_thread_group_taskstats(struct taskstats *stats, pid_t tgid, bool
        return 0;
 }
 
-int kernel_get_thread_group_map_info(struct proc_map_info *map_info, pid_t tgid)
+/*
+ * Since the smap section is started with address as hexadecimal number,
+ * on the other hand all nodes start with capital character as below, the entry
+ * of the section can be found by check the first letter is [0-9|a-f].
+ *
+ * 5598f8e6b000-7ffcefde5000 ---p 00000000 00:00 0                          [rollup]
+ * Rss:                5940 kB
+ * Pss:                2437 kB
+ * ...
+ */
+static inline bool is_new_entry(const char *str)
 {
-       char smap_file_path[BUFF_MAX];
+       return ((*str >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f'));
+}
+
+static void
+get_gpu_mem_info(struct proc_map_info *map_info, FILE *smaps_fd, char *entry)
+{
+       struct gpu_mem_node *gnode = NULL;
+       char name[BUFF_MAX];
        char buffer[BUFF_MAX];
-       FILE *smaps_file;
+       int n;
 
-       sprintf(smap_file_path, "/proc/%d/%s", tgid, have_smaps_rollup ? "smaps_rollup" : "smaps");
+new_entry:
+       n = sscanf(entry, "%*s %*s %*s %*s %*s %[^\n]", name);
 
-       smaps_file = fopen(smap_file_path, "r");
-       if (!smaps_file)
-               return -EIO;
+       gnode = get_gpu_mem_node(name);
+       if (gnode) {
+               while (fgets(buffer, sizeof(buffer), smaps_fd)) {
+                       if (strstr(buffer, gnode->node))
+                               map_info->gpu_mem += strtol(buffer + strlen(gnode->node), NULL, 10);
+
+                       if (is_new_entry(buffer)) {
+                               entry = buffer;
+                               goto new_entry;
+                       }
+               }
+       }
+}
+
+int kernel_get_thread_group_map_info(struct proc_map_info *map_info,
+                                    pid_t tgid, bool include_gpu_mem)
+{
+       char smap_file_path[BUFF_MAX];
+       char buffer[BUFF_MAX];
+       FILE *smaps_fd;
+       bool use_smaps_rollup = have_smaps_rollup && !include_gpu_mem;
 
-       map_info->rss = 0;
-       map_info->pss = 0;
-       map_info->swap = 0;
-       map_info->swap_pss = 0;
+       sprintf(smap_file_path, "/proc/%d/%s", tgid, use_smaps_rollup ? "smaps_rollup" : "smaps");
 
-       while (fgets(buffer, sizeof(buffer), smaps_file)) {
-               if (strchr(buffer, '\n') == 0)
-                       continue;
+       smaps_fd = fopen(smap_file_path, "r");
+       if (!smaps_fd) {
+               _E("failed to open smap: %s", strerror(errno));
+               return -ENOENT;
+       }
+
+       while (fgets(buffer, sizeof(buffer), smaps_fd)) {
+               if (include_gpu_mem && is_new_entry(buffer))
+                       get_gpu_mem_info(map_info, smaps_fd, buffer);
 
                if (strstr(buffer, "Rss:"))
                        map_info->rss += strtol(buffer + 4, NULL, 10);
@@ -441,7 +481,7 @@ int kernel_get_thread_group_map_info(struct proc_map_info *map_info, pid_t tgid)
                        map_info->swap_pss += strtol(buffer + 8, NULL, 10);
        }
 
-       fclose(smaps_file);
+       fclose(smaps_fd);
 
        return 0;
 }