summaryrefslogtreecommitdiff
path: root/memtrack_aml.c (plain)
blob: 671c519c7007b9774c18b76ffaa8c3d45784e874
1/*
2 * Copyright (c) 2017 Amlogic, Inc. All rights reserved.
3 *
4 * This source code is subject to the terms and conditions defined in the
5 * file 'LICENSE' which is part of this source code package.
6 *
7 * Description:
8 * used for memory track.
9 */
10
11#define LOG_TAG "memtrack_aml"
12#include <errno.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <fcntl.h>
17#include <ctype.h>
18#include <inttypes.h>
19#include <dirent.h>
20#include <stdint.h>
21
22#include <hardware/memtrack.h>
23#include <log/log.h>
24
25#define DEBUG 0
26#define VMALLOCION "/proc/ion/vmalloc_ion"
27#define GPUT8X "/sys/kernel/debug/mali0/ctx"
28#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
29
30static struct hw_module_methods_t memtrack_module_methods = {
31 .open = NULL,
32};
33
34struct memtrack_record record_templates[] = {
35 {
36 .flags = MEMTRACK_FLAG_SMAPS_UNACCOUNTED |
37 MEMTRACK_FLAG_PRIVATE |
38 MEMTRACK_FLAG_NONSECURE,
39 },
40
41/*
42 {
43 .flags = MEMTRACK_FLAG_SMAPS_ACCOUNTED |
44 MEMTRACK_FLAG_PRIVATE |
45 MEMTRACK_FLAG_NONSECURE,
46 },
47*/
48};
49
50// just return 0
51int aml_memtrack_init(const struct memtrack_module *module)
52{
53 return 0;
54}
55
56/*
57 * find the userid of process @pid
58 * return the userid if success, or return -1 if not
59 */
60static int memtrack_find_userid(int pid)
61{
62 FILE *fp;
63 char line[1024];
64 char tmp[128];
65 int userid;
66
67 sprintf(tmp, "/proc/%d/status", pid);
68 if ((fp=fopen(tmp, "r")) == NULL) {
69 if (DEBUG) ALOGD("open file %s error %s", tmp, strerror(errno));
70 return -1;
71 }
72
73 while (fgets(line, sizeof(line), fp) != NULL) {
74 if (sscanf(line, "Uid: %d", &userid) == 1) {
75 fclose(fp);
76 return userid;
77 }
78 }
79
80 // should never reach here
81 fclose(fp);
82 return -1;
83}
84
85static unsigned int memtrack_read_smaps(FILE *fp)
86{
87 char line[1024];
88 unsigned int size, sum = 0;
89 int skip, done = 0;
90
91 uint64_t start;
92 uint64_t end = 0;
93 int len;
94 char *name;
95 int nameLen, name_pos;
96
97 if(fgets(line, sizeof(line), fp) == 0) {
98 return 0;
99 }
100
101 while (!done) {
102 skip = 0;
103
104 len = strlen(line);
105 if (len < 1)
106 return 0;
107
108 line[--len] = 0;
109
110 if (sscanf(line, "%"SCNx64 "-%"SCNx64 " %*s %*x %*x:%*x %*d%n", &start, &end, &name_pos) != 2) {
111 skip = 1;
112 } else {
113 while (isspace(line[name_pos])) {
114 name_pos += 1;
115 }
116 name = line + name_pos;
117 nameLen = strlen(name);
118
119 if (nameLen >= 8 &&
120 (!strncmp(name, "/dev/mali", 6) || !strncmp(name, "/dev/ump", 6))) {
121 skip = 0;
122 } else {
123 skip = 1;
124 }
125
126 }
127
128 while (1) {
129 if (fgets(line, 1024, fp) == 0) {
130 done = 1;
131 break;
132 }
133
134 if(!skip) {
135 if (line[0] == 'S' && sscanf(line, "Size: %d kB", &size) == 1) {
136 sum += size;
137 }
138 }
139
140 if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %*s %*x %*x:%*x %*d", &start, &end) == 2) {
141 // looks like a new mapping
142 // example: "10000000-10001000 ---p 10000000 00:00 0"
143 break;
144 }
145 }
146 }
147
148 // converted into Bytes
149 return (sum * 1024);
150}
151
152// mali t82x t83x
153static int memtrack_get_gpuT8X(char *path)
154{
155 FILE *file;
156 char line[1024];
157
158 int gpu_size = 0;
159
160 if ((file = fopen(path, "r")) == NULL) {
161 if (DEBUG) ALOGD("open file %s error %s", path, strerror(errno));
162 return 0;
163 }
164
165 while (fgets(line, sizeof(line), file) != NULL) {
166 if (sscanf(line, "Total allocated memory: %d", &gpu_size) != 1)
167 continue;
168 else
169 break;
170 }
171 fclose(file);
172 return gpu_size;
173}
174
175static unsigned int memtrack_get_gpuMem(int pid)
176{
177 FILE *fp;
178 char *cp, tmp[128];
179 unsigned int result;
180
181 DIR *gpudir;
182 struct dirent *dir;
183 int gpid = -1;
184
185 gpudir = opendir(GPUT8X);
186 if (!gpudir) {
187 if (DEBUG)
188 ALOGD("open %s error %s\n", GPUT8X, strerror(errno));
189 sprintf(tmp, "/proc/%d/smaps", pid);
190 fp = fopen(tmp, "r");
191 if (fp == NULL) {
192 if (DEBUG) ALOGD("open file %s error %s", tmp, strerror(errno));
193 return 0;
194 }
195 result = memtrack_read_smaps(fp);
196
197 fclose(fp);
198 return result;
199 } else {
200 while ((dir = readdir(gpudir))) {
201 strcpy(tmp, dir->d_name);
202 if ((cp=strchr(tmp, '_'))) {
203 *cp = '\0';
204 gpid = atoi(tmp);
205 if (gpid == pid) {
206 sprintf(tmp, GPUT8X"/%s/%s", dir->d_name, "mem_profile");
207 result = memtrack_get_gpuT8X(tmp);
208 closedir(gpudir);
209 return result;
210 }
211 }
212 }
213 closedir(gpudir);
214 }
215 return 0;
216}
217
218static int memtrack_get_memory(pid_t pid, enum memtrack_type type,
219 struct memtrack_record *records,
220 size_t *num_records)
221{
222 FILE *fp;
223 FILE *ion_fp;
224 char line[1024];
225 char tmp[128];
226 unsigned int mali_inuse = 0;
227 unsigned int size;
228 size_t unaccounted_size = 0;
229
230 char ion_name[128];
231 int ion_pid;
232 unsigned int ion_size;
233 unsigned int gpu_size;
234
235
236 // ALOGD("type is %d, pid is %d\n", type, pid);
237 size_t allocated_records = ARRAY_SIZE(record_templates);
238 *num_records = ARRAY_SIZE(record_templates);
239
240 if (records == NULL) {
241 return 0;
242 }
243
244 memcpy(records, record_templates, sizeof(struct memtrack_record) * allocated_records);
245
246 if (type == MEMTRACK_TYPE_GL) {
247 // find the user id of the process, only support calculate the non root process
248 int ret = memtrack_find_userid(pid);
249 if (ret <= 0) {
250 return -1;
251 }
252 gpu_size = memtrack_get_gpuMem(pid);
253 unaccounted_size += gpu_size;
254 } else if (type == MEMTRACK_TYPE_GRAPHICS) {
255 sprintf(tmp, VMALLOCION);
256 if ((ion_fp = fopen(tmp, "r")) == NULL) {
257 if (DEBUG) ALOGD("open file %s error %s", tmp, strerror(errno));
258 return -errno;
259 }
260
261 while(fgets(line, sizeof(line), ion_fp) != NULL) {
262 if (sscanf(line, "%s%d%u", ion_name, &ion_pid, &ion_size) != 3) {
263 continue;
264 } else {
265 if (ion_pid == pid) {
266 unaccounted_size += ion_size;
267 }
268 }
269
270 }
271
272 fclose(ion_fp);
273 }
274
275 if (allocated_records > 0) {
276 records[0].size_in_bytes = unaccounted_size;
277 // ALOGD("graphic %u\n", unaccounted_size);
278 }
279
280 return 0;
281}
282
283int aml_memtrack_get_memory(const struct memtrack_module *module,
284 pid_t pid,
285 int type,
286 struct memtrack_record *records,
287 size_t *num_records)
288{
289 if (pid <= 0)
290 return -EINVAL;
291
292 if (type == MEMTRACK_TYPE_GL || type == MEMTRACK_TYPE_GRAPHICS)
293 return memtrack_get_memory(pid, type, records, num_records);
294 else
295 return -ENODEV;
296}
297
298
299struct memtrack_module HAL_MODULE_INFO_SYM = {
300 common: {
301 tag: HARDWARE_MODULE_TAG,
302 module_api_version: MEMTRACK_MODULE_API_VERSION_0_1,
303 hal_api_version: HARDWARE_HAL_API_VERSION,
304 id: MEMTRACK_HARDWARE_MODULE_ID,
305 name: "aml Memory Tracker HAL",
306 author: "amlogic",
307 methods: &memtrack_module_methods,
308 },
309
310 init: aml_memtrack_init,
311 getMemory: aml_memtrack_get_memory,
312};
313