Skip to content
Snippets Groups Projects
parse-events.c 29.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • 	if (debugfs_valid_mountpoint(tracing_events_path))
    
    	sys_dir = opendir(tracing_events_path);
    
    		return;
    
    
    	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
    
    		if (subsys_glob != NULL && 
    		    !strglobmatch(sys_dirent.d_name, subsys_glob))
    			continue;
    
    		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
    
    			 sys_dirent.d_name);
    		evt_dir = opendir(dir_path);
    		if (!evt_dir)
    
    		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
    
    			if (event_glob != NULL && 
    			    !strglobmatch(evt_dirent.d_name, event_glob))
    				continue;
    
    
    			if (name_only) {
    				printf("%s:%s ", sys_dirent.d_name, evt_dirent.d_name);
    				continue;
    			}
    
    
    			snprintf(evt_path, MAXPATHLEN, "%s:%s",
    				 sys_dirent.d_name, evt_dirent.d_name);
    
    			printf("  %-50s [%s]\n", evt_path,
    
    				event_type_descriptors[PERF_TYPE_TRACEPOINT]);
    
    /*
     * Check whether event is in <debugfs_mount_point>/tracing/events
     */
    
    int is_valid_tracepoint(const char *event_string)
    {
    	DIR *sys_dir, *evt_dir;
    	struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent;
    	char evt_path[MAXPATHLEN];
    	char dir_path[MAXPATHLEN];
    
    
    	if (debugfs_valid_mountpoint(tracing_events_path))
    
    	sys_dir = opendir(tracing_events_path);
    
    	if (!sys_dir)
    		return 0;
    
    	for_each_subsystem(sys_dir, sys_dirent, sys_next) {
    
    
    		snprintf(dir_path, MAXPATHLEN, "%s/%s", tracing_events_path,
    
    			 sys_dirent.d_name);
    		evt_dir = opendir(dir_path);
    		if (!evt_dir)
    			continue;
    
    		for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) {
    			snprintf(evt_path, MAXPATHLEN, "%s:%s",
    				 sys_dirent.d_name, evt_dirent.d_name);
    			if (!strcmp(evt_path, event_string)) {
    				closedir(evt_dir);
    				closedir(sys_dir);
    				return 1;
    			}
    		}
    		closedir(evt_dir);
    	}
    	closedir(sys_dir);
    	return 0;
    }
    
    
    static bool is_event_supported(u8 type, unsigned config)
    {
    	bool ret = true;
    	struct perf_evsel *evsel;
    	struct perf_event_attr attr = {
    		.type = type,
    		.config = config,
    		.disabled = 1,
    		.exclude_kernel = 1,
    	};
    	struct {
    		struct thread_map map;
    		int threads[1];
    	} tmap = {
    		.map.nr	 = 1,
    		.threads = { 0 },
    	};
    
    	evsel = perf_evsel__new(&attr, 0);
    	if (evsel) {
    		ret = perf_evsel__open(evsel, NULL, &tmap.map) >= 0;
    		perf_evsel__delete(evsel);
    	}
    
    	return ret;
    }
    
    
    static void __print_events_type(u8 type, struct event_symbol *syms,
    				unsigned max)
    
    	for (i = 0; i < max ; i++, syms++) {
    
    		if (!is_event_supported(type, i))
    			continue;
    
    
    		if (strlen(syms->alias))
    			snprintf(name, sizeof(name),  "%s OR %s",
    				 syms->symbol, syms->alias);
    		else
    			snprintf(name, sizeof(name), "%s", syms->symbol);
    
    
    		printf("  %-50s [%s]\n", name, event_type_descriptors[type]);
    
    void print_events_type(u8 type)
    {
    	if (type == PERF_TYPE_SOFTWARE)
    		__print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
    	else
    		__print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
    }
    
    
    int print_hwcache_events(const char *event_glob, bool name_only)
    
    {
    	unsigned int type, op, i, printed = 0;
    
    
    	for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
    		for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
    			/* skip invalid cache type */
    
    			if (!perf_evsel__is_cache_op_valid(type, op))
    
    				continue;
    
    			for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
    
    				__perf_evsel__hw_cache_type_op_res_name(type, op, i,
    									name, sizeof(name));
    
    				if (event_glob != NULL && !strglobmatch(name, event_glob))
    
    				if (!is_event_supported(PERF_TYPE_HW_CACHE,
    							type | (op << 8) | (i << 16)))
    					continue;
    
    
    				if (name_only)
    					printf("%s ", name);
    				else
    					printf("  %-50s [%s]\n", name,
    					       event_type_descriptors[PERF_TYPE_HW_CACHE]);
    
    	if (printed)
    		printf("\n");
    
    static void print_symbol_events(const char *event_glob, unsigned type,
    
    				struct event_symbol *syms, unsigned max,
    				bool name_only)
    
    	unsigned i, printed = 0;
    
    	char name[MAX_NAME_LEN];
    
    	for (i = 0; i < max; i++, syms++) {
    
    
    		if (event_glob != NULL && 
    		    !(strglobmatch(syms->symbol, event_glob) ||
    		      (syms->alias && strglobmatch(syms->alias, event_glob))))
    			continue;
    
    		if (!is_event_supported(type, i))
    			continue;
    
    
    		if (name_only) {
    			printf("%s ", syms->symbol);
    			continue;
    		}
    
    
    			snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
    
    			strncpy(name, syms->symbol, MAX_NAME_LEN);
    
    		printf("  %-50s [%s]\n", name, event_type_descriptors[type]);
    
    		printed++;
    
    }
    
    /*
     * Print the help text for the event symbols:
     */
    
    void print_events(const char *event_glob, bool name_only)
    
    	if (!name_only) {
    		printf("\n");
    		printf("List of pre-defined events (to be used in -e):\n");
    	}
    
    
    	print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
    
    			    event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
    
    
    	print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
    
    			    event_symbols_sw, PERF_COUNT_SW_MAX, name_only);
    
    	print_hwcache_events(event_glob, name_only);
    
    	print_pmu_events(event_glob, name_only);
    
    
    	if (event_glob != NULL)
    		return;
    
    	if (!name_only) {
    		printf("  %-50s [%s]\n",
    		       "rNNN",
    		       event_type_descriptors[PERF_TYPE_RAW]);
    		printf("  %-50s [%s]\n",
    		       "cpu/t1=v1[,t2=v2,t3 ...]/modifier",
    		       event_type_descriptors[PERF_TYPE_RAW]);
    
    		printf("   (see 'man perf-list' on how to encode it)\n");
    
    		printf("\n");
    
    		printf("  %-50s [%s]\n",
    		       "mem:<addr>[:access]",
    
    			event_type_descriptors[PERF_TYPE_BREAKPOINT]);
    
    	print_tracepoint_events(NULL, NULL, name_only);
    
    int parse_events__is_hardcoded_term(struct parse_events_term *term)
    
    	return term->type_term != PARSE_EVENTS__TERM_TYPE_USER;
    
    static int new_term(struct parse_events_term **_term, int type_val,
    
    		    int type_term, char *config,
    
    	struct parse_events_term *term;
    
    
    	term = zalloc(sizeof(*term));
    	if (!term)
    		return -ENOMEM;
    
    	INIT_LIST_HEAD(&term->list);
    
    	term->type_val  = type_val;
    	term->type_term = type_term;
    
    	case PARSE_EVENTS__TERM_TYPE_NUM:
    		term->val.num = num;
    		break;
    	case PARSE_EVENTS__TERM_TYPE_STR:
    		term->val.str = str;
    		break;
    	default:
    
    int parse_events_term__num(struct parse_events_term **term,
    
    			   int type_term, char *config, u64 num)
    
    {
    	return new_term(term, PARSE_EVENTS__TERM_TYPE_NUM, type_term,
    			config, NULL, num);
    }
    
    
    int parse_events_term__str(struct parse_events_term **term,
    
    			   int type_term, char *config, char *str)
    {
    	return new_term(term, PARSE_EVENTS__TERM_TYPE_STR, type_term,
    			config, str, 0);
    }
    
    
    int parse_events_term__sym_hw(struct parse_events_term **term,
    
    			      char *config, unsigned idx)
    {
    	struct event_symbol *sym;
    
    	BUG_ON(idx >= PERF_COUNT_HW_MAX);
    	sym = &event_symbols_hw[idx];
    
    	if (config)
    		return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
    				PARSE_EVENTS__TERM_TYPE_USER, config,
    				(char *) sym->symbol, 0);
    	else
    		return new_term(term, PARSE_EVENTS__TERM_TYPE_STR,
    				PARSE_EVENTS__TERM_TYPE_USER,
    				(char *) "event", (char *) sym->symbol, 0);
    }
    
    
    int parse_events_term__clone(struct parse_events_term **new,
    			     struct parse_events_term *term)
    
    {
    	return new_term(new, term->type_val, term->type_term, term->config,
    			term->val.str, term->val.num);
    }
    
    
    void parse_events__free_terms(struct list_head *terms)
    {
    
    	struct parse_events_term *term, *h;
    
    
    	list_for_each_entry_safe(term, h, terms, list)
    		free(term);
    }