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 c640bd5..b3b9a3d 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 81565e0..7520194 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 beb3db3..701e3a5 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 2101535..2b60f3e 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;
 }