65 #include <sys/syscall.h> 67 #include <sys/ioctl.h> 73 #include <linux/perf_event.h> 74 #include <linux/version.h> 135 #define LINUX_PERF_DEBUG 0 145 #define DEFAULT_THRESHOLD HPCRUN_DEFAULT_SAMPLE_RATE 147 #ifndef sigev_notify_thread_id 148 #define sigev_notify_thread_id _sigev_un._tid 156 #define PERF_SIGNAL (SIGRTMIN+4) 158 #define PERF_EVENT_AVAILABLE_UNKNOWN 0 159 #define PERF_EVENT_AVAILABLE_NO 1 160 #define PERF_EVENT_AVAILABLE_YES 2 162 #define PERF_MULTIPLEX_RANGE 1.2 164 #define FILE_BUFFER_SIZE (1024*1024) 166 #define DEFAULT_COMPRESSION 5 168 #define PERIOD_THRESHOLD 1 169 #define PERIOD_FREQUENCY 2 170 #define PERIOD_DEFAULT 0 172 #define PERF_FD_FINALIZED (-2) 196 static const struct timespec
nowait = {0, 0};
240 for(i=0; i<nevents; i++) {
241 int fd = event_thread[i].
fd;
245 ret = ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);
248 EMSG(
"Can't enable event with fd: %d: %s", fd, strerror(errno));
261 for(i=0; i<nevents; i++) {
262 int fd = event_thread[i].
fd;
266 ret = ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
268 EMSG(
"Can't disable event with fd: %d: %s", fd, strerror(errno));
291 FILE *infile = fopen(source,
"r");
295 char dest[PATH_MAX], kernel_name[PATH_MAX];
296 char dest_directory[PATH_MAX];
299 snprintf(dest_directory, PATH_MAX,
"%s/%s", output_directory,
308 snprintf(dest, PATH_MAX,
"%s/%s", dest_directory, kernel_name);
311 struct stat st = {0};
312 if (stat(dest, &st) >= 0) {
316 mkdir(dest_directory, S_IRWXU | S_IRGRP | S_IXGRP);
318 FILE *outfile = fopen(dest,
"wx");
328 TMSG(LINUX_PERF,
"copy %s into %s", source, dest);
346 TMSG(LINUX_PERF,
"copy_kallsyms result: %d", ret);
353 sigemptyset(&sig_mask);
358 struct sigaction perf_sigaction;
359 sigemptyset(&perf_sigaction.sa_mask);
360 sigaddset(&perf_sigaction.sa_mask, SIGRTMIN+8);
361 perf_sigaction.sa_flags = 0;
364 monitor_real_pthread_sigmask(SIG_UNBLOCK, &sig_mask,
NULL);
383 TMSG(LINUX_PERF,
"event fd: %d, skid: %d, code: %d, type: %d, period: %d, freq: %d",
384 et->
fd, event->
attr.precise_ip, event->
attr.config,
385 event->
attr.type, event->
attr.sample_freq, event->
attr.freq);
389 EMSG(
"linux perf event open failed" 391 " config: %d, type: %d, sample_freq: %d," 392 " freq: %d, error: %s",
393 et->
fd, event->
attr.precise_ip,
394 event->
attr.config, event->
attr.type, event->
attr.sample_freq,
395 event->
attr.freq, strerror(errno));
403 int flag = fcntl(et->
fd, F_GETFL, 0);
404 int ret = fcntl(et->
fd, F_SETFL, flag | O_ASYNC );
406 EMSG(
"can't set notification for event fd: %d: %s",
407 et->
fd, strerror(errno));
414 EMSG(
"can't set signal for event fd: %d: %s",
415 et->
fd, strerror(errno));
419 struct f_owner_ex owner;
420 owner.type = F_OWNER_TID;
421 owner.pid = syscall(SYS_gettid);
422 ret = fcntl(et->
fd, F_SETOWN_EX, &owner);
424 EMSG(
"can't set thread owner for event fd: %d: %s",
425 et->
fd, strerror(errno));
428 ret = ioctl(et->
fd, PERF_EVENT_IOC_RESET, 0);
430 EMSG(
"can't reset event fd: %d: %s",
431 et->
fd, strerror(errno));
446 sigset_t perf_sigset;
447 sigemptyset(&perf_sigset);
449 monitor_real_pthread_sigmask(SIG_BLOCK, &perf_sigset,
NULL);
451 for(
int i=0; i<nevents; i++) {
458 if (event_thread[i].fd >= 0) {
459 close(event_thread[i].fd);
463 if (event_thread[i].mmap) {
465 event_thread[i].
mmap = 0;
473 if (sigtimedwait(&perf_sigset, &siginfo, &
nowait) < 0)
break;
485 for(
int i=0; i<nevents; i++) {
486 if (event_thread[i].fd == fd)
510 uint64_t metric_inc = 1;
511 if (freq==1 && mmap_data->
period > 0)
512 metric_inc = mmap_data->
period;
518 u64 time_enabled = current->
mmap->time_enabled;
519 u64 time_running = current->
mmap->time_running;
525 double scale_f = (double) time_enabled / time_running;
537 int weight = (mmap_data->
weight < 1 ? 1 : mmap_data->
weight);
539 double counter = scale_f * metric_inc * (double) weight;
566 #if kernel_sampling_enabled 589 size_t len = strlen(original_event);
594 is_precise = (original_event[len-2] ==
':') &&
595 (original_event[len-1] ==
'p' || original_event[len-1] ==
'p');
614 TMSG(LINUX_PERF,
"%d: init", self->sel_idx);
630 TMSG(LINUX_PERF,
"%d: init ok", self->sel_idx);
641 TMSG(LINUX_PERF,
"%d: thread init", self->sel_idx);
643 TMSG(LINUX_PERF,
"%d: thread init ok", self->sel_idx);
653 TMSG(LINUX_PERF,
"%d: thread init action", self->sel_idx);
655 TMSG(LINUX_PERF,
"%d: thread init action ok", self->sel_idx);
665 TMSG(LINUX_PERF,
"%d: start", self->sel_idx);
673 if (my_state ==
START) {
674 TMSG(LINUX_PERF,
"%d: *note* LINUX_PERF start called when already in state start",
679 int nevents = (
self->evl).nevents;
688 TMSG(LINUX_PERF,
"%d: start ok", self->sel_idx);
697 TMSG(LINUX_PERF,
"%d: unregister thread", self->sel_idx);
702 int nevents =
self->evl.nevents;
708 TMSG(LINUX_PERF,
"%d: unregister thread ok", self->sel_idx);
718 TMSG(LINUX_PERF,
"%d: stop", self->sel_idx);
721 if (my_state ==
STOP) {
722 TMSG(LINUX_PERF,
"%d: *note* perf stop called when already in state stop",
727 if (my_state !=
START) {
728 TMSG(LINUX_PERF,
"%d: *warning* perf stop called when not in state start",
734 int nevents =
self->evl.nevents;
741 TMSG(LINUX_PERF,
"%d: stop ok", self->sel_idx);
750 TMSG(LINUX_PERF,
"shutdown");
755 int nevents =
self->evl.nevents;
761 TMSG(LINUX_PERF,
"shutdown ok");
772 TMSG(LINUX_PERF,
"supports event %s", ev_str);
774 if (self->state ==
UNINIT){
794 if (precise_ip_pos > 0) {
795 ev_tmp[precise_ip_pos] =
'\0';
811 TMSG(LINUX_PERF,
"process event list");
829 TMSG(LINUX_PERF,
"checking event spec = %s",event);
846 if (precise_ip_pos > 0) {
847 name[precise_ip_pos] =
'\0';
851 struct perf_event_attr *event_attr = &
event->attr;
867 if (precise_ip_pos>0) {
876 if (strcasestr(name,
"cycles") !=
NULL) {
883 char *name_dup = strdup(name);
897 if (metric_desc ==
NULL) {
898 EMSG(
"error: unable to create metric #%d: %s", index, name);
903 int index =
METHOD_CALL(
self, store_event_and_info,
904 event_attr->config, threshold, metric, event);;
906 EMSG(
"error: cannot create event %s (%d)", name, event_attr->config);
911 int nevents =
self->evl.nevents;
922 TMSG(LINUX_PERF,
"gen_event_set");
924 int nevents =
self->evl.nevents;
939 memset(aux_info, 0, mem_metrics_size);
944 td->
ss_info[
self->sel_idx].
ptr = event_thread;
949 for (
int i=0; i<nevents; i++)
955 EEMSG(
"Failed to initialize event %d (%s): %s", i, mdesc->
name, strerror(errno));
960 TMSG(LINUX_PERF,
"gen_event_set OK");
991 size_t t =
read(fd, buffer, 1024);
1004 #define ss_name linux_perf 1005 #define ss_cls SS_HARDWARE 1006 #define ss_sort_order 60 1046 int nevents =
self->evl.nevents;
1061 if (siginfo->si_code < 0) {
1062 TMSG(LINUX_PERF,
"signal si_code %d < 0 indicates not from kernel",
1081 int fd = siginfo->si_fd;
1089 if (siginfo->si_code != POLL_HUP) {
1090 TMSG(LINUX_PERF,
"signal si_code %d (fd: %d) not generated by signal %d",
1093 restart_perf_event(fd);
1109 int event_index =
get_fd_index(nevents, fd, event_thread);
1112 if (current ==
NULL) {
1114 TMSG(LINUX_PERF,
"signal si_code %d with fd %d: unknown perf event",
1115 siginfo->si_code, fd);
1129 struct perf_event_attr *attr = &event_info->
attr;
1131 int metric = self->evl.events[event_index].metric_id;
1146 if (mmap_data.header_type == PERF_RECORD_SAMPLE) {
1154 arg.
data = &mmap_data;
1162 }
while (more_data);
struct event_info_s * current
static void perf_thread_fini(int nevents, event_thread_t *event_thread)
int read_perf_buffer(pe_mmap_t *current_perf_mmap, struct perf_event_attr *attr, perf_mmap_data_t *mmap_info)
metric_aux_info_t * perf_event_info
static const struct timespec nowait
static struct perf_mem_metric metric
static void perf_stop_all(int nevents, event_thread_t *event_thread)
void MONITOR_EXT_WRAP_NAME() free(void *ptr)
struct cct_custom_update_s sample_custom_cct
int perf_skid_set_max_precise_ip(struct perf_event_attr *attr)
static void hpcrun_safe_exit(void)
struct perf_event_attr attr
cct_node_t *(* hpcrun_cct_update_after_t)(cct_node_t *path, void *data_aux)
sample_val_t hpcrun_sample_callpath(void *context, int metricId, hpcrun_metricVal_t metricIncr, int skipInner, int isSync, sampling_info_t *data)
#define HPCTOOLKIT_APPLICATION_ERRNO_RESTORE()
void perf_unmmap(pe_mmap_t *mmap)
const char * hpcrun_files_output_directory()
void blame_shift_source_register(bs_type bst)
int OSUtil_setCustomKernelName(char *buffer, size_t max_chars)
hpcrun_cct_update_after_t update_after_fn
static void perf_start_all(int nevents, event_thread_t *event_thread)
#define PERF_MULTIPLEX_RANGE
pe_mmap_t * set_mmap(int perf_fd)
static size_t exist_precise_ip_modifier(const char *original_event)
static bool perf_thread_init(event_info_t *event, event_thread_t *et)
int hpcrun_get_num_metrics()
#define PERF_FD_FINALIZED
void blame_shift_apply(int metric_id, cct_node_t *node, int metric_incr)
void hpcrun_stats_num_samples_blocked_async_inc(void)
bool perf_util_is_ksym_available()
cct_node_t * perf_util_add_kernel_callchain(cct_node_t *leaf, void *data_aux)
metric_desc_t * hpcrun_set_metric_info_and_period(int metric_id, const char *name, MetricFlags_ValFmt_t valFmt, size_t period, metric_desc_properties_t prop)
static int get_fd_index(int nevents, int fd, event_thread_t *event_thread)
long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags)
int pfmu_isSupported(const char *eventname)
int event_custom_handler(event_handler_arg_t *args)
source_state_t * ss_state
static void METHOD_FN(init)
#define metric_property_cycles
struct metric_aux_info_s metric_aux_info_t
void perf_util_get_default_threshold(struct event_threshold_s *threshold)
char * start_tok(char *lst)
int event_custom_create_event(sample_source_t *self, char *name)
core_profile_trace_data_t core_profile_trace_data
#define DEFAULT_COMPRESSION
struct perf_mmap_data_s * data
void * hpcrun_malloc(size_t size)
int perf_skid_parse_event(const char *event_string, char **event_string_without_skidmarks)
event_custom_t * event_custom_find(const char *name)
static int copy_kallsyms()
int perf_util_attr_init(const char *event_name, struct perf_event_attr *attr, bool usePeriod, u64 threshold, u64 sampletype)
#define LINUX_KERNEL_SYMBOL_FILE
hpcrun_cct_update_before_t update_before_fn
static char output_directory[PATH_MAX]
static int perf_get_pmu_support(const char *name, struct perf_event_attr *event_attr)
void event_custom_display(FILE *std)
int hpcrun_extract_ev_thresh(const char *in, int evlen, char *ev, long *th, long def)
static int hpcrun_safe_enter_async(void *pc)
int mkdir(const char *dir)
#define METHOD_CALL(obj, meth,...)
ssize_t MONITOR_EXT_WRAP_NAME() read(int fd, void *buf, size_t count)
__thread bool hpcrun_thread_suppress_sample
static int perf_was_finalized(int nevents, event_thread_t *event_thread)
static int const threshold
int hpcrun_new_metric(void)
static double record_sample(event_thread_t *current, perf_mmap_data_t *mmap_data, void *context, int metric, int freq, sample_val_t *sv)
#define HPCTOOLKIT_APPLICATION_ERRNO_SAVE()
void display_header(FILE *output, const char *title)
void * hpcrun_context_pc(void *context)
#define KERNEL_SYMBOLS_DIRECTORY
static int perf_event_handler(int sig, siginfo_t *siginfo, void *context)
void kernel_blocking_init()
enum compress_e compress_deflate(FILE *source, FILE *dest, int level)
metric_desc_t * hpcrun_id2metric(int metric_id)
thread_data_t *(* hpcrun_get_thread_data)(void)
int pfmu_getEventAttribute(const char *eventname, struct perf_event_attr *event_attr)
#define metric_property_none