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