6 #include <linux/bitops.h>
7 #include <linux/hash.h>
9 struct perf_evlist
*perf_evlist__new(void)
11 struct perf_evlist
*evlist
= zalloc(sizeof(*evlist
));
16 for (i
= 0; i
< PERF_EVLIST__HLIST_SIZE
; ++i
)
17 INIT_HLIST_HEAD(&evlist
->heads
[i
]);
18 INIT_LIST_HEAD(&evlist
->entries
);
24 static void perf_evlist__purge(struct perf_evlist
*evlist
)
26 struct perf_evsel
*pos
, *n
;
28 list_for_each_entry_safe(pos
, n
, &evlist
->entries
, node
) {
29 list_del_init(&pos
->node
);
30 perf_evsel__delete(pos
);
33 evlist
->nr_entries
= 0;
36 void perf_evlist__delete(struct perf_evlist
*evlist
)
38 perf_evlist__purge(evlist
);
44 void perf_evlist__add(struct perf_evlist
*evlist
, struct perf_evsel
*entry
)
46 list_add_tail(&entry
->node
, &evlist
->entries
);
50 int perf_evlist__add_default(struct perf_evlist
*evlist
)
52 struct perf_event_attr attr
= {
53 .type
= PERF_TYPE_HARDWARE
,
54 .config
= PERF_COUNT_HW_CPU_CYCLES
,
56 struct perf_evsel
*evsel
= perf_evsel__new(&attr
, 0);
61 perf_evlist__add(evlist
, evsel
);
65 int perf_evlist__alloc_pollfd(struct perf_evlist
*evlist
, int ncpus
, int nthreads
)
67 int nfds
= ncpus
* nthreads
* evlist
->nr_entries
;
68 evlist
->pollfd
= malloc(sizeof(struct pollfd
) * nfds
);
69 return evlist
->pollfd
!= NULL
? 0 : -ENOMEM
;
72 void perf_evlist__add_pollfd(struct perf_evlist
*evlist
, int fd
)
74 fcntl(fd
, F_SETFL
, O_NONBLOCK
);
75 evlist
->pollfd
[evlist
->nr_fds
].fd
= fd
;
76 evlist
->pollfd
[evlist
->nr_fds
].events
= POLLIN
;
80 struct perf_evsel
*perf_evlist__id2evsel(struct perf_evlist
*evlist
, u64 id
)
82 struct hlist_head
*head
;
83 struct hlist_node
*pos
;
84 struct perf_sample_id
*sid
;
87 if (evlist
->nr_entries
== 1)
88 return list_entry(evlist
->entries
.next
, struct perf_evsel
, node
);
90 hash
= hash_64(id
, PERF_EVLIST__HLIST_BITS
);
91 head
= &evlist
->heads
[hash
];
93 hlist_for_each_entry(sid
, pos
, head
, node
)
99 event_t
*perf_evlist__read_on_cpu(struct perf_evlist
*evlist
, int cpu
)
101 /* XXX Move this to perf.c, making it generally available */
102 unsigned int page_size
= sysconf(_SC_PAGE_SIZE
);
103 struct perf_mmap
*md
= &evlist
->mmap
[cpu
];
104 unsigned int head
= perf_mmap__read_head(md
);
105 unsigned int old
= md
->prev
;
106 unsigned char *data
= md
->base
+ page_size
;
107 event_t
*event
= NULL
;
111 * If we're further behind than half the buffer, there's a chance
112 * the writer will bite our tail and mess up the samples under us.
114 * If we somehow ended up ahead of the head, we got messed up.
116 * In either case, truncate and restart at head.
119 if (diff
> md
->mask
/ 2 || diff
< 0) {
120 fprintf(stderr
, "WARNING: failed to keep up with mmap data.\n");
123 * head points to a known good entry, start there.
131 event
= (event_t
*)&data
[old
& md
->mask
];
132 size
= event
->header
.size
;
135 * Event straddles the mmap boundary -- header should always
136 * be inside due to u64 alignment of output.
138 if ((old
& md
->mask
) + size
!= ((old
+ size
) & md
->mask
)) {
139 unsigned int offset
= old
;
140 unsigned int len
= min(sizeof(*event
), size
), cpy
;
141 void *dst
= &evlist
->event_copy
;
144 cpy
= min(md
->mask
+ 1 - (offset
& md
->mask
), len
);
145 memcpy(dst
, &data
[offset
& md
->mask
], cpy
);
151 event
= &evlist
->event_copy
;