--- /dev/null
+/*
+ * 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
#include <util/common.h>
#include <util/log.h>
#include <util/kernel.h>
+#include <util/gpu-mem.h>
static int have_smaps_rollup;
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);
map_info->swap_pss += strtol(buffer + 8, NULL, 10);
}
- fclose(smaps_file);
+ fclose(smaps_fd);
return 0;
}