107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani/* 207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Copyright (C) 2013 The Android Open Source Project 307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Licensed under the Apache License, Version 2.0 (the "License"); 507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * you may not use this file except in compliance with the License. 607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * You may obtain a copy of the License at 707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * http://www.apache.org/licenses/LICENSE-2.0 907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 1007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * Unless required by applicable law or agreed to in writing, software 1107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * distributed under the License is distributed on an "AS IS" BASIS, 1207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * See the License for the specific language governing permissions and 1407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * limitations under the License. 1507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani */ 1607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 1707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <errno.h> 1807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <stdbool.h> 1907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <stdio.h> 2007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <string.h> 2107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <sys/mman.h> 2207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 2307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include <hardware/memtrack.h> 2407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 2507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#include "memtrack_msm.h" 2607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 2707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) 2807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani#define min(x, y) ((x) < (y) ? (x) : (y)) 2907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 3007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malanistruct memtrack_record record_templates[] = { 3107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani { 3207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .flags = MEMTRACK_FLAG_SMAPS_ACCOUNTED | 3307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani MEMTRACK_FLAG_PRIVATE | 3407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani MEMTRACK_FLAG_NONSECURE, 3507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani }, 3607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani { 3707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani .flags = MEMTRACK_FLAG_SMAPS_UNACCOUNTED | 3807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani MEMTRACK_FLAG_PRIVATE | 3907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani MEMTRACK_FLAG_NONSECURE, 4007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani }, 4107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani}; 4207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 4307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malaniint kgsl_memtrack_get_memory(pid_t pid, enum memtrack_type type, 4407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani struct memtrack_record *records, 4507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani size_t *num_records) 4607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani{ 4707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani size_t allocated_records = min(*num_records, ARRAY_SIZE(record_templates)); 4807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani FILE *fp; 4907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani char line[1024]; 5007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani char tmp[128]; 5107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani bool is_surfaceflinger = false; 5207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani size_t accounted_size = 0; 5307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani size_t unaccounted_size = 0; 5407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 5507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani *num_records = ARRAY_SIZE(record_templates); 5607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 5707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani /* fastpath to return the necessary number of records */ 5807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (allocated_records == 0) { 5907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return 0; 6007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 6107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 6207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani snprintf(tmp, sizeof(tmp), "/proc/%d/cmdline", pid); 6307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani fp = fopen(tmp, "r"); 6407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (fp != NULL) { 6507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (fgets(line, sizeof(line), fp)) { 6607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (strcmp(line, "/system/bin/surfaceflinger") == 0) 6707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani is_surfaceflinger = true; 6807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 6907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani fclose(fp); 7007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 7107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 7207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani memcpy(records, record_templates, 7307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani sizeof(struct memtrack_record) * allocated_records); 7407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 7507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani snprintf(tmp, sizeof(tmp), "/d/kgsl/proc/%d/mem", pid); 7607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani fp = fopen(tmp, "r"); 7707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (fp == NULL) { 7807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return -errno; 7907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 8007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 8107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani /* Go through each line of <pid>/mem file and for every entry of type "gpumem" 8207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * check if the gpubuffer entry is usermapped or not. If the entry is usermapped 8307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * count the entry as accounted else count the entry as unaccounted. 8407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani */ 8507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani while (1) { 8607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani unsigned long size; 8707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani char line_type[7]; 8807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani char flags[7]; 8907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani char line_usage[19]; 9007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani int ret; 9107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 9207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (fgets(line, sizeof(line), fp) == NULL) { 9307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani break; 9407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 9507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 9607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani /* Format: 9707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * gpuaddr useraddr size id flags type usage sglen 9807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani * 545ba000 545ba000 4096 1 ----pY gpumem arraybuffer 1 9907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani */ 10007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %18s %*d\n", 10107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani &size, flags, line_type, line_usage); 10207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (ret != 4) { 10307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani continue; 10407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 10507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 10607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (type == MEMTRACK_TYPE_GL && strcmp(line_type, "gpumem") == 0) { 10707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 10807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (flags[5] == 'Y') 10907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani accounted_size += size; 11007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani else 11107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani unaccounted_size += size; 11207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 11307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) { 11407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (!is_surfaceflinger || strcmp(line_usage, "egl_image") != 0) { 11507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani unaccounted_size += size; 11607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 11707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 11807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 11907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 12007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (allocated_records > 0) { 12107bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani records[0].size_in_bytes = accounted_size; 12207bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 12307bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani if (allocated_records > 1) { 12407bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani records[1].size_in_bytes = unaccounted_size; 12507bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani } 12607bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 12707bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani fclose(fp); 12807bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani 12907bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani return 0; 13007bbf1e89c031a5d41a7561433e832d396c311a5Prashant Malani} 131