1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
#ifndef UFTRACE_PERF_H
#define UFTRACE_PERF_H
#include <linux/perf_event.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#define PERF_MMAP_SIZE (132 * 1024) /* 32 + 1 pages */
#define PERF_WATERMARK (8 * 1024) /* 2 pages */
#define COMM_LEN 16
struct uftrace_perf_writer {
int *event_fd;
void **page;
uint64_t *data_pos;
FILE **fp;
int nr_event;
};
struct sample_id {
uint32_t pid;
uint32_t tid;
uint64_t time;
};
struct perf_task_event {
/*
* type: PERF_RECORD_FORK (7) or PERF_RECORD_EXIT (4)
*/
uint32_t pid, ppid;
uint32_t tid, ptid;
uint64_t time;
struct sample_id sample_id;
};
struct perf_comm_event {
/*
* type: PERF_RECORD_COMM (3)
*/
uint32_t pid, tid;
/* variable length (aligned to 8) */
char comm[COMM_LEN];
/* needs to be read separately */
struct sample_id sample_id;
};
struct perf_context_switch_event {
/*
* type: PERF_RECORD_SWITCH (14)
* misc: PERF_RECORD_MISC_SWITCH_OUT (0x2000)
* size: 24
*/
struct sample_id sample_id;
};
struct uftrace_ctxsw_event {
bool out;
bool preempt;
};
struct uftrace_task_event {
int pid;
int ppid;
};
struct uftrace_comm_event {
int pid;
bool exec;
char comm[COMM_LEN];
};
#ifdef HAVE_PERF_CLOCKID
int setup_perf_record(struct uftrace_perf_writer *perf, int nr_cpu, int pid, const char *dirname,
int use_ctxsw);
void finish_perf_record(struct uftrace_perf_writer *perf);
void record_perf_data(struct uftrace_perf_writer *perf, int cpu, int sock);
#else /* !HAVE_PERF_CLOCKID */
static inline int setup_perf_record(struct uftrace_perf_writer *perf, int nr_cpu, int pid,
const char *dirname, int use_ctxsw)
{
return -1;
}
static inline void finish_perf_record(struct uftrace_perf_writer *perf)
{
}
static inline void record_perf_data(struct uftrace_perf_writer *perf, int cpu, int sock)
{
}
#endif /* HAVE_PERF_CLOCKID */
#ifndef PERF_RECORD_MISC_COMM_EXEC
#define PERF_RECORD_MISC_COMM_EXEC (1 << 13)
#endif
#ifdef HAVE_PERF_CTXSW
#define PERF_CTXSW_AVAILABLE 1
#else /* !HAVE_PERF_CTXSW */
#define PERF_CTXSW_AVAILABLE 0
#define PERF_RECORD_SWITCH 14
#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13)
#endif /* HAVE_PERF_CTXSW */
#define PERF_RECORD_MISC_SWITCH_OUT_PREEMPT (1 << 14)
struct uftrace_perf_reader {
FILE *fp;
bool valid;
bool done;
int type;
int tid;
uint64_t time;
union {
struct uftrace_ctxsw_event ctxsw;
struct uftrace_task_event task;
struct uftrace_comm_event comm;
} u;
};
struct uftrace_data;
struct uftrace_record;
int setup_perf_data(struct uftrace_data *handle);
void finish_perf_data(struct uftrace_data *handle);
int read_perf_data(struct uftrace_data *handle);
struct uftrace_record *get_perf_record(struct uftrace_data *handle,
struct uftrace_perf_reader *perf);
void update_perf_task_comm(struct uftrace_data *handle);
void process_perf_event(struct uftrace_data *handle);
#endif /* UFTRACE_PERF_H */
|