Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_INTERNAL_CPUMAP_H
#define __LIBPERF_INTERNAL_CPUMAP_H
#include <linux/refcount.h>
#include <perf/cpumap.h>
#include <internal/rc_check.h>
/**
* A sized, reference counted, sorted array of integers representing CPU
* numbers. This is commonly used to capture which CPUs a PMU is associated
* with. The indices into the cpumap are frequently used as they avoid having
* gaps if CPU numbers were used. For events associated with a pid, rather than
* a CPU, a single dummy map with an entry of -1 is used.
*/
DECLARE_RC_STRUCT(perf_cpu_map) {
refcount_t refcnt;
/** Length of the map array. */
unsigned int nr;
/** The CPU values. */
struct perf_cpu map[];
};
struct perf_cpu_map *perf_cpu_map__alloc(unsigned int nr_cpus);
int perf_cpu_map__idx(const struct perf_cpu_map *cpus, struct perf_cpu cpu);
bool perf_cpu_map__is_subset(const struct perf_cpu_map *a, const struct perf_cpu_map *b);
void perf_cpu_map__set_nr(struct perf_cpu_map *map, unsigned int nr_cpus);
static inline refcount_t *perf_cpu_map__refcnt(struct perf_cpu_map *map)
{
return &RC_CHK_ACCESS(map)->refcnt;
}
#endif /* __LIBPERF_INTERNAL_CPUMAP_H */
@@ -0,0 +1,140 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_INTERNAL_EVLIST_H
#define __LIBPERF_INTERNAL_EVLIST_H
#include <linux/list.h>
#include <api/fd/array.h>
#include <internal/cpumap.h>
#include <internal/evsel.h>
#define PERF_EVLIST__HLIST_BITS 8
#define PERF_EVLIST__HLIST_SIZE (1 << PERF_EVLIST__HLIST_BITS)
struct perf_cpu_map;
struct perf_thread_map;
struct perf_mmap_param;
struct perf_evlist {
struct list_head entries;
int nr_entries;
bool has_user_cpus;
bool needs_map_propagation;
/**
* The cpus passed from the command line or all online CPUs by
* default.
*/
struct perf_cpu_map *user_requested_cpus;
/** The union of all evsel cpu maps. */
struct perf_cpu_map *all_cpus;
struct perf_thread_map *threads;
int nr_mmaps;
size_t mmap_len;
struct fdarray pollfd;
struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
struct perf_mmap *mmap;
struct perf_mmap *mmap_ovw;
struct perf_mmap *mmap_first;
struct perf_mmap *mmap_ovw_first;
};
typedef void
(*perf_evlist_mmap__cb_idx_t)(struct perf_evlist*, struct perf_evsel*,
struct perf_mmap_param*, int);
typedef struct perf_mmap*
(*perf_evlist_mmap__cb_get_t)(struct perf_evlist*, bool, int);
typedef int
(*perf_evlist_mmap__cb_mmap_t)(struct perf_mmap*, struct perf_mmap_param*, int, struct perf_cpu);
struct perf_evlist_mmap_ops {
perf_evlist_mmap__cb_idx_t idx;
perf_evlist_mmap__cb_get_t get;
perf_evlist_mmap__cb_mmap_t mmap;
};
int perf_evlist__alloc_pollfd(struct perf_evlist *evlist);
int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd,
void *ptr, short revent, enum fdarray_flags flags);
int perf_evlist__mmap_ops(struct perf_evlist *evlist,
struct perf_evlist_mmap_ops *ops,
struct perf_mmap_param *mp);
void perf_evlist__init(struct perf_evlist *evlist);
void perf_evlist__exit(struct perf_evlist *evlist);
/**
* __perf_evlist__for_each_entry - iterate thru all the evsels
* @list: list_head instance to iterate
* @evsel: struct perf_evsel iterator
*/
#define __perf_evlist__for_each_entry(list, evsel) \
list_for_each_entry(evsel, list, node)
/**
* evlist__for_each_entry - iterate thru all the evsels
* @evlist: perf_evlist instance to iterate
* @evsel: struct perf_evsel iterator
*/
#define perf_evlist__for_each_entry(evlist, evsel) \
__perf_evlist__for_each_entry(&(evlist)->entries, evsel)
/**
* __perf_evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
* @list: list_head instance to iterate
* @evsel: struct evsel iterator
*/
#define __perf_evlist__for_each_entry_reverse(list, evsel) \
list_for_each_entry_reverse(evsel, list, node)
/**
* perf_evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
* @evlist: evlist instance to iterate
* @evsel: struct evsel iterator
*/
#define perf_evlist__for_each_entry_reverse(evlist, evsel) \
__perf_evlist__for_each_entry_reverse(&(evlist)->entries, evsel)
/**
* __perf_evlist__for_each_entry_safe - safely iterate thru all the evsels
* @list: list_head instance to iterate
* @tmp: struct evsel temp iterator
* @evsel: struct evsel iterator
*/
#define __perf_evlist__for_each_entry_safe(list, tmp, evsel) \
list_for_each_entry_safe(evsel, tmp, list, node)
/**
* perf_evlist__for_each_entry_safe - safely iterate thru all the evsels
* @evlist: evlist instance to iterate
* @evsel: struct evsel iterator
* @tmp: struct evsel temp iterator
*/
#define perf_evlist__for_each_entry_safe(evlist, tmp, evsel) \
__perf_evlist__for_each_entry_safe(&(evlist)->entries, tmp, evsel)
static inline struct perf_evsel *perf_evlist__first(struct perf_evlist *evlist)
{
return list_entry(evlist->entries.next, struct perf_evsel, node);
}
static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
{
return list_entry(evlist->entries.prev, struct perf_evsel, node);
}
u64 perf_evlist__read_format(struct perf_evlist *evlist);
void perf_evlist__id_add(struct perf_evlist *evlist,
struct perf_evsel *evsel,
int cpu_map_idx, int thread, u64 id);
int perf_evlist__id_add_fd(struct perf_evlist *evlist,
struct perf_evsel *evsel,
int cpu_map_idx, int thread, int fd);
void perf_evlist__reset_id_hash(struct perf_evlist *evlist);
void __perf_evlist__set_leader(struct list_head *list, struct perf_evsel *leader);
void perf_evlist__go_system_wide(struct perf_evlist *evlist, struct perf_evsel *evsel);
#endif /* __LIBPERF_INTERNAL_EVLIST_H */
@@ -0,0 +1,153 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_INTERNAL_EVSEL_H
#define __LIBPERF_INTERNAL_EVSEL_H
#include <linux/types.h>
#include <linux/perf_event.h>
#include <stdbool.h>
#include <sys/types.h>
#include <internal/cpumap.h>
struct perf_thread_map;
struct xyarray;
/**
* The per-thread accumulated period storage node.
*/
struct perf_sample_id_period {
struct list_head node;
struct hlist_node hnode;
/* Holds total ID period value for PERF_SAMPLE_READ processing. */
u64 period;
/* The TID that the values belongs to */
u32 tid;
};
/**
* perf_evsel_for_each_per_thread_period_safe - safely iterate thru all the
* per_stream_periods
* @evlist:perf_evsel instance to iterate
* @item: struct perf_sample_id_period iterator
* @tmp: struct perf_sample_id_period temp iterator
*/
#define perf_evsel_for_each_per_thread_period_safe(evsel, tmp, item) \
list_for_each_entry_safe(item, tmp, &(evsel)->per_stream_periods, node)
#define PERF_SAMPLE_ID__HLIST_BITS 4
#define PERF_SAMPLE_ID__HLIST_SIZE (1 << PERF_SAMPLE_ID__HLIST_BITS)
/*
* Per fd, to map back from PERF_SAMPLE_ID to evsel, only used when there are
* more than one entry in the evlist.
*/
struct perf_sample_id {
struct hlist_node node;
u64 id;
struct perf_evsel *evsel;
/*
* 'idx' will be used for AUX area sampling. A sample will have AUX area
* data that will be queued for decoding, where there are separate
* queues for each CPU (per-cpu tracing) or task (per-thread tracing).
* The sample ID can be used to lookup 'idx' which is effectively the
* queue number.
*/
int idx;
struct perf_cpu cpu;
pid_t tid;
/* Guest machine pid and VCPU, valid only if machine_pid is non-zero */
pid_t machine_pid;
struct perf_cpu vcpu;
/*
* Per-thread, and global event counts are mutually exclusive:
* Whilst it is possible to combine events into a group with differing
* values of PERF_SAMPLE_READ, it is not valid to have inconsistent
* values for `inherit`. Therefore it is not possible to have a
* situation where a per-thread event is sampled as a global event;
* all !inherit groups are global, and all groups where the sampling
* event is inherit + PERF_SAMPLE_READ will be per-thread. Any event
* that is part of such a group that is inherit but not PERF_SAMPLE_READ
* will be read as per-thread. If such an event can also trigger a
* sample (such as with sample_period > 0) then it will not cause
* `read_format` to be included in its PERF_RECORD_SAMPLE, and
* therefore will not expose the per-thread group members as global.
*/
union {
/*
* Holds total ID period value for PERF_SAMPLE_READ processing
* (when period is not per-thread).
*/
u64 period;
/*
* Holds total ID period value for PERF_SAMPLE_READ processing
* (when period is per-thread).
*/
struct hlist_head periods[PERF_SAMPLE_ID__HLIST_SIZE];
};
};
struct perf_evsel {
struct list_head node;
struct perf_event_attr attr;
/** The commonly used cpu map of CPUs the event should be opened upon, etc. */
struct perf_cpu_map *cpus;
/**
* The cpu map read from the PMU. For core PMUs this is the list of all
* CPUs the event can be opened upon. For other PMUs this is the default
* cpu map for opening the event on, for example, the first CPU on a
* socket for an uncore event.
*/
struct perf_cpu_map *pmu_cpus;
struct perf_thread_map *threads;
struct xyarray *fd;
struct xyarray *mmap;
struct xyarray *sample_id;
u64 *id;
u32 ids;
struct perf_evsel *leader;
/* For events where the read_format value is per-thread rather than
* global, stores the per-thread cumulative period */
struct list_head per_stream_periods;
/* parse modifier helper */
int nr_members;
/*
* system_wide is for events that need to be on every CPU, irrespective
* of user requested CPUs or threads. Tha main example of this is the
* dummy event. Map propagation will set cpus for this event to all CPUs
* as software PMU events like dummy, have a CPU map that is empty.
*/
bool system_wide;
/*
* Some events, for example uncore events, require a CPU.
* i.e. it cannot be the 'any CPU' value of -1.
*/
bool requires_cpu;
/** Is the PMU for the event a core one? Effects the handling of own_cpus. */
bool is_pmu_core;
/** Does the evsel on read on the first CPU index such as tool time events? */
bool reads_only_on_cpu_idx0;
int idx;
};
void perf_evsel__init(struct perf_evsel *evsel, struct perf_event_attr *attr,
int idx);
void perf_evsel__exit(struct perf_evsel *evsel);
int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
void perf_evsel__close_fd(struct perf_evsel *evsel);
void perf_evsel__free_fd(struct perf_evsel *evsel);
int perf_evsel__read_size(struct perf_evsel *evsel);
int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter);
int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
void perf_evsel__free_id(struct perf_evsel *evsel);
bool perf_evsel__attr_has_per_thread_sample_period(struct perf_evsel *evsel);
u64 *perf_sample_id__get_period_storage(struct perf_sample_id *sid, u32 tid,
bool per_thread);
#endif /* __LIBPERF_INTERNAL_EVSEL_H */
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_INTERNAL_LIB_H
#define __LIBPERF_INTERNAL_LIB_H
#include <sys/types.h>
extern unsigned int page_size;
ssize_t readn(int fd, void *buf, size_t n);
ssize_t writen(int fd, const void *buf, size_t n);
ssize_t preadn(int fd, void *buf, size_t n, off_t offs);
#endif /* __LIBPERF_INTERNAL_CPUMAP_H */
@@ -0,0 +1,60 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_INTERNAL_MMAP_H
#define __LIBPERF_INTERNAL_MMAP_H
#include <linux/compiler.h>
#include <linux/refcount.h>
#include <linux/types.h>
#include <stdbool.h>
#include <internal/cpumap.h>
/* perf sample has 16 bits size limit */
#define PERF_SAMPLE_MAX_SIZE (1 << 16)
struct perf_mmap;
struct perf_counts_values;
typedef void (*libperf_unmap_cb_t)(struct perf_mmap *map);
/**
* struct perf_mmap - perf's ring buffer mmap details
*
* @refcnt - e.g. code using PERF_EVENT_IOC_SET_OUTPUT to share this
*/
struct perf_mmap {
void *base;
int mask;
int fd;
struct perf_cpu cpu;
refcount_t refcnt;
u64 prev;
u64 start;
u64 end;
bool overwrite;
u64 flush;
libperf_unmap_cb_t unmap_cb;
void *event_copy;
size_t event_copy_sz;
struct perf_mmap *next;
};
struct perf_mmap_param {
int prot;
int mask;
};
size_t perf_mmap__mmap_len(struct perf_mmap *map);
void perf_mmap__init(struct perf_mmap *map, struct perf_mmap *prev,
bool overwrite, libperf_unmap_cb_t unmap_cb);
int perf_mmap__mmap(struct perf_mmap *map, struct perf_mmap_param *mp,
int fd, struct perf_cpu cpu);
void perf_mmap__munmap(struct perf_mmap *map);
void perf_mmap__get(struct perf_mmap *map);
void perf_mmap__put(struct perf_mmap *map);
u64 perf_mmap__read_head(struct perf_mmap *map);
int perf_mmap__read_self(struct perf_mmap *map, struct perf_counts_values *count);
#endif /* __LIBPERF_INTERNAL_MMAP_H */
@@ -0,0 +1,113 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __LIBPERF_INTERNAL_RC_CHECK_H
#define __LIBPERF_INTERNAL_RC_CHECK_H
#include <stdlib.h>
#include <linux/zalloc.h>
/*
* Enable reference count checking implicitly with leak checking, which is
* integrated into address sanitizer.
*/
#if defined(__SANITIZE_ADDRESS__) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
#define REFCNT_CHECKING 1
#elif defined(__has_feature)
#if __has_feature(address_sanitizer) || __has_feature(leak_sanitizer)
#define REFCNT_CHECKING 1
#endif
#endif
/*
* Shared reference count checking macros.
*
* Reference count checking is an approach to sanitizing the use of reference
* counted structs. It leverages address and leak sanitizers to make sure gets
* are paired with a put. Reference count checking adds a malloc-ed layer of
* indirection on a get, and frees it on a put. A missed put will be reported as
* a memory leak. A double put will be reported as a double free. Accessing
* after a put will cause a use-after-free and/or a segfault.
*/
#ifndef REFCNT_CHECKING
/* Replaces "struct foo" so that the pointer may be interposed. */
#define DECLARE_RC_STRUCT(struct_name) \
struct struct_name
/* Declare a reference counted struct variable. */
#define RC_STRUCT(struct_name) struct struct_name
/*
* Interpose the indirection. Result will hold the indirection and object is the
* reference counted struct.
*/
#define ADD_RC_CHK(result, object) (result = object, object)
/* Strip the indirection layer. */
#define RC_CHK_ACCESS(object) object
/* Frees the object and the indirection layer. */
#define RC_CHK_FREE(object) free(object)
/* A get operation adding the indirection layer. */
#define RC_CHK_GET(result, object) ADD_RC_CHK(result, object)
/* A put operation removing the indirection layer. */
#define RC_CHK_PUT(object) {}
/* Pointer equality when the indirection may or may not be there. */
#define RC_CHK_EQUAL(object1, object2) (object1 == object2)
#else
/* Replaces "struct foo" so that the pointer may be interposed. */
#define DECLARE_RC_STRUCT(struct_name) \
struct original_##struct_name; \
struct struct_name { \
struct original_##struct_name *orig; \
}; \
struct original_##struct_name
/* Declare a reference counted struct variable. */
#define RC_STRUCT(struct_name) struct original_##struct_name
/*
* Interpose the indirection. Result will hold the indirection and object is the
* reference counted struct.
*/
#define ADD_RC_CHK(result, object) \
( \
object ? (result = malloc(sizeof(*result)), \
result ? (result->orig = object, result) \
: (result = NULL, NULL)) \
: (result = NULL, NULL) \
)
/* Strip the indirection layer. */
#define RC_CHK_ACCESS(object) object->orig
/* Frees the object and the indirection layer. */
#define RC_CHK_FREE(object) \
do { \
zfree(&object->orig); \
free(object); \
} while(0)
/* A get operation adding the indirection layer. */
#define RC_CHK_GET(result, object) ADD_RC_CHK(result, (object ? object->orig : NULL))
/* A put operation removing the indirection layer. */
#define RC_CHK_PUT(object) \
do { \
if (object) { \
object->orig = NULL; \
free(object); \
} \
} while(0)
/* Pointer equality when the indirection may or may not be there. */
#define RC_CHK_EQUAL(object1, object2) (object1 == object2 || \
(object1 && object2 && object1->orig == object2->orig))
#endif
#endif /* __LIBPERF_INTERNAL_RC_CHECK_H */
@@ -0,0 +1,67 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_INTERNAL_TESTS_H
#define __LIBPERF_INTERNAL_TESTS_H
#include <stdio.h>
#include <unistd.h>
extern int tests_failed;
extern int tests_verbose;
static inline int get_verbose(char **argv, int argc)
{
int c;
int verbose = 0;
while ((c = getopt(argc, argv, "v")) != -1) {
switch (c)
{
case 'v':
verbose = 1;
break;
default:
break;
}
}
optind = 1;
return verbose;
}
#define __T_START \
do { \
tests_verbose = get_verbose(argv, argc); \
fprintf(stdout, "- running %s...", __FILE__); \
fflush(NULL); \
tests_failed = 0; \
} while (0)
#define __T_END \
do { \
if (tests_failed) \
fprintf(stdout, " FAILED (%d)\n", tests_failed); \
else \
fprintf(stdout, "OK\n"); \
} while (0)
#define __T(text, cond) \
do { \
if (!(cond)) { \
fprintf(stderr, "FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
tests_failed++; \
return -1; \
} \
} while (0)
#define __T_VERBOSE(...) \
do { \
if (tests_verbose) { \
if (tests_verbose == 1) { \
fputc('\n', stderr); \
tests_verbose++; \
} \
fprintf(stderr, ##__VA_ARGS__); \
} \
} while (0)
#endif /* __LIBPERF_INTERNAL_TESTS_H */
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_INTERNAL_THREADMAP_H
#define __LIBPERF_INTERNAL_THREADMAP_H
#include <linux/refcount.h>
#include <sys/types.h>
#include <unistd.h>
struct thread_map_data {
pid_t pid;
char *comm;
};
struct perf_thread_map {
refcount_t refcnt;
int nr;
int err_thread;
struct thread_map_data map[];
};
struct perf_thread_map *perf_thread_map__realloc(struct perf_thread_map *map, int nr);
#endif /* __LIBPERF_INTERNAL_THREADMAP_H */
@@ -0,0 +1,43 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_INTERNAL_XYARRAY_H
#define __LIBPERF_INTERNAL_XYARRAY_H
#include <linux/compiler.h>
#include <sys/types.h>
struct xyarray {
size_t row_size;
size_t entry_size;
size_t entries;
size_t max_x;
size_t max_y;
char contents[] __aligned(8);
};
struct xyarray *xyarray__new(int xlen, int ylen, size_t entry_size);
void xyarray__delete(struct xyarray *xy);
void xyarray__reset(struct xyarray *xy);
static inline void *__xyarray__entry(struct xyarray *xy, int x, int y)
{
return &xy->contents[x * xy->row_size + y * xy->entry_size];
}
static inline void *xyarray__entry(struct xyarray *xy, size_t x, size_t y)
{
if (x >= xy->max_x || y >= xy->max_y)
return NULL;
return __xyarray__entry(xy, x, y);
}
static inline int xyarray__max_y(struct xyarray *xy)
{
return xy->max_y;
}
static inline int xyarray__max_x(struct xyarray *xy)
{
return xy->max_x;
}
#endif /* __LIBPERF_INTERNAL_XYARRAY_H */
@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
#ifndef __LIBPERF_BPF_PERF_H
#define __LIBPERF_BPF_PERF_H
#include <linux/types.h> /* for __u32 */
/*
* bpf_perf uses a hashmap, the attr_map, to track all the leader programs.
* The hashmap is pinned in bpffs. flock() on this file is used to ensure
* no concurrent access to the attr_map. The key of attr_map is struct
* perf_event_attr, and the value is struct perf_event_attr_map_entry.
*
* struct perf_event_attr_map_entry contains two __u32 IDs, bpf_link of the
* leader prog, and the diff_map. Each perf-stat session holds a reference
* to the bpf_link to make sure the leader prog is attached to sched_switch
* tracepoint.
*
* Since the hashmap only contains IDs of the bpf_link and diff_map, it
* does not hold any references to the leader program. Once all perf-stat
* sessions of these events exit, the leader prog, its maps, and the
* perf_events will be freed.
*/
struct perf_event_attr_map_entry {
__u32 link_id;
__u32 diff_map_id;
};
/* default attr_map name */
#define BPF_PERF_DEFAULT_ATTR_MAP_PATH "perf_attr_map"
#endif /* __LIBPERF_BPF_PERF_H */
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_CORE_H
#define __LIBPERF_CORE_H
#include <stdarg.h>
#ifndef LIBPERF_API
#define LIBPERF_API extern __attribute__((visibility("default")))
#endif
enum libperf_print_level {
LIBPERF_ERR,
LIBPERF_WARN,
LIBPERF_INFO,
LIBPERF_DEBUG,
LIBPERF_DEBUG2,
LIBPERF_DEBUG3,
};
typedef int (*libperf_print_fn_t)(enum libperf_print_level level,
const char *, va_list ap);
LIBPERF_API void libperf_init(libperf_print_fn_t fn);
#endif /* __LIBPERF_CORE_H */
@@ -0,0 +1,110 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_CPUMAP_H
#define __LIBPERF_CPUMAP_H
#include <perf/core.h>
#include <stdbool.h>
#include <stdint.h>
/**
* struct perf_cpu - wrapper around a CPU number.
* @cpu: CPU number, -1 for the "any CPU"/dummy value.
*
* int16_t limits this to 32767 CPUs. Widening to int requires a libperf
* ABI bump — see tools/lib/perf/TODO for the full scope.
*/
struct perf_cpu {
int16_t cpu;
};
struct perf_cache {
int cache_lvl;
int cache;
};
struct perf_cpu_map;
/**
* perf_cpu_map__new_any_cpu - a map with a singular "any CPU"/dummy -1 value.
*/
LIBPERF_API struct perf_cpu_map *perf_cpu_map__new_any_cpu(void);
/**
* perf_cpu_map__new_online_cpus - a map read from
* /sys/devices/system/cpu/online if
* available. If reading wasn't possible a map
* is created using the online processors
* assuming the first 'n' processors are all
* online.
*/
LIBPERF_API struct perf_cpu_map *perf_cpu_map__new_online_cpus(void);
/**
* perf_cpu_map__new - create a map from the given cpu_list such as "0-7". If no
* cpu_list argument is provided then
* perf_cpu_map__new_online_cpus is returned.
*/
LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
/** perf_cpu_map__new_int - create a map with the one given cpu. */
LIBPERF_API struct perf_cpu_map *perf_cpu_map__new_int(int cpu);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
LIBPERF_API int perf_cpu_map__merge(struct perf_cpu_map **orig,
struct perf_cpu_map *other);
LIBPERF_API struct perf_cpu_map *perf_cpu_map__intersect(struct perf_cpu_map *orig,
struct perf_cpu_map *other);
LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map);
/**
* perf_cpu_map__cpu - get the CPU value at the given index. Returns -1 if index
* is invalid.
*/
LIBPERF_API struct perf_cpu perf_cpu_map__cpu(const struct perf_cpu_map *cpus, unsigned int idx);
/**
* perf_cpu_map__nr - for an empty map returns 1, as perf_cpu_map__cpu returns a
* cpu of -1 for an invalid index, this makes an empty map
* look like it contains the "any CPU"/dummy value. Otherwise
* the result is the number CPUs in the map plus one if the
* "any CPU"/dummy value is present.
*/
LIBPERF_API unsigned int perf_cpu_map__nr(const struct perf_cpu_map *cpus);
/**
* perf_cpu_map__has_any_cpu_or_is_empty - is map either empty or has the "any CPU"/dummy value.
*/
LIBPERF_API bool perf_cpu_map__has_any_cpu_or_is_empty(const struct perf_cpu_map *map);
/**
* perf_cpu_map__is_any_cpu_or_is_empty - is map either empty or the "any CPU"/dummy value.
*/
LIBPERF_API bool perf_cpu_map__is_any_cpu_or_is_empty(const struct perf_cpu_map *map);
/**
* perf_cpu_map__is_empty - does the map contain no values and it doesn't
* contain the special "any CPU"/dummy value.
*/
LIBPERF_API bool perf_cpu_map__is_empty(const struct perf_cpu_map *map);
/**
* perf_cpu_map__min - the minimum CPU value or -1 if empty or just the "any CPU"/dummy value.
*/
LIBPERF_API struct perf_cpu perf_cpu_map__min(const struct perf_cpu_map *map);
/**
* perf_cpu_map__max - the maximum CPU value or -1 if empty or just the "any CPU"/dummy value.
*/
LIBPERF_API struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *map);
LIBPERF_API bool perf_cpu_map__has(const struct perf_cpu_map *map, struct perf_cpu cpu);
LIBPERF_API bool perf_cpu_map__equal(const struct perf_cpu_map *lhs,
const struct perf_cpu_map *rhs);
/**
* perf_cpu_map__any_cpu - Does the map contain the "any CPU"/dummy -1 value?
*/
LIBPERF_API bool perf_cpu_map__has_any_cpu(const struct perf_cpu_map *map);
#define perf_cpu_map__for_each_cpu(cpu, idx, cpus) \
for ((idx) = 0, (cpu) = perf_cpu_map__cpu(cpus, idx); \
(idx) < perf_cpu_map__nr(cpus); \
(idx)++, (cpu) = perf_cpu_map__cpu(cpus, idx))
#define perf_cpu_map__for_each_cpu_skip_any(_cpu, idx, cpus) \
for ((idx) = 0, (_cpu) = perf_cpu_map__cpu(cpus, idx); \
(idx) < perf_cpu_map__nr(cpus); \
(idx)++, (_cpu) = perf_cpu_map__cpu(cpus, idx)) \
if ((_cpu).cpu != -1)
#define perf_cpu_map__for_each_idx(idx, cpus) \
for ((idx) = 0; (idx) < perf_cpu_map__nr(cpus); (idx)++)
#endif /* __LIBPERF_CPUMAP_H */
@@ -0,0 +1,643 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_EVENT_H
#define __LIBPERF_EVENT_H
#include <linux/perf_event.h>
#include <linux/types.h>
#include <linux/limits.h>
#include <linux/bpf.h>
#include <sys/types.h> /* pid_t */
/*
* Verify the full field fits within the event, not just its start offset.
* Only valid for fixed-size scalar fields — for trailing arrays like
* filename[PATH_MAX], sizeof() evaluates to the declared maximum, not
* the actual string length, so this would spuriously return false.
*/
#define event_contains(obj, mem) \
((obj).header.size >= offsetof(typeof(obj), mem) + sizeof((obj).mem))
struct perf_record_mmap {
struct perf_event_header header;
__u32 pid, tid;
__u64 start;
__u64 len;
__u64 pgoff;
char filename[PATH_MAX];
};
struct perf_record_mmap2 {
struct perf_event_header header;
__u32 pid, tid;
__u64 start;
__u64 len;
__u64 pgoff;
union {
struct {
__u32 maj;
__u32 min;
__u64 ino;
__u64 ino_generation;
};
struct {
__u8 build_id_size;
__u8 __reserved_1;
__u16 __reserved_2;
__u8 build_id[20];
};
};
__u32 prot;
__u32 flags;
char filename[PATH_MAX];
};
struct perf_record_comm {
struct perf_event_header header;
__u32 pid, tid;
char comm[16];
};
struct perf_record_namespaces {
struct perf_event_header header;
__u32 pid, tid;
__u64 nr_namespaces;
struct perf_ns_link_info link_info[];
};
struct perf_record_fork {
struct perf_event_header header;
__u32 pid, ppid;
__u32 tid, ptid;
__u64 time;
};
struct perf_record_lost {
struct perf_event_header header;
__u64 id;
__u64 lost;
};
#define PERF_RECORD_MISC_LOST_SAMPLES_BPF (1 << 15)
struct perf_record_lost_samples {
struct perf_event_header header;
__u64 lost;
};
#define MAX_ID_HDR_ENTRIES 6
struct perf_record_lost_samples_and_ids {
struct perf_record_lost_samples lost;
__u64 sample_ids[MAX_ID_HDR_ENTRIES];
};
/*
* PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID | PERF_FORMAT_LOST
*/
struct perf_record_read {
struct perf_event_header header;
__u32 pid, tid;
__u64 value;
__u64 time_enabled;
__u64 time_running;
__u64 id;
__u64 lost;
};
struct perf_record_throttle {
struct perf_event_header header;
__u64 time;
__u64 id;
__u64 stream_id;
};
#ifndef KSYM_NAME_LEN
#define KSYM_NAME_LEN 512
#endif
struct perf_record_ksymbol {
struct perf_event_header header;
__u64 addr;
__u32 len;
__u16 ksym_type;
__u16 flags;
char name[KSYM_NAME_LEN];
};
struct perf_record_bpf_event {
struct perf_event_header header;
__u16 type;
__u16 flags;
__u32 id;
/* for bpf_prog types */
__u8 tag[BPF_TAG_SIZE]; // prog tag
};
struct perf_record_cgroup {
struct perf_event_header header;
__u64 id;
char path[PATH_MAX];
};
struct perf_record_text_poke_event {
struct perf_event_header header;
__u64 addr;
__u16 old_len;
__u16 new_len;
__u8 bytes[];
};
struct perf_record_sample {
struct perf_event_header header;
__u64 array[];
};
struct perf_record_switch {
struct perf_event_header header;
__u32 next_prev_pid;
__u32 next_prev_tid;
};
struct perf_record_callchain_deferred {
struct perf_event_header header;
/*
* This is to match kernel and (deferred) user stacks together.
* The kernel part will be in the sample callchain array after
* the PERF_CONTEXT_USER_DEFERRED entry.
*/
__u64 cookie;
__u64 nr;
__u64 ips[];
};
struct perf_record_header_attr {
struct perf_event_header header;
struct perf_event_attr attr;
/*
* Array of u64 id follows here but we cannot use a flexible array
* because size of attr in the data can be different then current
* version. Please use perf_record_header_attr_id() below.
*
* __u64 id[]; // do not use this
*/
};
/* Returns the pointer to id array based on the actual attr size. */
#define perf_record_header_attr_id(evt) \
((void *)&(evt)->attr.attr + (evt)->attr.attr.size)
enum {
PERF_CPU_MAP__CPUS = 0,
PERF_CPU_MAP__MASK = 1,
PERF_CPU_MAP__RANGE_CPUS = 2,
};
/*
* Array encoding of a perf_cpu_map where nr is the number of entries in cpu[]
* and each entry is a value for a CPU in the map.
*/
struct cpu_map_entries {
__u16 nr;
__u16 cpu[];
};
/* Bitmap encoding of a perf_cpu_map where bitmap entries are 32-bit. */
struct perf_record_mask_cpu_map32 {
/* Number of mask values. */
__u16 nr;
/* Constant 4. */
__u16 long_size;
/* Bitmap data. */
__u32 mask[];
};
/* Bitmap encoding of a perf_cpu_map where bitmap entries are 64-bit. */
struct perf_record_mask_cpu_map64 {
/* Number of mask values. */
__u16 nr;
/* Constant 8. */
__u16 long_size;
/* Legacy padding. */
char __pad[4];
/* Bitmap data. */
__u64 mask[];
};
/*
* 'struct perf_record_cpu_map_data' is packed as unfortunately an earlier
* version had unaligned data and we wish to retain file format compatibility.
* -irogers
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
/*
* An encoding of a CPU map for a range starting at start_cpu through to
* end_cpu. If any_cpu is 1, an any CPU (-1) value (aka dummy value) is present.
*/
struct perf_record_range_cpu_map {
__u8 any_cpu;
__u8 __pad;
__u16 start_cpu;
__u16 end_cpu;
};
struct perf_record_cpu_map_data {
__u16 type;
union {
/* Used when type == PERF_CPU_MAP__CPUS. */
struct cpu_map_entries cpus_data;
/* Used when type == PERF_CPU_MAP__MASK and long_size == 4. */
struct perf_record_mask_cpu_map32 mask32_data;
/* Used when type == PERF_CPU_MAP__MASK and long_size == 8. */
struct perf_record_mask_cpu_map64 mask64_data;
/* Used when type == PERF_CPU_MAP__RANGE_CPUS. */
struct perf_record_range_cpu_map range_cpu_data;
};
} __attribute__((packed));
#pragma GCC diagnostic pop
struct perf_record_cpu_map {
struct perf_event_header header;
struct perf_record_cpu_map_data data;
};
enum {
PERF_EVENT_UPDATE__UNIT = 0,
PERF_EVENT_UPDATE__SCALE = 1,
PERF_EVENT_UPDATE__NAME = 2,
PERF_EVENT_UPDATE__CPUS = 3,
};
struct perf_record_event_update_cpus {
struct perf_record_cpu_map_data cpus;
};
struct perf_record_event_update_scale {
double scale;
};
struct perf_record_event_update {
struct perf_event_header header;
__u64 type;
__u64 id;
union {
/* Used when type == PERF_EVENT_UPDATE__SCALE. */
struct perf_record_event_update_scale scale;
/* Used when type == PERF_EVENT_UPDATE__UNIT. */
char unit[0];
/* Used when type == PERF_EVENT_UPDATE__NAME. */
char name[0];
/* Used when type == PERF_EVENT_UPDATE__CPUS. */
struct perf_record_event_update_cpus cpus;
};
};
#define MAX_EVENT_NAME 64
struct perf_trace_event_type {
__u64 event_id;
char name[MAX_EVENT_NAME];
};
struct perf_record_header_event_type {
struct perf_event_header header;
struct perf_trace_event_type event_type;
};
struct perf_record_header_tracing_data {
struct perf_event_header header;
__u32 size;
__u32 pad;
};
#define PERF_RECORD_MISC_BUILD_ID_SIZE (1 << 15)
struct perf_record_header_build_id {
struct perf_event_header header;
pid_t pid;
union {
__u8 build_id[24];
struct {
__u8 data[20];
__u8 size;
__u8 reserved1__;
__u16 reserved2__;
};
};
char filename[];
};
struct id_index_entry {
__u64 id;
__u64 idx;
__u64 cpu;
__u64 tid;
};
struct id_index_entry_2 {
__u64 machine_pid;
__u64 vcpu;
};
struct perf_record_id_index {
struct perf_event_header header;
__u64 nr;
struct id_index_entry entries[];
};
struct perf_record_auxtrace_info {
struct perf_event_header header;
__u32 type;
__u32 reserved__; /* For alignment */
__u64 priv[];
};
struct perf_record_auxtrace {
struct perf_event_header header;
__u64 size;
__u64 offset;
__u64 reference;
__u32 idx;
__u32 tid;
__u32 cpu;
__u32 reserved__; /* For alignment */
};
#define MAX_AUXTRACE_ERROR_MSG 64
struct perf_record_auxtrace_error {
struct perf_event_header header;
__u32 type;
__u32 code;
__u32 cpu;
__u32 pid;
__u32 tid;
__u32 fmt;
__u64 ip;
__u64 time;
char msg[MAX_AUXTRACE_ERROR_MSG];
__u32 machine_pid;
__u32 vcpu;
};
struct perf_record_aux {
struct perf_event_header header;
__u64 aux_offset;
__u64 aux_size;
__u64 flags;
};
struct perf_record_itrace_start {
struct perf_event_header header;
__u32 pid;
__u32 tid;
};
struct perf_record_aux_output_hw_id {
struct perf_event_header header;
__u64 hw_id;
};
struct perf_record_thread_map_entry {
__u64 pid;
char comm[16];
};
struct perf_record_thread_map {
struct perf_event_header header;
__u64 nr;
struct perf_record_thread_map_entry entries[];
};
enum {
PERF_STAT_CONFIG_TERM__AGGR_MODE = 0,
PERF_STAT_CONFIG_TERM__INTERVAL = 1,
PERF_STAT_CONFIG_TERM__SCALE = 2,
PERF_STAT_CONFIG_TERM__AGGR_LEVEL = 3,
PERF_STAT_CONFIG_TERM__MAX = 4,
};
struct perf_record_stat_config_entry {
__u64 tag;
__u64 val;
};
struct perf_record_stat_config {
struct perf_event_header header;
__u64 nr;
struct perf_record_stat_config_entry data[];
};
struct perf_record_stat {
struct perf_event_header header;
__u64 id;
__u32 cpu;
__u32 thread;
union {
struct {
__u64 val;
__u64 ena;
__u64 run;
};
__u64 values[3];
};
};
struct perf_record_stat_round {
struct perf_event_header header;
__u64 type;
__u64 time;
};
struct perf_record_time_conv {
struct perf_event_header header;
__u64 time_shift;
__u64 time_mult;
__u64 time_zero;
__u64 time_cycles;
__u64 time_mask;
__u8 cap_user_time_zero;
__u8 cap_user_time_short;
__u8 reserved[6]; /* For alignment */
};
struct perf_record_header_feature {
struct perf_event_header header;
__u64 feat_id;
char data[];
};
struct perf_record_compressed {
struct perf_event_header header;
char data[];
};
/*
* `header.size` includes the padding we are going to add while writing the record.
* `data_size` only includes the size of `data[]` itself.
*/
struct perf_record_compressed2 {
struct perf_event_header header;
__u64 data_size;
char data[];
};
#define BPF_METADATA_KEY_LEN 64
#define BPF_METADATA_VALUE_LEN 256
#define BPF_PROG_NAME_LEN KSYM_NAME_LEN
struct perf_record_bpf_metadata_entry {
char key[BPF_METADATA_KEY_LEN];
char value[BPF_METADATA_VALUE_LEN];
};
struct perf_record_bpf_metadata {
struct perf_event_header header;
char prog_name[BPF_PROG_NAME_LEN];
__u64 nr_entries;
struct perf_record_bpf_metadata_entry entries[];
};
struct perf_record_schedstat_cpu_v15 {
#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) _type _name
#include "schedstat-v15.h"
#undef CPU_FIELD
};
struct perf_record_schedstat_cpu_v16 {
#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) _type _name
#include "schedstat-v16.h"
#undef CPU_FIELD
};
struct perf_record_schedstat_cpu_v17 {
#define CPU_FIELD(_type, _name, _desc, _format, _is_pct, _pct_of, _ver) _type _name
#include "schedstat-v17.h"
#undef CPU_FIELD
};
struct perf_record_schedstat_cpu {
struct perf_event_header header;
__u64 timestamp;
__u32 cpu;
__u16 version;
/* Padding */
char __pad[2];
union {
struct perf_record_schedstat_cpu_v15 v15;
struct perf_record_schedstat_cpu_v16 v16;
struct perf_record_schedstat_cpu_v17 v17;
};
};
struct perf_record_schedstat_domain_v15 {
#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) _type _name
#include "schedstat-v15.h"
#undef DOMAIN_FIELD
};
struct perf_record_schedstat_domain_v16 {
#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) _type _name
#include "schedstat-v16.h"
#undef DOMAIN_FIELD
};
struct perf_record_schedstat_domain_v17 {
#define DOMAIN_FIELD(_type, _name, _desc, _format, _is_jiffies, _ver) _type _name
#include "schedstat-v17.h"
#undef DOMAIN_FIELD
};
#define DOMAIN_NAME_LEN 16
struct perf_record_schedstat_domain {
struct perf_event_header header;
__u64 timestamp;
__u32 cpu;
__u16 version;
__u16 domain;
union {
struct perf_record_schedstat_domain_v15 v15;
struct perf_record_schedstat_domain_v16 v16;
struct perf_record_schedstat_domain_v17 v17;
};
};
enum perf_user_event_type { /* above any possible kernel type */
PERF_RECORD_USER_TYPE_START = 64,
PERF_RECORD_HEADER_ATTR = 64,
PERF_RECORD_HEADER_EVENT_TYPE = 65, /* deprecated */
PERF_RECORD_HEADER_TRACING_DATA = 66,
PERF_RECORD_HEADER_BUILD_ID = 67,
PERF_RECORD_FINISHED_ROUND = 68,
PERF_RECORD_ID_INDEX = 69,
PERF_RECORD_AUXTRACE_INFO = 70,
PERF_RECORD_AUXTRACE = 71,
PERF_RECORD_AUXTRACE_ERROR = 72,
PERF_RECORD_THREAD_MAP = 73,
PERF_RECORD_CPU_MAP = 74,
PERF_RECORD_STAT_CONFIG = 75,
PERF_RECORD_STAT = 76,
PERF_RECORD_STAT_ROUND = 77,
PERF_RECORD_EVENT_UPDATE = 78,
PERF_RECORD_TIME_CONV = 79,
PERF_RECORD_HEADER_FEATURE = 80,
PERF_RECORD_COMPRESSED = 81,
PERF_RECORD_FINISHED_INIT = 82,
PERF_RECORD_COMPRESSED2 = 83,
PERF_RECORD_BPF_METADATA = 84,
PERF_RECORD_SCHEDSTAT_CPU = 85,
PERF_RECORD_SCHEDSTAT_DOMAIN = 86,
PERF_RECORD_HEADER_MAX
};
union perf_event {
struct perf_event_header header;
struct perf_record_mmap mmap;
struct perf_record_mmap2 mmap2;
struct perf_record_comm comm;
struct perf_record_namespaces namespaces;
struct perf_record_cgroup cgroup;
struct perf_record_fork fork;
struct perf_record_lost lost;
struct perf_record_lost_samples lost_samples;
struct perf_record_read read;
struct perf_record_throttle throttle;
struct perf_record_sample sample;
struct perf_record_callchain_deferred callchain_deferred;
struct perf_record_bpf_event bpf;
struct perf_record_ksymbol ksymbol;
struct perf_record_text_poke_event text_poke;
struct perf_record_header_attr attr;
struct perf_record_event_update event_update;
struct perf_record_header_event_type event_type;
struct perf_record_header_tracing_data tracing_data;
struct perf_record_header_build_id build_id;
struct perf_record_id_index id_index;
struct perf_record_auxtrace_info auxtrace_info;
struct perf_record_auxtrace auxtrace;
struct perf_record_auxtrace_error auxtrace_error;
struct perf_record_aux aux;
struct perf_record_itrace_start itrace_start;
struct perf_record_aux_output_hw_id aux_output_hw_id;
struct perf_record_switch context_switch;
struct perf_record_thread_map thread_map;
struct perf_record_cpu_map cpu_map;
struct perf_record_stat_config stat_config;
struct perf_record_stat stat;
struct perf_record_stat_round stat_round;
struct perf_record_time_conv time_conv;
struct perf_record_header_feature feat;
struct perf_record_compressed pack;
struct perf_record_compressed2 pack2;
struct perf_record_bpf_metadata bpf_metadata;
struct perf_record_schedstat_cpu schedstat_cpu;
struct perf_record_schedstat_domain schedstat_domain;
};
#endif /* __LIBPERF_EVENT_H */
@@ -0,0 +1,51 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_EVLIST_H
#define __LIBPERF_EVLIST_H
#include <perf/core.h>
#include <stdbool.h>
struct perf_evlist;
struct perf_evsel;
struct perf_cpu_map;
struct perf_thread_map;
LIBPERF_API void perf_evlist__add(struct perf_evlist *evlist,
struct perf_evsel *evsel);
LIBPERF_API void perf_evlist__remove(struct perf_evlist *evlist,
struct perf_evsel *evsel);
LIBPERF_API struct perf_evlist *perf_evlist__new(void);
LIBPERF_API void perf_evlist__delete(struct perf_evlist *evlist);
LIBPERF_API struct perf_evsel* perf_evlist__next(struct perf_evlist *evlist,
struct perf_evsel *evsel);
LIBPERF_API int perf_evlist__open(struct perf_evlist *evlist);
LIBPERF_API void perf_evlist__close(struct perf_evlist *evlist);
LIBPERF_API void perf_evlist__enable(struct perf_evlist *evlist);
LIBPERF_API void perf_evlist__disable(struct perf_evlist *evlist);
#define perf_evlist__for_each_evsel(evlist, pos) \
for ((pos) = perf_evlist__next((evlist), NULL); \
(pos) != NULL; \
(pos) = perf_evlist__next((evlist), (pos)))
LIBPERF_API void perf_evlist__set_maps(struct perf_evlist *evlist,
struct perf_cpu_map *cpus,
struct perf_thread_map *threads);
LIBPERF_API int perf_evlist__poll(struct perf_evlist *evlist, int timeout);
LIBPERF_API int perf_evlist__filter_pollfd(struct perf_evlist *evlist,
short revents_and_mask);
LIBPERF_API int perf_evlist__mmap(struct perf_evlist *evlist, int pages);
LIBPERF_API void perf_evlist__munmap(struct perf_evlist *evlist);
LIBPERF_API struct perf_mmap *perf_evlist__next_mmap(struct perf_evlist *evlist,
struct perf_mmap *map,
bool overwrite);
#define perf_evlist__for_each_mmap(evlist, pos, overwrite) \
for ((pos) = perf_evlist__next_mmap((evlist), NULL, overwrite); \
(pos) != NULL; \
(pos) = perf_evlist__next_mmap((evlist), (pos), overwrite))
LIBPERF_API void perf_evlist__set_leader(struct perf_evlist *evlist);
LIBPERF_API int perf_evlist__nr_groups(struct perf_evlist *evlist);
#endif /* __LIBPERF_EVLIST_H */
@@ -0,0 +1,50 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_EVSEL_H
#define __LIBPERF_EVSEL_H
#include <stdint.h>
#include <perf/core.h>
#include <stdbool.h>
#include <linux/types.h>
struct perf_evsel;
struct perf_event_attr;
struct perf_cpu_map;
struct perf_thread_map;
struct perf_counts_values {
union {
struct {
uint64_t val;
uint64_t ena;
uint64_t run;
uint64_t id;
uint64_t lost;
};
uint64_t values[5];
};
};
LIBPERF_API struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr);
LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel);
LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
struct perf_thread_map *threads);
LIBPERF_API void perf_evsel__close(struct perf_evsel *evsel);
LIBPERF_API void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu_map_idx);
LIBPERF_API int perf_evsel__mmap(struct perf_evsel *evsel, int pages);
LIBPERF_API void perf_evsel__munmap(struct perf_evsel *evsel);
LIBPERF_API void *perf_evsel__mmap_base(struct perf_evsel *evsel, int cpu_map_idx, int thread);
LIBPERF_API int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread,
struct perf_counts_values *count);
LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel);
LIBPERF_API int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
LIBPERF_API int perf_evsel__enable_thread(struct perf_evsel *evsel, int thread);
LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel);
LIBPERF_API int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu_map_idx);
LIBPERF_API struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
LIBPERF_API struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
LIBPERF_API void perf_counts_values__scale(struct perf_counts_values *count,
bool scale, __s8 *pscaled);
#endif /* __LIBPERF_EVSEL_H */
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_MMAP_H
#define __LIBPERF_MMAP_H
#include <perf/core.h>
struct perf_mmap;
union perf_event;
LIBPERF_API void perf_mmap__consume(struct perf_mmap *map);
LIBPERF_API int perf_mmap__read_init(struct perf_mmap *map);
LIBPERF_API void perf_mmap__read_done(struct perf_mmap *map);
LIBPERF_API union perf_event *perf_mmap__read_event(struct perf_mmap *map);
#endif /* __LIBPERF_MMAP_H */
@@ -0,0 +1,146 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifdef CPU_FIELD
CPU_FIELD(__u32, yld_count, "sched_yield() count",
"%11u", false, yld_count, v15);
CPU_FIELD(__u32, array_exp, "Legacy counter can be ignored",
"%11u", false, array_exp, v15);
CPU_FIELD(__u32, sched_count, "schedule() called",
"%11u", false, sched_count, v15);
CPU_FIELD(__u32, sched_goidle, "schedule() left the processor idle",
"%11u", true, sched_count, v15);
CPU_FIELD(__u32, ttwu_count, "try_to_wake_up() was called",
"%11u", false, ttwu_count, v15);
CPU_FIELD(__u32, ttwu_local, "try_to_wake_up() was called to wake up the local cpu",
"%11u", true, ttwu_count, v15);
CPU_FIELD(__u64, rq_cpu_time, "total runtime by tasks on this processor (in jiffies)",
"%11llu", false, rq_cpu_time, v15);
CPU_FIELD(__u64, run_delay, "total waittime by tasks on this processor (in jiffies)",
"%11llu", true, rq_cpu_time, v15);
CPU_FIELD(__u64, pcount, "total timeslices run on this cpu",
"%11llu", false, pcount, v15);
#endif
#ifdef DOMAIN_FIELD
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category idle> ");
#endif
DOMAIN_FIELD(__u32, idle_lb_count,
"load_balance() count on cpu idle", "%11u", true, v15);
DOMAIN_FIELD(__u32, idle_lb_balanced,
"load_balance() found balanced on cpu idle", "%11u", true, v15);
DOMAIN_FIELD(__u32, idle_lb_failed,
"load_balance() move task failed on cpu idle", "%11u", true, v15);
DOMAIN_FIELD(__u32, idle_lb_imbalance,
"imbalance sum on cpu idle", "%11u", false, v15);
DOMAIN_FIELD(__u32, idle_lb_gained,
"pull_task() count on cpu idle", "%11u", false, v15);
DOMAIN_FIELD(__u32, idle_lb_hot_gained,
"pull_task() when target task was cache-hot on cpu idle", "%11u", false, v15);
DOMAIN_FIELD(__u32, idle_lb_nobusyq,
"load_balance() failed to find busier queue on cpu idle", "%11u", true, v15);
DOMAIN_FIELD(__u32, idle_lb_nobusyg,
"load_balance() failed to find busier group on cpu idle", "%11u", true, v15);
#ifdef DERIVED_CNT_FIELD
DERIVED_CNT_FIELD(idle_lb_success_count, "load_balance() success count on cpu idle", "%11u",
idle_lb_count, idle_lb_balanced, idle_lb_failed, v15);
#endif
#ifdef DERIVED_AVG_FIELD
DERIVED_AVG_FIELD(idle_lb_avg_pulled,
"avg task pulled per successful lb attempt (cpu idle)", "%11.2Lf",
idle_lb_count, idle_lb_balanced, idle_lb_failed, idle_lb_gained, v15);
#endif
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category busy> ");
#endif
DOMAIN_FIELD(__u32, busy_lb_count,
"load_balance() count on cpu busy", "%11u", true, v15);
DOMAIN_FIELD(__u32, busy_lb_balanced,
"load_balance() found balanced on cpu busy", "%11u", true, v15);
DOMAIN_FIELD(__u32, busy_lb_failed,
"load_balance() move task failed on cpu busy", "%11u", true, v15);
DOMAIN_FIELD(__u32, busy_lb_imbalance,
"imbalance sum on cpu busy", "%11u", false, v15);
DOMAIN_FIELD(__u32, busy_lb_gained,
"pull_task() count on cpu busy", "%11u", false, v15);
DOMAIN_FIELD(__u32, busy_lb_hot_gained,
"pull_task() when target task was cache-hot on cpu busy", "%11u", false, v15);
DOMAIN_FIELD(__u32, busy_lb_nobusyq,
"load_balance() failed to find busier queue on cpu busy", "%11u", true, v15);
DOMAIN_FIELD(__u32, busy_lb_nobusyg,
"load_balance() failed to find busier group on cpu busy", "%11u", true, v15);
#ifdef DERIVED_CNT_FIELD
DERIVED_CNT_FIELD(busy_lb_success_count, "load_balance() success count on cpu busy", "%11u",
busy_lb_count, busy_lb_balanced, busy_lb_failed, v15);
#endif
#ifdef DERIVED_AVG_FIELD
DERIVED_AVG_FIELD(busy_lb_avg_pulled,
"avg task pulled per successful lb attempt (cpu busy)", "%11.2Lf",
busy_lb_count, busy_lb_balanced, busy_lb_failed, busy_lb_gained, v15);
#endif
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category newidle> ");
#endif
DOMAIN_FIELD(__u32, newidle_lb_count,
"load_balance() count on cpu newly idle", "%11u", true, v15);
DOMAIN_FIELD(__u32, newidle_lb_balanced,
"load_balance() found balanced on cpu newly idle", "%11u", true, v15);
DOMAIN_FIELD(__u32, newidle_lb_failed,
"load_balance() move task failed on cpu newly idle", "%11u", true, v15);
DOMAIN_FIELD(__u32, newidle_lb_imbalance,
"imbalance sum on cpu newly idle", "%11u", false, v15);
DOMAIN_FIELD(__u32, newidle_lb_gained,
"pull_task() count on cpu newly idle", "%11u", false, v15);
DOMAIN_FIELD(__u32, newidle_lb_hot_gained,
"pull_task() when target task was cache-hot on cpu newly idle", "%11u", false, v15);
DOMAIN_FIELD(__u32, newidle_lb_nobusyq,
"load_balance() failed to find busier queue on cpu newly idle", "%11u", true, v15);
DOMAIN_FIELD(__u32, newidle_lb_nobusyg,
"load_balance() failed to find busier group on cpu newly idle", "%11u", true, v15);
#ifdef DERIVED_CNT_FIELD
DERIVED_CNT_FIELD(newidle_lb_success_count,
"load_balance() success count on cpu newly idle", "%11u",
newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, v15);
#endif
#ifdef DERIVED_AVG_FIELD
DERIVED_AVG_FIELD(newidle_lb_avg_pulled,
"avg task pulled per successful lb attempt (cpu newly idle)", "%11.2Lf",
newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, newidle_lb_gained, v15);
#endif
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category active_load_balance()> ");
#endif
DOMAIN_FIELD(__u32, alb_count,
"active_load_balance() count", "%11u", false, v15);
DOMAIN_FIELD(__u32, alb_failed,
"active_load_balance() move task failed", "%11u", false, v15);
DOMAIN_FIELD(__u32, alb_pushed,
"active_load_balance() successfully moved a task", "%11u", false, v15);
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category sched_balance_exec()> ");
#endif
DOMAIN_FIELD(__u32, sbe_count,
"sbe_count is not used", "%11u", false, v15);
DOMAIN_FIELD(__u32, sbe_balanced,
"sbe_balanced is not used", "%11u", false, v15);
DOMAIN_FIELD(__u32, sbe_pushed,
"sbe_pushed is not used", "%11u", false, v15);
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category sched_balance_fork()> ");
#endif
DOMAIN_FIELD(__u32, sbf_count,
"sbf_count is not used", "%11u", false, v15);
DOMAIN_FIELD(__u32, sbf_balanced,
"sbf_balanced is not used", "%11u", false, v15);
DOMAIN_FIELD(__u32, sbf_pushed,
"sbf_pushed is not used", "%11u", false, v15);
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Wakeup Info> ");
#endif
DOMAIN_FIELD(__u32, ttwu_wake_remote,
"try_to_wake_up() awoke a task that last ran on a diff cpu", "%11u", false, v15);
DOMAIN_FIELD(__u32, ttwu_move_affine,
"try_to_wake_up() moved task because cache-cold on own cpu", "%11u", false, v15);
DOMAIN_FIELD(__u32, ttwu_move_balance,
"try_to_wake_up() started passive balancing", "%11u", false, v15);
#endif /* DOMAIN_FIELD */
@@ -0,0 +1,146 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifdef CPU_FIELD
CPU_FIELD(__u32, yld_count, "sched_yield() count",
"%11u", false, yld_count, v16);
CPU_FIELD(__u32, array_exp, "Legacy counter can be ignored",
"%11u", false, array_exp, v16);
CPU_FIELD(__u32, sched_count, "schedule() called",
"%11u", false, sched_count, v16);
CPU_FIELD(__u32, sched_goidle, "schedule() left the processor idle",
"%11u", true, sched_count, v16);
CPU_FIELD(__u32, ttwu_count, "try_to_wake_up() was called",
"%11u", false, ttwu_count, v16);
CPU_FIELD(__u32, ttwu_local, "try_to_wake_up() was called to wake up the local cpu",
"%11u", true, ttwu_count, v16);
CPU_FIELD(__u64, rq_cpu_time, "total runtime by tasks on this processor (in jiffies)",
"%11llu", false, rq_cpu_time, v16);
CPU_FIELD(__u64, run_delay, "total waittime by tasks on this processor (in jiffies)",
"%11llu", true, rq_cpu_time, v16);
CPU_FIELD(__u64, pcount, "total timeslices run on this cpu",
"%11llu", false, pcount, v16);
#endif /* CPU_FIELD */
#ifdef DOMAIN_FIELD
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category busy> ");
#endif
DOMAIN_FIELD(__u32, busy_lb_count,
"load_balance() count on cpu busy", "%11u", true, v16);
DOMAIN_FIELD(__u32, busy_lb_balanced,
"load_balance() found balanced on cpu busy", "%11u", true, v16);
DOMAIN_FIELD(__u32, busy_lb_failed,
"load_balance() move task failed on cpu busy", "%11u", true, v16);
DOMAIN_FIELD(__u32, busy_lb_imbalance,
"imbalance sum on cpu busy", "%11u", false, v16);
DOMAIN_FIELD(__u32, busy_lb_gained,
"pull_task() count on cpu busy", "%11u", false, v16);
DOMAIN_FIELD(__u32, busy_lb_hot_gained,
"pull_task() when target task was cache-hot on cpu busy", "%11u", false, v16);
DOMAIN_FIELD(__u32, busy_lb_nobusyq,
"load_balance() failed to find busier queue on cpu busy", "%11u", true, v16);
DOMAIN_FIELD(__u32, busy_lb_nobusyg,
"load_balance() failed to find busier group on cpu busy", "%11u", true, v16);
#ifdef DERIVED_CNT_FIELD
DERIVED_CNT_FIELD(busy_lb_success_count, "load_balance() success count on cpu busy", "%11u",
busy_lb_count, busy_lb_balanced, busy_lb_failed, v16);
#endif
#ifdef DERIVED_AVG_FIELD
DERIVED_AVG_FIELD(busy_lb_avg_pulled,
"avg task pulled per successful lb attempt (cpu busy)", "%11.2Lf",
busy_lb_count, busy_lb_balanced, busy_lb_failed, busy_lb_gained, v16);
#endif
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category idle> ");
#endif
DOMAIN_FIELD(__u32, idle_lb_count,
"load_balance() count on cpu idle", "%11u", true, v16);
DOMAIN_FIELD(__u32, idle_lb_balanced,
"load_balance() found balanced on cpu idle", "%11u", true, v16);
DOMAIN_FIELD(__u32, idle_lb_failed,
"load_balance() move task failed on cpu idle", "%11u", true, v16);
DOMAIN_FIELD(__u32, idle_lb_imbalance,
"imbalance sum on cpu idle", "%11u", false, v16);
DOMAIN_FIELD(__u32, idle_lb_gained,
"pull_task() count on cpu idle", "%11u", false, v16);
DOMAIN_FIELD(__u32, idle_lb_hot_gained,
"pull_task() when target task was cache-hot on cpu idle", "%11u", false, v16);
DOMAIN_FIELD(__u32, idle_lb_nobusyq,
"load_balance() failed to find busier queue on cpu idle", "%11u", true, v16);
DOMAIN_FIELD(__u32, idle_lb_nobusyg,
"load_balance() failed to find busier group on cpu idle", "%11u", true, v16);
#ifdef DERIVED_CNT_FIELD
DERIVED_CNT_FIELD(idle_lb_success_count, "load_balance() success count on cpu idle", "%11u",
idle_lb_count, idle_lb_balanced, idle_lb_failed, v16);
#endif
#ifdef DERIVED_AVG_FIELD
DERIVED_AVG_FIELD(idle_lb_avg_pulled,
"avg task pulled per successful lb attempt (cpu idle)", "%11.2Lf",
idle_lb_count, idle_lb_balanced, idle_lb_failed, idle_lb_gained, v16);
#endif
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category newidle> ");
#endif
DOMAIN_FIELD(__u32, newidle_lb_count,
"load_balance() count on cpu newly idle", "%11u", true, v16);
DOMAIN_FIELD(__u32, newidle_lb_balanced,
"load_balance() found balanced on cpu newly idle", "%11u", true, v16);
DOMAIN_FIELD(__u32, newidle_lb_failed,
"load_balance() move task failed on cpu newly idle", "%11u", true, v16);
DOMAIN_FIELD(__u32, newidle_lb_imbalance,
"imbalance sum on cpu newly idle", "%11u", false, v16);
DOMAIN_FIELD(__u32, newidle_lb_gained,
"pull_task() count on cpu newly idle", "%11u", false, v16);
DOMAIN_FIELD(__u32, newidle_lb_hot_gained,
"pull_task() when target task was cache-hot on cpu newly idle", "%11u", false, v16);
DOMAIN_FIELD(__u32, newidle_lb_nobusyq,
"load_balance() failed to find busier queue on cpu newly idle", "%11u", true, v16);
DOMAIN_FIELD(__u32, newidle_lb_nobusyg,
"load_balance() failed to find busier group on cpu newly idle", "%11u", true, v16);
#ifdef DERIVED_CNT_FIELD
DERIVED_CNT_FIELD(newidle_lb_success_count,
"load_balance() success count on cpu newly idle", "%11u",
newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, v16);
#endif
#ifdef DERIVED_AVG_FIELD
DERIVED_AVG_FIELD(newidle_lb_avg_count,
"avg task pulled per successful lb attempt (cpu newly idle)", "%11.2Lf",
newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, newidle_lb_gained, v16);
#endif
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category active_load_balance()> ");
#endif
DOMAIN_FIELD(__u32, alb_count,
"active_load_balance() count", "%11u", false, v16);
DOMAIN_FIELD(__u32, alb_failed,
"active_load_balance() move task failed", "%11u", false, v16);
DOMAIN_FIELD(__u32, alb_pushed,
"active_load_balance() successfully moved a task", "%11u", false, v16);
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category sched_balance_exec()> ");
#endif
DOMAIN_FIELD(__u32, sbe_count,
"sbe_count is not used", "%11u", false, v16);
DOMAIN_FIELD(__u32, sbe_balanced,
"sbe_balanced is not used", "%11u", false, v16);
DOMAIN_FIELD(__u32, sbe_pushed,
"sbe_pushed is not used", "%11u", false, v16);
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category sched_balance_fork()> ");
#endif
DOMAIN_FIELD(__u32, sbf_count,
"sbf_count is not used", "%11u", false, v16);
DOMAIN_FIELD(__u32, sbf_balanced,
"sbf_balanced is not used", "%11u", false, v16);
DOMAIN_FIELD(__u32, sbf_pushed,
"sbf_pushed is not used", "%11u", false, v16);
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Wakeup Info> ");
#endif
DOMAIN_FIELD(__u32, ttwu_wake_remote,
"try_to_wake_up() awoke a task that last ran on a diff cpu", "%11u", false, v16);
DOMAIN_FIELD(__u32, ttwu_move_affine,
"try_to_wake_up() moved task because cache-cold on own cpu", "%11u", false, v16);
DOMAIN_FIELD(__u32, ttwu_move_balance,
"try_to_wake_up() started passive balancing", "%11u", false, v16);
#endif /* DOMAIN_FIELD */
@@ -0,0 +1,164 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifdef CPU_FIELD
CPU_FIELD(__u32, yld_count, "sched_yield() count",
"%11u", false, yld_count, v17);
CPU_FIELD(__u32, array_exp, "Legacy counter can be ignored",
"%11u", false, array_exp, v17);
CPU_FIELD(__u32, sched_count, "schedule() called",
"%11u", false, sched_count, v17);
CPU_FIELD(__u32, sched_goidle, "schedule() left the processor idle",
"%11u", true, sched_count, v17);
CPU_FIELD(__u32, ttwu_count, "try_to_wake_up() was called",
"%11u", false, ttwu_count, v17);
CPU_FIELD(__u32, ttwu_local, "try_to_wake_up() was called to wake up the local cpu",
"%11u", true, ttwu_count, v17);
CPU_FIELD(__u64, rq_cpu_time, "total runtime by tasks on this processor (in jiffies)",
"%11llu", false, rq_cpu_time, v17);
CPU_FIELD(__u64, run_delay, "total waittime by tasks on this processor (in jiffies)",
"%11llu", true, rq_cpu_time, v17);
CPU_FIELD(__u64, pcount, "total timeslices run on this cpu",
"%11llu", false, pcount, v17);
#endif /* CPU_FIELD */
#ifdef DOMAIN_FIELD
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category busy> ");
#endif
DOMAIN_FIELD(__u32, busy_lb_count,
"load_balance() count on cpu busy", "%11u", true, v17);
DOMAIN_FIELD(__u32, busy_lb_balanced,
"load_balance() found balanced on cpu busy", "%11u", true, v17);
DOMAIN_FIELD(__u32, busy_lb_failed,
"load_balance() move task failed on cpu busy", "%11u", true, v17);
DOMAIN_FIELD(__u32, busy_lb_imbalance_load,
"imbalance in load on cpu busy", "%11u", false, v17);
DOMAIN_FIELD(__u32, busy_lb_imbalance_util,
"imbalance in utilization on cpu busy", "%11u", false, v17);
DOMAIN_FIELD(__u32, busy_lb_imbalance_task,
"imbalance in number of tasks on cpu busy", "%11u", false, v17);
DOMAIN_FIELD(__u32, busy_lb_imbalance_misfit,
"imbalance in misfit tasks on cpu busy", "%11u", false, v17);
DOMAIN_FIELD(__u32, busy_lb_gained,
"pull_task() count on cpu busy", "%11u", false, v17);
DOMAIN_FIELD(__u32, busy_lb_hot_gained,
"pull_task() when target task was cache-hot on cpu busy", "%11u", false, v17);
DOMAIN_FIELD(__u32, busy_lb_nobusyq,
"load_balance() failed to find busier queue on cpu busy", "%11u", true, v17);
DOMAIN_FIELD(__u32, busy_lb_nobusyg,
"load_balance() failed to find busier group on cpu busy", "%11u", true, v17);
#ifdef DERIVED_CNT_FIELD
DERIVED_CNT_FIELD(busy_lb_success_count, "load_balance() success count on cpu busy", "%11u",
busy_lb_count, busy_lb_balanced, busy_lb_failed, v17);
#endif
#ifdef DERIVED_AVG_FIELD
DERIVED_AVG_FIELD(busy_lb_avg_pulled,
"avg task pulled per successful lb attempt (cpu busy)", "%11.2Lf",
busy_lb_count, busy_lb_balanced, busy_lb_failed, busy_lb_gained, v17);
#endif
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category idle> ");
#endif
DOMAIN_FIELD(__u32, idle_lb_count,
"load_balance() count on cpu idle", "%11u", true, v17);
DOMAIN_FIELD(__u32, idle_lb_balanced,
"load_balance() found balanced on cpu idle", "%11u", true, v17);
DOMAIN_FIELD(__u32, idle_lb_failed,
"load_balance() move task failed on cpu idle", "%11u", true, v17);
DOMAIN_FIELD(__u32, idle_lb_imbalance_load,
"imbalance in load on cpu idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, idle_lb_imbalance_util,
"imbalance in utilization on cpu idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, idle_lb_imbalance_task,
"imbalance in number of tasks on cpu idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, idle_lb_imbalance_misfit,
"imbalance in misfit tasks on cpu idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, idle_lb_gained,
"pull_task() count on cpu idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, idle_lb_hot_gained,
"pull_task() when target task was cache-hot on cpu idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, idle_lb_nobusyq,
"load_balance() failed to find busier queue on cpu idle", "%11u", true, v17);
DOMAIN_FIELD(__u32, idle_lb_nobusyg,
"load_balance() failed to find busier group on cpu idle", "%11u", true, v17);
#ifdef DERIVED_CNT_FIELD
DERIVED_CNT_FIELD(idle_lb_success_count, "load_balance() success count on cpu idle", "%11u",
idle_lb_count, idle_lb_balanced, idle_lb_failed, v17);
#endif
#ifdef DERIVED_AVG_FIELD
DERIVED_AVG_FIELD(idle_lb_avg_pulled,
"avg task pulled per successful lb attempt (cpu idle)", "%11.2Lf",
idle_lb_count, idle_lb_balanced, idle_lb_failed, idle_lb_gained, v17);
#endif
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category newidle> ");
#endif
DOMAIN_FIELD(__u32, newidle_lb_count,
"load_balance() count on cpu newly idle", "%11u", true, v17);
DOMAIN_FIELD(__u32, newidle_lb_balanced,
"load_balance() found balanced on cpu newly idle", "%11u", true, v17);
DOMAIN_FIELD(__u32, newidle_lb_failed,
"load_balance() move task failed on cpu newly idle", "%11u", true, v17);
DOMAIN_FIELD(__u32, newidle_lb_imbalance_load,
"imbalance in load on cpu newly idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, newidle_lb_imbalance_util,
"imbalance in utilization on cpu newly idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, newidle_lb_imbalance_task,
"imbalance in number of tasks on cpu newly idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, newidle_lb_imbalance_misfit,
"imbalance in misfit tasks on cpu newly idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, newidle_lb_gained,
"pull_task() count on cpu newly idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, newidle_lb_hot_gained,
"pull_task() when target task was cache-hot on cpu newly idle", "%11u", false, v17);
DOMAIN_FIELD(__u32, newidle_lb_nobusyq,
"load_balance() failed to find busier queue on cpu newly idle", "%11u", true, v17);
DOMAIN_FIELD(__u32, newidle_lb_nobusyg,
"load_balance() failed to find busier group on cpu newly idle", "%11u", true, v17);
#ifdef DERIVED_CNT_FIELD
DERIVED_CNT_FIELD(newidle_lb_success_count,
"load_balance() success count on cpu newly idle", "%11u",
newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, v17);
#endif
#ifdef DERIVED_AVG_FIELD
DERIVED_AVG_FIELD(newidle_lb_avg_pulled,
"avg task pulled per successful lb attempt (cpu newly idle)", "%11.2Lf",
newidle_lb_count, newidle_lb_balanced, newidle_lb_failed, newidle_lb_gained, v17);
#endif
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category active_load_balance()> ");
#endif
DOMAIN_FIELD(__u32, alb_count,
"active_load_balance() count", "%11u", false, v17);
DOMAIN_FIELD(__u32, alb_failed,
"active_load_balance() move task failed", "%11u", false, v17);
DOMAIN_FIELD(__u32, alb_pushed,
"active_load_balance() successfully moved a task", "%11u", false, v17);
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category sched_balance_exec()> ");
#endif
DOMAIN_FIELD(__u32, sbe_count,
"sbe_count is not used", "%11u", false, v17);
DOMAIN_FIELD(__u32, sbe_balanced,
"sbe_balanced is not used", "%11u", false, v17);
DOMAIN_FIELD(__u32, sbe_pushed,
"sbe_pushed is not used", "%11u", false, v17);
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Category sched_balance_fork()> ");
#endif
DOMAIN_FIELD(__u32, sbf_count,
"sbf_count is not used", "%11u", false, v17);
DOMAIN_FIELD(__u32, sbf_balanced,
"sbf_balanced is not used", "%11u", false, v17);
DOMAIN_FIELD(__u32, sbf_pushed,
"sbf_pushed is not used", "%11u", false, v17);
#ifdef DOMAIN_CATEGORY
DOMAIN_CATEGORY(" <Wakeup Info> ");
#endif
DOMAIN_FIELD(__u32, ttwu_wake_remote,
"try_to_wake_up() awoke a task that last ran on a diff cpu", "%11u", false, v17);
DOMAIN_FIELD(__u32, ttwu_move_affine,
"try_to_wake_up() moved task because cache-cold on own cpu", "%11u", false, v17);
DOMAIN_FIELD(__u32, ttwu_move_balance,
"try_to_wake_up() started passive balancing", "%11u", false, v17);
#endif /* DOMAIN_FIELD */
@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LIBPERF_THREADMAP_H
#define __LIBPERF_THREADMAP_H
#include <perf/core.h>
#include <sys/types.h>
struct perf_thread_map;
LIBPERF_API struct perf_thread_map *perf_thread_map__new_dummy(void);
LIBPERF_API struct perf_thread_map *perf_thread_map__new_array(int nr_threads, pid_t *array);
LIBPERF_API void perf_thread_map__set_pid(struct perf_thread_map *map, int idx, pid_t pid);
LIBPERF_API char *perf_thread_map__comm(struct perf_thread_map *map, int idx);
LIBPERF_API int perf_thread_map__nr(struct perf_thread_map *threads);
LIBPERF_API pid_t perf_thread_map__pid(struct perf_thread_map *map, int idx);
LIBPERF_API int perf_thread_map__idx(struct perf_thread_map *map, pid_t pid);
LIBPERF_API struct perf_thread_map *perf_thread_map__get(struct perf_thread_map *map);
LIBPERF_API void perf_thread_map__put(struct perf_thread_map *map);
#endif /* __LIBPERF_THREADMAP_H */