7 static int process_event_stub(event_t
*event __used
,
8 struct perf_session
*session __used
)
10 dump_printf(": unhandled!\n");
14 static void perf_event_ops__fill_defaults(struct perf_event_ops
*handler
)
16 if (!handler
->process_sample_event
)
17 handler
->process_sample_event
= process_event_stub
;
18 if (!handler
->process_mmap_event
)
19 handler
->process_mmap_event
= process_event_stub
;
20 if (!handler
->process_comm_event
)
21 handler
->process_comm_event
= process_event_stub
;
22 if (!handler
->process_fork_event
)
23 handler
->process_fork_event
= process_event_stub
;
24 if (!handler
->process_exit_event
)
25 handler
->process_exit_event
= process_event_stub
;
26 if (!handler
->process_lost_event
)
27 handler
->process_lost_event
= process_event_stub
;
28 if (!handler
->process_read_event
)
29 handler
->process_read_event
= process_event_stub
;
30 if (!handler
->process_throttle_event
)
31 handler
->process_throttle_event
= process_event_stub
;
32 if (!handler
->process_unthrottle_event
)
33 handler
->process_unthrottle_event
= process_event_stub
;
36 static const char *event__name
[] = {
38 [PERF_RECORD_MMAP
] = "MMAP",
39 [PERF_RECORD_LOST
] = "LOST",
40 [PERF_RECORD_COMM
] = "COMM",
41 [PERF_RECORD_EXIT
] = "EXIT",
42 [PERF_RECORD_THROTTLE
] = "THROTTLE",
43 [PERF_RECORD_UNTHROTTLE
] = "UNTHROTTLE",
44 [PERF_RECORD_FORK
] = "FORK",
45 [PERF_RECORD_READ
] = "READ",
46 [PERF_RECORD_SAMPLE
] = "SAMPLE",
49 unsigned long event__total
[PERF_RECORD_MAX
];
51 void event__print_totals(void)
54 for (i
= 0; i
< PERF_RECORD_MAX
; ++i
)
55 pr_info("%10s events: %10ld\n",
56 event__name
[i
], event__total
[i
]);
59 static int process_event(event_t
*event
, struct perf_session
*session
,
60 struct perf_event_ops
*ops
,
61 unsigned long offset
, unsigned long head
)
65 if (event
->header
.type
< PERF_RECORD_MAX
) {
66 dump_printf("%p [%p]: PERF_RECORD_%s",
67 (void *)(offset
+ head
),
68 (void *)(long)(event
->header
.size
),
69 event__name
[event
->header
.type
]);
71 ++event__total
[event
->header
.type
];
74 switch (event
->header
.type
) {
75 case PERF_RECORD_SAMPLE
:
76 return ops
->process_sample_event(event
, session
);
77 case PERF_RECORD_MMAP
:
78 return ops
->process_mmap_event(event
, session
);
79 case PERF_RECORD_COMM
:
80 return ops
->process_comm_event(event
, session
);
81 case PERF_RECORD_FORK
:
82 return ops
->process_fork_event(event
, session
);
83 case PERF_RECORD_EXIT
:
84 return ops
->process_exit_event(event
, session
);
85 case PERF_RECORD_LOST
:
86 return ops
->process_lost_event(event
, session
);
87 case PERF_RECORD_READ
:
88 return ops
->process_read_event(event
, session
);
89 case PERF_RECORD_THROTTLE
:
90 return ops
->process_throttle_event(event
, session
);
91 case PERF_RECORD_UNTHROTTLE
:
92 return ops
->process_unthrottle_event(event
, session
);
99 int perf_header__read_build_ids(int input
, u64 offset
, u64 size
)
101 struct build_id_event bev
;
102 char filename
[PATH_MAX
];
103 u64 limit
= offset
+ size
;
106 while (offset
< limit
) {
110 if (read(input
, &bev
, sizeof(bev
)) != sizeof(bev
))
113 len
= bev
.header
.size
- sizeof(bev
);
114 if (read(input
, filename
, len
) != len
)
117 dso
= dsos__findnew(filename
);
119 dso__set_build_id(dso
, &bev
.build_id
);
121 offset
+= bev
.header
.size
;
128 static struct thread
*perf_session__register_idle_thread(struct perf_session
*self
)
130 struct thread
*thread
= perf_session__findnew(self
, 0);
132 if (!thread
|| thread__set_comm(thread
, "swapper")) {
133 pr_err("problem inserting idle task.\n");
140 int perf_session__process_events(struct perf_session
*self
,
141 struct perf_event_ops
*ops
)
144 unsigned long head
, shift
;
145 unsigned long offset
= 0;
151 if (perf_session__register_idle_thread(self
) == NULL
)
154 perf_event_ops__fill_defaults(ops
);
156 page_size
= getpagesize();
158 head
= self
->header
.data_offset
;
159 self
->sample_type
= perf_header__sample_type(&self
->header
);
162 if (ops
->sample_type_check
&& ops
->sample_type_check(self
) < 0)
165 if (!ops
->full_paths
) {
168 if (getcwd(bf
, sizeof(bf
)) == NULL
) {
171 pr_err("failed to get the current directory\n");
174 self
->cwd
= strdup(bf
);
175 if (self
->cwd
== NULL
) {
179 self
->cwdlen
= strlen(self
->cwd
);
182 shift
= page_size
* (head
/ page_size
);
187 buf
= mmap(NULL
, page_size
* self
->mmap_window
, PROT_READ
,
188 MAP_SHARED
, self
->fd
, offset
);
189 if (buf
== MAP_FAILED
) {
190 pr_err("failed to mmap file\n");
196 event
= (event_t
*)(buf
+ head
);
198 size
= event
->header
.size
;
202 if (head
+ event
->header
.size
>= page_size
* self
->mmap_window
) {
205 shift
= page_size
* (head
/ page_size
);
207 munmap_ret
= munmap(buf
, page_size
* self
->mmap_window
);
208 assert(munmap_ret
== 0);
215 size
= event
->header
.size
;
217 dump_printf("\n%p [%p]: event: %d\n",
218 (void *)(offset
+ head
),
219 (void *)(long)event
->header
.size
,
222 if (!size
|| process_event(event
, self
, ops
, offset
, head
) < 0) {
224 dump_printf("%p [%p]: skipping unknown header type: %d\n",
225 (void *)(offset
+ head
),
226 (void *)(long)(event
->header
.size
),
230 * assume we lost track of the stream, check alignment, and
231 * increment a single u64 in the hope to catch on again 'soon'.
234 if (unlikely(head
& 7))
242 if (offset
+ head
>= self
->header
.data_offset
+ self
->header
.data_size
)
245 if (offset
+ head
< self
->size
)