62 #include <linux/perf_event.h> 63 #include <linux/version.h> 84 #define MMAP_OFFSET_0 0 86 #define PERF_DATA_PAGE_EXP 1 // use 2^PERF_DATA_PAGE_EXP pages 87 #define PERF_DATA_PAGES (1 << PERF_DATA_PAGE_EXP) 89 #define PERF_MMAP_SIZE(pagesz) ((pagesz) * (PERF_DATA_PAGES + 1)) 90 #define PERF_TAIL_MASK(pagesz) (((pagesz) * PERF_DATA_PAGES) - 1) 121 u64 head = hdr->data_head;
133 return (head - hdr->data_tail);
157 if (current_perf_mmap ==
NULL)
166 size_t bytes_available = data_head - current_perf_mmap->data_tail;
168 if (bytes_wanted > bytes_available)
return -1;
171 unsigned long tail =
BUFFER_OFFSET(current_perf_mmap->data_tail);
176 size_t right = bytes_at_right < bytes_wanted ? bytes_at_right : bytes_wanted;
179 memcpy(buf, data + tail, right);
182 if (bytes_wanted > right) {
183 size_t left = bytes_wanted - right;
184 memcpy(buf + right, data, left);
188 current_perf_mmap->data_tail += bytes_wanted;
230 u64 value, id, nr, time_enabled, time_running;
232 if (read_format & PERF_FORMAT_GROUP) {
238 if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
241 if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
245 if (read_format & PERF_FORMAT_GROUP) {
246 for(
int i=0;i<nr;i++) {
249 if (read_format & PERF_FORMAT_ID) {
255 if (read_format & PERF_FORMAT_ID) {
275 if (num_records > 0) {
283 if (
perf_read( current_perf_mmap, mmap_data->
ips, num_records *
sizeof(
u64)) != 0) {
286 TMSG(LINUX_PERF,
"unable to read all %d frames", mmap_data->
nr);
290 TMSG(LINUX_PERF,
"unable to read the number of frames" );
292 return mmap_data->
nr;
302 struct perf_event_mmap_page *hdr = current_perf_mmap;
306 if ((hdr->data_tail + sz) > data_head)
307 sz = data_head - hdr->data_tail;
309 hdr->data_tail += sz;
320 struct perf_event_attr *attr,
324 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) 325 if (sample_type & PERF_SAMPLE_IDENTIFIER) {
330 if (sample_type & PERF_SAMPLE_IP) {
335 if (sample_type & PERF_SAMPLE_TID) {
340 if (sample_type & PERF_SAMPLE_TIME) {
344 if (sample_type & PERF_SAMPLE_ADDR) {
349 if (sample_type & PERF_SAMPLE_ID) {
353 if (sample_type & PERF_SAMPLE_STREAM_ID) {
357 if (sample_type & PERF_SAMPLE_CPU) {
362 if (sample_type & PERF_SAMPLE_PERIOD) {
366 if (sample_type & PERF_SAMPLE_READ) {
372 if (sample_type & PERF_SAMPLE_CALLCHAIN) {
377 if (sample_type & PERF_SAMPLE_RAW) {
379 mmap_info->
data = alloca(
sizeof(
char) * mmap_info->
size );
383 if (sample_type & PERF_SAMPLE_BRANCH_STACK) {
386 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) 387 if (sample_type & PERF_SAMPLE_REGS_USER) {
390 if (sample_type & PERF_SAMPLE_STACK_USER) {
394 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) 395 if (sample_type & PERF_SAMPLE_WEIGHT) {
398 if (sample_type & PERF_SAMPLE_DATA_SRC) {
403 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) 405 if (sample_type & PERF_SAMPLE_TRANSACTION) {
409 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) 411 if (sample_type & PERF_SAMPLE_REGS_INTR) {
436 if (read_successfully != 0) {
443 if (hdr.type == PERF_RECORD_SAMPLE) {
447 int sample_type = attr->sample_type;
448 parse_buffer(sample_type, current_perf_mmap, attr, mmap_info);
450 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,3,0) 451 }
else if (hdr.type == PERF_RECORD_SWITCH) {
456 struct { uint32_t
cpu, reserved; }
cpu;
458 type = attr->sample_type;
460 if (type & PERF_SAMPLE_TID) {
464 if (type & PERF_SAMPLE_TIME) {
467 if (type & PERF_SAMPLE_CPU) {
470 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,0) 471 }
else if (hdr.type == PERF_RECORD_LOST_SAMPLES) {
474 TMSG(LINUX_PERF,
"[%d] lost samples %d",
475 current->fd, lost_samples);
486 TMSG(LINUX_PERF,
"[%d] skip header %d %d : %d bytes",
488 hdr.type, hdr.misc, hdr.size);
507 if (map_result == MAP_FAILED) {
508 EMSG(
"Linux perf mmap failed: %s", strerror(errno));
516 mmap->compat_version = 0;
539 pagesize = sysconf(_SC_PAGESIZE);
static int perf_read_u64(pe_mmap_t *current_perf_mmap, u64 *val)
int read_perf_buffer(pe_mmap_t *current_perf_mmap, struct perf_event_attr *attr, perf_mmap_data_t *mmap_info)
#define MAX_CALLCHAIN_FRAMES
void perf_unmmap(pe_mmap_t *mmap)
static int perf_sample_callchain(pe_mmap_t *current_perf_mmap, perf_mmap_data_t *mmap_data)
#define PERF_MMAP_SIZE(pagesz)
pe_mmap_t * set_mmap(int perf_fd)
static int perf_read_u32(pe_mmap_t *current_perf_mmap, u32 *val)
#define BUFFER_FRONT(current_perf_mmap)
static int has_more_perf_data(pe_mmap_t *hdr)
struct perf_event_mmap_page pe_mmap_t
static int perf_read(pe_mmap_t *current_perf_mmap, void *buf, size_t bytes_wanted)
static int parse_buffer(int sample_type, pe_mmap_t *current_perf_mmap, struct perf_event_attr *attr, perf_mmap_data_t *mmap_info)
static int perf_read_header(pe_mmap_t *current_perf_mmap, pe_header_t *hdr)
#define BUFFER_OFFSET(tail)
#define PERF_TAIL_MASK(pagesz)
static u64 perf_mmap_read_head(pe_mmap_t *hdr)
static int num_of_more_perf_data(pe_mmap_t *hdr)
struct perf_event_header pe_header_t
u64 ips[MAX_CALLCHAIN_FRAMES]
static void handle_struct_read_format(pe_mmap_t *perf_mmap, int read_format)
static void skip_perf_data(pe_mmap_t *current_perf_mmap, size_t sz) __attribute__((unused))