Bug 1038921 - Extend system memory reporter to report kgsl memory. r=njn

This commit is contained in:
Eric Rahm 2014-07-21 17:25:21 -07:00
parent 0cce7ce188
commit 99c9bcaeba

View File

@ -176,6 +176,10 @@ public:
rv = CollectZramReports(aHandleReport, aData);
NS_ENSURE_SUCCESS(rv, rv);
// Report kgsl graphics memory usage.
rv = CollectKgslReports(aHandleReport, aData);
NS_ENSURE_SUCCESS(rv, rv);
return rv;
}
@ -862,6 +866,99 @@ private:
return NS_OK;
}
struct AutoDir
{
AutoDir(DIR* aDir) : mDir(aDir) {}
~AutoDir() { closedir(mDir); };
DIR* mDir;
};
struct AutoFile
{
AutoFile(FILE* aFile) : mFile(aFile) {}
~AutoFile() { fclose(mFile); }
FILE* mFile;
};
nsresult
CollectKgslReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
// Each process that uses kgsl memory will have an entry under
// /sys/kernel/debug/kgsl/proc/<pid>/mem. This file format includes a
// header and then entries with types as follows:
// gpuaddr useraddr size id flags type usage sglen
// hexaddr hexaddr int int str str str int
// We care primarily about the usage and size.
// For simplicity numbers will be uint64_t, strings 63 chars max.
const char* const kScanFormat =
"%" SCNx64 " %" SCNx64 " %" SCNu64 " %" SCNu64
" %63s %63s %63s %" SCNu64;
const int kNumFields = 8;
const size_t kStringSize = 64;
DIR* d = opendir("/sys/kernel/debug/kgsl/proc/");
if (!d) {
if (NS_WARN_IF(errno != ENOENT && errno != EACCES)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
AutoDir dirGuard(d);
struct dirent* ent;
while ((ent = readdir(d))) {
const char* pid = ent->d_name;
// Skip "." and ".." (and any other dotfiles).
if (pid[0] == '.') {
continue;
}
nsPrintfCString memPath("/sys/kernel/debug/kgsl/proc/%s/mem", pid);
FILE* memFile = fopen(memPath.get(), "r");
if (NS_WARN_IF(!memFile)) {
continue;
}
AutoFile fileGuard(memFile);
// Attempt to map the pid to a more useful name.
nsAutoCString procName;
GetThreadName(atoi(pid), procName);
if (procName.IsEmpty()) {
procName.Append("pid=");
procName.Append(pid);
} else {
procName.Append(" (pid=");
procName.Append(pid);
procName.Append(")");
}
uint64_t gpuaddr, useraddr, size, id, sglen;
char flags[kStringSize];
char type[kStringSize];
char usage[kStringSize];
// Bypass the header line.
char buff[1024];
fgets(buff, 1024, memFile);
while (fscanf(memFile, kScanFormat, &gpuaddr, &useraddr, &size, &id,
flags, type, usage, &sglen) == kNumFields) {
nsPrintfCString entryPath("kgsl-memory/%s/%s", procName.get(), usage);
REPORT(entryPath,
size,
NS_LITERAL_CSTRING("A kgsl graphics memory allocation."));
}
}
return NS_OK;
}
#undef REPORT
};