linux/samples/bpf/offwaketime_user.c
Thomas Gleixner 25763b3c86 treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 206
Based on 1 normalized pattern(s):

  this program is free software you can redistribute it and or modify
  it under the terms of version 2 of the gnu general public license as
  published by the free software foundation

extracted by the scancode license scanner the SPDX license identifier

  GPL-2.0-only

has been chosen to replace the boilerplate/reference in 107 file(s).

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Allison Randal <allison@lohutok.net>
Reviewed-by: Richard Fontana <rfontana@redhat.com>
Reviewed-by: Steve Winslow <swinslow@gmail.com>
Reviewed-by: Alexios Zavras <alexios.zavras@intel.com>
Cc: linux-spdx@vger.kernel.org
Link: https://lkml.kernel.org/r/20190528171438.615055994@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2019-05-30 11:29:53 -07:00

125 lines
2.4 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016 Facebook
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <linux/bpf.h>
#include <string.h>
#include <linux/perf_event.h>
#include <errno.h>
#include <assert.h>
#include <stdbool.h>
#include <sys/resource.h>
#include "libbpf.h"
#include "bpf_load.h"
#include "trace_helpers.h"
#define PRINT_RAW_ADDR 0
static void print_ksym(__u64 addr)
{
struct ksym *sym;
if (!addr)
return;
sym = ksym_search(addr);
if (!sym) {
printf("ksym not found. Is kallsyms loaded?\n");
return;
}
if (PRINT_RAW_ADDR)
printf("%s/%llx;", sym->name, addr);
else
printf("%s;", sym->name);
}
#define TASK_COMM_LEN 16
struct key_t {
char waker[TASK_COMM_LEN];
char target[TASK_COMM_LEN];
__u32 wret;
__u32 tret;
};
static void print_stack(struct key_t *key, __u64 count)
{
__u64 ip[PERF_MAX_STACK_DEPTH] = {};
static bool warned;
int i;
printf("%s;", key->target);
if (bpf_map_lookup_elem(map_fd[3], &key->tret, ip) != 0) {
printf("---;");
} else {
for (i = PERF_MAX_STACK_DEPTH - 1; i >= 0; i--)
print_ksym(ip[i]);
}
printf("-;");
if (bpf_map_lookup_elem(map_fd[3], &key->wret, ip) != 0) {
printf("---;");
} else {
for (i = 0; i < PERF_MAX_STACK_DEPTH; i++)
print_ksym(ip[i]);
}
printf(";%s %lld\n", key->waker, count);
if ((key->tret == -EEXIST || key->wret == -EEXIST) && !warned) {
printf("stackmap collisions seen. Consider increasing size\n");
warned = true;
} else if (((int)(key->tret) < 0 || (int)(key->wret) < 0)) {
printf("err stackid %d %d\n", key->tret, key->wret);
}
}
static void print_stacks(int fd)
{
struct key_t key = {}, next_key;
__u64 value;
while (bpf_map_get_next_key(fd, &key, &next_key) == 0) {
bpf_map_lookup_elem(fd, &next_key, &value);
print_stack(&next_key, value);
key = next_key;
}
}
static void int_exit(int sig)
{
print_stacks(map_fd[0]);
exit(0);
}
int main(int argc, char **argv)
{
struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
char filename[256];
int delay = 1;
snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]);
setrlimit(RLIMIT_MEMLOCK, &r);
signal(SIGINT, int_exit);
signal(SIGTERM, int_exit);
if (load_kallsyms()) {
printf("failed to process /proc/kallsyms\n");
return 2;
}
if (load_bpf_file(filename)) {
printf("%s", bpf_log_buf);
return 1;
}
if (argc > 1)
delay = atoi(argv[1]);
sleep(delay);
print_stacks(map_fd[0]);
return 0;
}