mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 02:51:10 +00:00
88 lines
3.6 KiB
C
88 lines
3.6 KiB
C
#define _GNU_SOURCE
|
|
#include <dlfcn.h>
|
|
#include <limits.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
|
|
#define STANDIN_DIR "/tmp/droiddeck-tracefs"
|
|
#define KGSL_TOTAL "/sys/class/kgsl/kgsl/page_alloc"
|
|
|
|
struct tracefs_instance;
|
|
struct tep_handle;
|
|
struct tep_event;
|
|
|
|
struct tep_record {
|
|
unsigned long long ts, offset;
|
|
long long missed_events;
|
|
int record_size, size;
|
|
void *data;
|
|
int cpu, ref_count, locked;
|
|
void *priv;
|
|
};
|
|
|
|
static const char gpu_mem_total_format[] =
|
|
"name: gpu_mem_total\n"
|
|
"ID: 1\n"
|
|
"format:\n"
|
|
"\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n"
|
|
"\tfield:unsigned char common_flags;\toffset:2;\tsize:1;\tsigned:0;\n"
|
|
"\tfield:unsigned char common_preempt_count;\toffset:3;\tsize:1;\tsigned:0;\n"
|
|
"\tfield:int common_pid;\toffset:4;\tsize:4;\tsigned:1;\n"
|
|
"\n"
|
|
"\tfield:uint32_t gpu_id;\toffset:8;\tsize:4;\tsigned:0;\n"
|
|
"\tfield:uint32_t pid;\toffset:12;\tsize:4;\tsigned:0;\n"
|
|
"\tfield:uint64_t size;\toffset:16;\tsize:8;\tsigned:0;\n"
|
|
"\n"
|
|
"print fmt: \"gpu_id=%u pid=%u size=%llu\", REC->gpu_id, REC->pid, REC->size\n";
|
|
|
|
static struct tracefs_instance *standin;
|
|
|
|
struct tracefs_instance *tracefs_instance_create(const char *name) {
|
|
struct tracefs_instance *(*real)(const char *) = dlsym(RTLD_NEXT, "tracefs_instance_create");
|
|
struct tracefs_instance *instance = real ? real(name) : NULL;
|
|
if (instance || !name) return instance;
|
|
struct tracefs_instance *(*alloc)(const char *, const char *) = dlsym(RTLD_NEXT, "tracefs_instance_alloc");
|
|
if (!alloc) return NULL;
|
|
char path[PATH_MAX];
|
|
mkdir(STANDIN_DIR, 0700);
|
|
mkdir(STANDIN_DIR "/instances", 0700);
|
|
snprintf(path, sizeof(path), STANDIN_DIR "/instances/%s", name);
|
|
mkdir(path, 0700);
|
|
return standin = alloc(STANDIN_DIR, name);
|
|
}
|
|
|
|
struct tep_handle *tracefs_local_events(const char *tracing_dir) {
|
|
if (!tracing_dir || strncmp(tracing_dir, STANDIN_DIR "/", sizeof(STANDIN_DIR))) {
|
|
struct tep_handle *(*real)(const char *) = dlsym(RTLD_NEXT, "tracefs_local_events");
|
|
return real ? real(tracing_dir) : NULL;
|
|
}
|
|
struct tep_handle *(*tep_alloc)(void) = dlsym(RTLD_DEFAULT, "tep_alloc");
|
|
int (*parse)(struct tep_handle *, const char *, unsigned long, const char *) = dlsym(RTLD_DEFAULT, "tep_parse_event");
|
|
struct tep_handle *tep = tep_alloc ? tep_alloc() : NULL;
|
|
if (tep && parse) parse(tep, gpu_mem_total_format, sizeof(gpu_mem_total_format) - 1, "gpu_mem");
|
|
return tep;
|
|
}
|
|
|
|
int tracefs_iterate_raw_events(struct tep_handle *tep, struct tracefs_instance *instance, void *cpus, int cpu_size,
|
|
int (*callback)(struct tep_event *, struct tep_record *, int, void *), void *context) {
|
|
if (!standin || instance != standin) {
|
|
int (*real)(struct tep_handle *, struct tracefs_instance *, void *, int,
|
|
int (*)(struct tep_event *, struct tep_record *, int, void *), void *) =
|
|
dlsym(RTLD_NEXT, "tracefs_iterate_raw_events");
|
|
return real ? real(tep, instance, cpus, cpu_size, callback, context) : -1;
|
|
}
|
|
struct tep_event *(*find)(struct tep_handle *, int) = dlsym(RTLD_DEFAULT, "tep_find_event");
|
|
struct tep_event *event = find && tep ? find(tep, 1) : NULL;
|
|
unsigned long long total;
|
|
FILE *f = fopen(KGSL_TOTAL, "r");
|
|
int have = f && fscanf(f, "%llu", &total) == 1;
|
|
if (f) fclose(f);
|
|
if (!event || !have || !callback) return -1;
|
|
struct { uint16_t type; uint8_t flags, preempt; int32_t common_pid; uint32_t gpu_id, pid; uint64_t size; } data = {
|
|
.type = 1, .size = total};
|
|
struct tep_record record = {.record_size = sizeof(data), .size = sizeof(data), .data = &data};
|
|
return callback(event, &record, 0, context);
|
|
}
|