prof: add user/kernel statistics

This commit is contained in:
Matheus
2026-04-22 19:44:08 -03:00
parent 337c2e6b69
commit 90a420d8bb
3 changed files with 49 additions and 20 deletions
+2 -6
View File
@@ -99,10 +99,8 @@ static bool intel_irq(context_t *context) {
uint8_t data[1 + sizeof(uintptr_t) * 256];
uint8_t size = get_backtrace(context, (uintptr_t *)(data + 1));
if (size) {
*data = size;
profiling_insert(size, data);
}
*data = size;
profiling_insert(size, data);
arch_apic_init_perf(); // SDM LVT figure says a PMC irq masks itself, so unmask it
reset_intel_pmc();
@@ -118,8 +116,6 @@ static void init_amd_pmc(void) {
__assert(!"Unimplemented");
}
bool arch_profiling_irq(context_t *context) {
if (!strcmp(current_cpu()->vendor, "AuthenticAMD"))
return amd_irq(context);
+29 -8
View File
@@ -8,6 +8,7 @@
#include <kernel/vfs.h>
#include <arch/smp.h>
#include <logging.h>
#include <kernel/usercopy.h>
#ifdef ENABLE_PROFILING
@@ -19,9 +20,17 @@ static MUTEX_DEFINE(mutex);
static pollheader_t pollheader;
static semaphore_t wait_sem;
static int remaining;
static size_t userspace_hits;
static size_t kernel_hits;
// called from a possibly NMI context!
void profiling_insert(uint8_t size, void *data) {
if (!size) {
__atomic_fetch_add(&userspace_hits, 1, __ATOMIC_SEQ_CST);
return;
}
__atomic_fetch_add(&kernel_hits, 1, __ATOMIC_SEQ_CST);
size_t write_size = sizeof(uint8_t) + sizeof(uintptr_t) * size;
if (current_cpu()->prof_ringbuffer && RINGBUFFER_FREESPACE(current_cpu()->prof_ringbuffer) >= write_size) {
size_t written = ringbuffer_write(current_cpu()->prof_ringbuffer, data, write_size);
@@ -149,19 +158,31 @@ static int device_read(int minor, iovec_iterator_t *iovec_iterator, size_t size,
return error;
}
static int device_ioctl(int, unsigned long request, void *, int *result, cred_t *cred) {
if (request != 12345678)
return ENOTTY;
static int device_ioctl(int, unsigned long request, void *addr, int *result, cred_t *cred) {
*result = 0;
// only supported ioctl is a truncation one: remove all previous data
MUTEX_ACQUIRE(&mutex);
switch (request) {
case 12345678:
MUTEX_ACQUIRE(&mutex);
ringbuffer_truncate(&global_ringbuffer, PROFILING_GLOBAL_BUFFER_SIZE);
ringbuffer_truncate(&global_ringbuffer, PROFILING_GLOBAL_BUFFER_SIZE);
MUTEX_RELEASE(&mutex);
MUTEX_RELEASE(&mutex);
__atomic_store_n(&userspace_hits, 0, __ATOMIC_SEQ_CST);
__atomic_store_n(&kernel_hits, 0, __ATOMIC_SEQ_CST);
break;
case 87654321:
size_t outputs[2] = {
__atomic_load_n(&userspace_hits, __ATOMIC_SEQ_CST),
__atomic_load_n(&kernel_hits, __ATOMIC_SEQ_CST)
};
return USERCOPY_POSSIBLY_TO_USER(addr, outputs, sizeof(outputs));
}
*result = 0;
return 0;
}
+18 -6
View File
@@ -22,8 +22,8 @@ static int open_or_die(const char *name, int flag, mode_t mode) {
int main(int argc, char *argv[]) {
progname = argv[0];
if (argc != 2) {
fprintf(stderr, "%s: usage: %s FILE\n", argv[0], argv[0]);
if (argc < 2 || argc > 3) {
fprintf(stderr, "%s: usage: %s FILE [-n]\n", argv[0], argv[0]);
return EXIT_FAILURE;
}
@@ -42,10 +42,12 @@ int main(int argc, char *argv[]) {
tcsetattr(outfd, TCSANOW, &termios);
}
printf("%s: draining /dev/prof\n", argv[0]);
// empty it
if (ioctl(infd, 12345678, NULL) < 0)
return EXIT_FAILURE;
if (argc == 2 || (strcmp(argv[1], "-n") && strcmp(argv[2], "-n"))) {
printf("%s: draining /dev/prof\n", argv[0]);
// empty it
if (ioctl(infd, 12345678, NULL) < 0)
return EXIT_FAILURE;
}
struct pollfd pollfd[2];
@@ -68,6 +70,16 @@ int main(int argc, char *argv[]) {
write(outfd, buf, 8 * count);
}
size_t hits[2];
ioctl(infd, 87654321, hits);
size_t total = hits[0] + hits[1];
float u_ratio = (float)hits[0] / (float)total;
float k_ratio = 1.f - u_ratio;
printf("%s: %lu hits\n", argv[0], total);
printf("%s: %lu userspace hits (%01.02f%%)\n", argv[0], hits[0], u_ratio * 100);
printf("%s: %lu kernel hits (%01.02f%%)\n", argv[0], hits[1], k_ratio * 100);
printf("%s: done\n", argv[0]);
return EXIT_SUCCESS;