diff options
Diffstat (limited to 'tools/perf/util/machine.c')
| -rw-r--r-- | tools/perf/util/machine.c | 166 | 
1 files changed, 92 insertions, 74 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 6188d2876a71..ce034c183a7e 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -40,12 +40,29 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)  			return -ENOMEM;  		snprintf(comm, sizeof(comm), "[guest/%d]", pid); -		thread__set_comm(thread, comm); +		thread__set_comm(thread, comm, 0);  	}  	return 0;  } +struct machine *machine__new_host(void) +{ +	struct machine *machine = malloc(sizeof(*machine)); + +	if (machine != NULL) { +		machine__init(machine, "", HOST_KERNEL_ID); + +		if (machine__create_kernel_maps(machine) < 0) +			goto out_delete; +	} + +	return machine; +out_delete: +	free(machine); +	return NULL; +} +  static void dsos__delete(struct list_head *dsos)  {  	struct dso *pos, *n; @@ -314,7 +331,8 @@ struct thread *machine__find_thread(struct machine *machine, pid_t tid)  	return __machine__findnew_thread(machine, 0, tid, false);  } -int machine__process_comm_event(struct machine *machine, union perf_event *event) +int machine__process_comm_event(struct machine *machine, union perf_event *event, +				struct perf_sample *sample)  {  	struct thread *thread = machine__findnew_thread(machine,  							event->comm.pid, @@ -323,7 +341,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event  	if (dump_trace)  		perf_event__fprintf_comm(event, stdout); -	if (thread == NULL || thread__set_comm(thread, event->comm.comm)) { +	if (thread == NULL || thread__set_comm(thread, event->comm.comm, sample->time)) {  		dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");  		return -1;  	} @@ -332,7 +350,7 @@ int machine__process_comm_event(struct machine *machine, union perf_event *event  }  int machine__process_lost_event(struct machine *machine __maybe_unused, -				union perf_event *event) +				union perf_event *event, struct perf_sample *sample __maybe_unused)  {  	dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",  		    event->lost.id, event->lost.lost); @@ -776,75 +794,44 @@ static int machine__set_modules_path(struct machine *machine)  	return map_groups__set_modules_path_dir(&machine->kmaps, modules_path);  } -static int machine__create_modules(struct machine *machine) +static int machine__create_module(void *arg, const char *name, u64 start)  { -	char *line = NULL; -	size_t n; -	FILE *file; +	struct machine *machine = arg;  	struct map *map; + +	map = machine__new_module(machine, start, name); +	if (map == NULL) +		return -1; + +	dso__kernel_module_get_build_id(map->dso, machine->root_dir); + +	return 0; +} + +static int machine__create_modules(struct machine *machine) +{  	const char *modules;  	char path[PATH_MAX]; -	if (machine__is_default_guest(machine)) +	if (machine__is_default_guest(machine)) {  		modules = symbol_conf.default_guest_modules; -	else { -		sprintf(path, "%s/proc/modules", machine->root_dir); +	} else { +		snprintf(path, PATH_MAX, "%s/proc/modules", machine->root_dir);  		modules = path;  	}  	if (symbol__restricted_filename(modules, "/proc/modules"))  		return -1; -	file = fopen(modules, "r"); -	if (file == NULL) +	if (modules__parse(modules, machine, machine__create_module))  		return -1; -	while (!feof(file)) { -		char name[PATH_MAX]; -		u64 start; -		char *sep; -		int line_len; - -		line_len = getline(&line, &n, file); -		if (line_len < 0) -			break; - -		if (!line) -			goto out_failure; - -		line[--line_len] = '\0'; /* \n */ - -		sep = strrchr(line, 'x'); -		if (sep == NULL) -			continue; - -		hex2u64(sep + 1, &start); - -		sep = strchr(line, ' '); -		if (sep == NULL) -			continue; - -		*sep = '\0'; - -		snprintf(name, sizeof(name), "[%s]", line); -		map = machine__new_module(machine, start, name); -		if (map == NULL) -			goto out_delete_line; -		dso__kernel_module_get_build_id(map->dso, machine->root_dir); -	} +	if (!machine__set_modules_path(machine)) +		return 0; -	free(line); -	fclose(file); +	pr_debug("Problems setting modules path maps, continuing anyway...\n"); -	if (machine__set_modules_path(machine) < 0) { -		pr_debug("Problems setting modules path maps, continuing anyway...\n"); -	}  	return 0; - -out_delete_line: -	free(line); -out_failure: -	return -1;  }  int machine__create_kernel_maps(struct machine *machine) @@ -998,7 +985,8 @@ out_problem:  }  int machine__process_mmap2_event(struct machine *machine, -				 union perf_event *event) +				 union perf_event *event, +				 struct perf_sample *sample __maybe_unused)  {  	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;  	struct thread *thread; @@ -1045,7 +1033,8 @@ out_problem:  	return 0;  } -int machine__process_mmap_event(struct machine *machine, union perf_event *event) +int machine__process_mmap_event(struct machine *machine, union perf_event *event, +				struct perf_sample *sample __maybe_unused)  {  	u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;  	struct thread *thread; @@ -1102,7 +1091,8 @@ static void machine__remove_thread(struct machine *machine, struct thread *th)  	list_add_tail(&th->node, &machine->dead_threads);  } -int machine__process_fork_event(struct machine *machine, union perf_event *event) +int machine__process_fork_event(struct machine *machine, union perf_event *event, +				struct perf_sample *sample)  {  	struct thread *thread = machine__find_thread(machine, event->fork.tid);  	struct thread *parent = machine__findnew_thread(machine, @@ -1119,7 +1109,7 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event  		perf_event__fprintf_task(event, stdout);  	if (thread == NULL || parent == NULL || -	    thread__fork(thread, parent) < 0) { +	    thread__fork(thread, parent, sample->time) < 0) {  		dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");  		return -1;  	} @@ -1127,8 +1117,8 @@ int machine__process_fork_event(struct machine *machine, union perf_event *event  	return 0;  } -int machine__process_exit_event(struct machine *machine __maybe_unused, -				union perf_event *event) +int machine__process_exit_event(struct machine *machine, union perf_event *event, +				struct perf_sample *sample __maybe_unused)  {  	struct thread *thread = machine__find_thread(machine, event->fork.tid); @@ -1141,23 +1131,24 @@ int machine__process_exit_event(struct machine *machine __maybe_unused,  	return 0;  } -int machine__process_event(struct machine *machine, union perf_event *event) +int machine__process_event(struct machine *machine, union perf_event *event, +			   struct perf_sample *sample)  {  	int ret;  	switch (event->header.type) {  	case PERF_RECORD_COMM: -		ret = machine__process_comm_event(machine, event); break; +		ret = machine__process_comm_event(machine, event, sample); break;  	case PERF_RECORD_MMAP: -		ret = machine__process_mmap_event(machine, event); break; +		ret = machine__process_mmap_event(machine, event, sample); break;  	case PERF_RECORD_MMAP2: -		ret = machine__process_mmap2_event(machine, event); break; +		ret = machine__process_mmap2_event(machine, event, sample); break;  	case PERF_RECORD_FORK: -		ret = machine__process_fork_event(machine, event); break; +		ret = machine__process_fork_event(machine, event, sample); break;  	case PERF_RECORD_EXIT: -		ret = machine__process_exit_event(machine, event); break; +		ret = machine__process_exit_event(machine, event, sample); break;  	case PERF_RECORD_LOST: -		ret = machine__process_lost_event(machine, event); break; +		ret = machine__process_lost_event(machine, event, sample); break;  	default:  		ret = -1;  		break; @@ -1267,10 +1258,12 @@ static int machine__resolve_callchain_sample(struct machine *machine,  					     struct thread *thread,  					     struct ip_callchain *chain,  					     struct symbol **parent, -					     struct addr_location *root_al) +					     struct addr_location *root_al, +					     int max_stack)  {  	u8 cpumode = PERF_RECORD_MISC_USER; -	unsigned int i; +	int chain_nr = min(max_stack, (int)chain->nr); +	int i;  	int err;  	callchain_cursor_reset(&callchain_cursor); @@ -1280,7 +1273,7 @@ static int machine__resolve_callchain_sample(struct machine *machine,  		return 0;  	} -	for (i = 0; i < chain->nr; i++) { +	for (i = 0; i < chain_nr; i++) {  		u64 ip;  		struct addr_location al; @@ -1352,12 +1345,14 @@ int machine__resolve_callchain(struct machine *machine,  			       struct thread *thread,  			       struct perf_sample *sample,  			       struct symbol **parent, -			       struct addr_location *root_al) +			       struct addr_location *root_al, +			       int max_stack)  {  	int ret;  	ret = machine__resolve_callchain_sample(machine, thread, -						sample->callchain, parent, root_al); +						sample->callchain, parent, +						root_al, max_stack);  	if (ret)  		return ret; @@ -1376,3 +1371,26 @@ int machine__resolve_callchain(struct machine *machine,  				   sample);  } + +int machine__for_each_thread(struct machine *machine, +			     int (*fn)(struct thread *thread, void *p), +			     void *priv) +{ +	struct rb_node *nd; +	struct thread *thread; +	int rc = 0; + +	for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) { +		thread = rb_entry(nd, struct thread, rb_node); +		rc = fn(thread, priv); +		if (rc != 0) +			return rc; +	} + +	list_for_each_entry(thread, &machine->dead_threads, node) { +		rc = fn(thread, priv); +		if (rc != 0) +			return rc; +	} +	return rc; +}  | 
