Example #1
0
static void do_trace_mem(struct tracecmd_input *handle)
{
	struct pevent *pevent = tracecmd_get_pevent(handle);
	struct event_format *event;
	struct pevent_record *record;
	int missed_events = 0;
	int cpus;
	int cpu;
	int ret;

	ret = tracecmd_init_data(handle);
	if (ret < 0)
		die("failed to init data");

	if (ret > 0)
		die("trace-cmd mem does not work with latency traces\n");

	cpus = tracecmd_cpus(handle);

	/* Need to get any event */
	for (cpu = 0; cpu < cpus; cpu++) {
		record = tracecmd_peek_data(handle, cpu);
		if (record)
			break;
	}
	if (!record)
		die("No records found in file");

	ret = pevent_data_type(pevent, record);
	event = pevent_data_event_from_type(pevent, ret);

	common_type_field = pevent_find_common_field(event, "common_type");
	if (!common_type_field)
		die("Can't find a 'type' field?");

	update_kmalloc(pevent);
	update_kmalloc_node(pevent);
	update_kfree(pevent);
	update_kmem_cache_alloc(pevent);
	update_kmem_cache_alloc_node(pevent);
	update_kmem_cache_free(pevent);

	while ((record = tracecmd_read_next_data(handle, &cpu))) {

		/* record missed event */
		if (!missed_events && record->missed_events)
			missed_events = 1;

		process_record(pevent, record);
		free_record(record);
	}

	sort_list();
	print_list();
}
Example #2
0
int tracecmd_ftrace_overrides(struct tracecmd_input *handle,
	struct tracecmd_ftrace *finfo)
{
	struct tep_handle *pevent;
	struct tep_event *event;

	finfo->handle = handle;

	pevent = tracecmd_get_pevent(handle);

	tep_register_event_handler(pevent, -1, "ftrace", "function",
				      function_handler, NULL);

	tep_register_event_handler(pevent, -1, "ftrace", "funcgraph_entry",
				      fgraph_ent_handler, finfo);

	tep_register_event_handler(pevent, -1, "ftrace", "funcgraph_exit",
				      fgraph_ret_handler, finfo);

	tep_register_event_handler(pevent, -1, "ftrace", "kernel_stack",
				      trace_stack_handler, finfo);

	trace_util_add_options("ftrace", trace_ftrace_options);

	/* Store the func ret id and event for later use */
	event = tep_find_event_by_name(pevent, "ftrace", "funcgraph_exit");
	if (!event)
		return 0;

	finfo->long_size = tracecmd_long_size(handle);

	finfo->fgraph_ret_id = event->id;
	finfo->fgraph_ret_event = event;

	return 0;
}
Example #3
0
int tracecmd_blk_hack(struct tracecmd_input *handle)
{
	struct pevent *pevent;
	struct event_format *event;
	struct format_field *field;
	char buf[4096]; /* way more than enough! */
	int id;
	int l;
	int r;

	pevent = tracecmd_get_pevent(handle);

	/*
	 * Unfortunately, the TRACE_BLK has changed a bit.
	 * We need to test if various events exist to try
	 * to guess what event id TRACE_BLK would be.
	 */

	/* It was originally behind the "power" event */
	event = pevent_find_event_by_name(pevent, "ftrace", "power");
	if (event) {
		id = event->id + 1;
		goto found;
	}

	/*
	 * But the power tracer is now in perf.
	 * Then it was after kmem_free
	 */
	event = pevent_find_event_by_name(pevent, "ftrace", "kmem_free");
	if (event) {
		id = event->id + 1;
		goto found;
	}

	/*
	 * But that then went away.
	 * Currently it should be behind the user stack.
	 */
	event = pevent_find_event_by_name(pevent, "ftrace", "user_stack");
	if (event) {
		id = event->id + 1;
		goto found;
	}
	/* Give up :( */
	return -1;

 found:
	/*
	 * Blk events are not exported in the events directory.
	 * This is a hack to attempt to create a block event
	 * that we can read.
	 *
	 * We'll make a format file to look like this:
	 *
	 * name: blktrace
	 * ID: 13
	 * format:
	 *	field:unsigned short common_type;	offset:0;	size:2;
	 *	field:unsigned char common_flags;	offset:2;	size:1;
	 *	field:unsigned char common_preempt_count;	offset:3;	size:1;
	 *	field:int common_pid;	offset:4;	size:4;
	 *	field:int common_lock_depth;	offset:8;	size:4;
	 *
	 *	field:u64 sector;	offset:16;	size:8;
	 *	field:int bytes;	offset:32;	size:4;
	 *	field:int action;	offset:36;	size:4;
	 *	field:int pid;	offset:40;	size:4;
	 *	field:int device;	offset:44;	size:4;
	 *	field:int cpu;	offset:48;	size:4;
	 *	field:short error;	offset:52;	size:2;
	 *	field:short pdu_len;	offset:54;	size:2;
	 *	field:void data;	offset:60;	size:0;
	 *
	 * print fmt: "%d", REC->pid
	 *
	 * Note: the struct blk_io_trace is used directly and
	 * just the first parts of the struct are not used in order
	 * to not write over the ftrace data.
	 */

	/* Make sure the common fields exist */
	field = pevent_find_common_field(event, "common_type");
	if (!field || field->offset != 0 || field->size != 2)
		goto fail;
	field = pevent_find_common_field(event, "common_flags");
	if (!field || field->offset != 2 || field->size != 1)
		goto fail;
	field = pevent_find_common_field(event, "common_preempt_count");
	if (!field || field->offset != 3 || field->size != 1)
		goto fail;
	field = pevent_find_common_field(event, "common_pid");
	if (!field || field->offset != 4 || field->size != 4)
		goto fail;
	r = sprintf(buf, blk_event_start, id);
	l = r;

	/* lock depth is optional */
	field = pevent_find_common_field(event, "common_lock_depth");
	if (field) {
		if (field->offset != 8 || field->size != 4)
			return -1;
		r = sprintf(buf+l, "\tfield:int common_lock_depth;\toffset:8;\tsize:4;\n");
		l += r;
	}

	r = sprintf(buf+l, blk_body);

	/* Parse this event */
	l += r;
	pevent_parse_event(pevent, buf, l, "ftrace");

	return 0;

 fail:
	return -1;
}
Example #4
0
TraceViewStore *
trace_view_store_new (struct tracecmd_input *handle)
{
	TraceViewStore *newstore;
	struct record *data;
	gint cpu, count, total=0;
	struct temp {
		guint64		offset;
		guint64		ts;
		struct temp	*next;
	} *list, **next, *rec;

	newstore = (TraceViewStore*) g_object_new (TRACE_VIEW_STORE_TYPE, NULL);

	g_assert( newstore != NULL );

	newstore->handle = handle;
	newstore->cpus = tracecmd_cpus(handle);
	tracecmd_ref(handle);
	newstore->event_filter = pevent_filter_alloc(tracecmd_get_pevent(handle));

	newstore->cpu_list = g_new(TraceViewRecord *, newstore->cpus);
	g_assert(newstore->cpu_list != NULL);

	newstore->cpu_items = g_new(gint, newstore->cpus);
	g_assert(newstore->cpu_items != NULL);

	newstore->all_cpus = 1;
	newstore->all_events = 1;

	newstore->cpu_mask = g_new0(guint64, (newstore->cpus >> 6) + 1);
	g_assert(newstore->cpu_mask != NULL);

	mask_set_cpus(newstore, newstore->cpus);

	for (cpu = 0; cpu < newstore->cpus; cpu++) {

		count = 0;
		list = NULL;
		next = &list;

		data = tracecmd_read_cpu_first(handle, cpu);
		while (data) {
			*next = rec = g_malloc(sizeof(*rec));
			g_assert(rec != NULL);
			rec->offset = data->offset;
			rec->ts = data->ts;
			rec->next = NULL;
			next = &rec->next;
			free_record(data);
			count++;
			data = tracecmd_read_data(handle, cpu);
		}

		if (count) {
			TraceViewRecord *trec;
			struct temp *t;
			gint i;

			rec = list;

			trec = g_new(TraceViewRecord, count);
			g_assert(trec != NULL);

			for (i = 0; i < count; i++) {
				g_assert(rec != NULL);
				trec[i].cpu = cpu;
				trec[i].timestamp = rec->ts;
				trec[i].offset = rec->offset;
				trec[i].visible = 1;
				trec[i].pos = i;
				t = rec;
				rec = rec->next;
				g_free(t);
			}
			g_assert(rec == NULL);

			newstore->cpu_list[cpu] = trec;
		} else
			newstore->cpu_list[cpu] = NULL;

		newstore->cpu_items[cpu] = count;

		total += count;
	}

	newstore->actual_rows = total;
	newstore->rows = g_malloc(sizeof(*newstore->rows) * total + 1);

	merge_sort_rows_ts(newstore);

	return newstore;
}
Example #5
0
void
trace_view_store_get_value (GtkTreeModel *tree_model,
			    GtkTreeIter	*iter,
			    gint	column,
			    GValue	*value)
{
	TraceViewRecord	*record;
	TraceViewStore	*trace_view_store;
	struct trace_seq s;
	struct pevent *pevent;
	struct event_format *event;
	struct record *data;
	const gchar *comm;
	gchar *str;
	guint64 secs, usecs;
	gint val;
	int cpu;

	g_return_if_fail (TRACE_VIEW_IS_LIST (tree_model));
	g_return_if_fail (iter != NULL);
	g_return_if_fail (column < TRACE_VIEW_STORE(tree_model)->n_columns);

	g_value_init (value, TRACE_VIEW_STORE(tree_model)->column_types[column]);

	trace_view_store = TRACE_VIEW_STORE(tree_model);

	pevent = tracecmd_get_pevent(trace_view_store->handle);

	record = (TraceViewRecord*)iter->user_data;

	g_return_if_fail ( record != NULL );

	column = get_visible_column(TRACE_VIEW_STORE(tree_model), column);

	switch(column)
	{
	case TRACE_VIEW_STORE_COL_INDEX:
		g_value_set_uint(value, record->pos);
		break;

	case TRACE_VIEW_STORE_COL_CPU:
		g_value_set_uint(value, record->cpu);
		break;

	case TRACE_VIEW_STORE_COL_TS:
		usecs = record->timestamp;
		usecs /= 1000;
		secs = usecs / 1000000ULL;
		usecs -= secs * 1000000ULL;
		str = g_strdup_printf("%llu.%06llu",
				      (long long)secs, (long long)usecs);
		g_value_set_string(value, str);
		g_free(str);
		break;
		
	case TRACE_VIEW_STORE_COL_COMM:
	case TRACE_VIEW_STORE_COL_PID:
	case TRACE_VIEW_STORE_COL_LAT:
	case TRACE_VIEW_STORE_COL_EVENT:
	case TRACE_VIEW_STORE_COL_INFO:

		data = tracecmd_read_at(trace_view_store->handle, record->offset, &cpu);
		g_assert(data != NULL);
		if (cpu != record->cpu) {
			free_record(data);
			return;
		}

		switch (column) {
		case TRACE_VIEW_STORE_COL_COMM:
		case TRACE_VIEW_STORE_COL_PID:
			val = pevent_data_pid(pevent, data);
			if (column == TRACE_VIEW_STORE_COL_PID)
				g_value_set_uint(value, val);
			else {
				comm = pevent_data_comm_from_pid(pevent, val);
				g_value_set_string(value, comm);
			}
			break;

		case TRACE_VIEW_STORE_COL_LAT:
			trace_seq_init(&s);
			pevent_data_lat_fmt(pevent, &s, data);
			g_value_set_string(value, s.buffer);
			trace_seq_destroy(&s);
			break;

		case TRACE_VIEW_STORE_COL_EVENT:
		case TRACE_VIEW_STORE_COL_INFO:
			val = pevent_data_type(pevent, data);
			event = pevent_data_event_from_type(pevent, val);
			if (!event) {
				if (column == TRACE_VIEW_STORE_COL_EVENT)
					g_value_set_string(value, "[UNKNOWN EVENT]");
				break;
			}

			if (column == TRACE_VIEW_STORE_COL_EVENT) {
				g_value_set_string(value, event->name);
				break;
			}

			trace_seq_init(&s);
			pevent_event_info(&s, event, data);
			g_value_set_string(value, s.buffer);
			trace_seq_destroy(&s);
			break;
		}
		free_record(data);
	}
}
Example #6
0
static void update_filter_tasks(TraceViewStore *store)
{
	struct tracecmd_input *handle;
	struct pevent *pevent;
	struct record *record;
	gint pid;
	gint cpu;
	gint i;

	handle = store->handle;
	pevent = tracecmd_get_pevent(store->handle);

	if (!store->sched_switch_event) {
		store->sched_switch_event =
			pevent_find_event_by_name(pevent, "sched", "sched_switch");
		if (store->sched_switch_event)
			store->sched_switch_next_field =
				pevent_find_any_field(store->sched_switch_event,
						      "next_pid");
		store->sched_wakeup_event =
			pevent_find_event_by_name(pevent, "sched", "sched_wakeup");
		if (store->sched_wakeup_event)
			store->sched_wakeup_pid_field =
				pevent_find_any_field(store->sched_wakeup_event,
						      "pid");

		store->sched_wakeup_new_event =
			pevent_find_event_by_name(pevent, "sched", "sched_wakeup");
		if (store->sched_wakeup_new_event)
			store->sched_wakeup_new_pid_field =
				pevent_find_any_field(store->sched_wakeup_new_event,
						      "pid");
	}

	for (cpu = 0; cpu < store->cpus; cpu++) {
		record = tracecmd_read_cpu_first(handle, cpu);

		for (i = 0; i < store->cpu_items[cpu]; i++) {

			g_assert(record->offset == store->cpu_list[cpu][i].offset);

			/* The record may be filtered by the events */
			if (!store->all_events) {
				int ret;
				ret = pevent_filter_match(store->event_filter,
							  record);
				if (ret != FILTER_MATCH) {
					store->cpu_list[cpu][i].visible = 0;
					goto skip;
				}
			}

			pid = pevent_data_pid(pevent, record);
			if (show_task(store, pevent, record, pid))
				store->cpu_list[cpu][i].visible = 1;
			else
				store->cpu_list[cpu][i].visible = 0;

 skip:
			free_record(record);
			record = tracecmd_read_data(handle, cpu);
		}
		g_assert(record == NULL);
	}

	merge_sort_rows_ts(store);
}
Example #7
0
static void do_trace_hist(struct tracecmd_input *handle)
{
	struct pevent *pevent = tracecmd_get_pevent(handle);
	struct event_format *event;
	struct pevent_record *record;
	int cpus;
	int cpu;
	int ret;

	ret = tracecmd_init_data(handle);
	if (ret < 0)
		die("failed to init data");

	if (ret > 0)
		die("trace-cmd hist does not work with latency traces\n");

	cpus = tracecmd_cpus(handle);

	/* Need to get any event */
	for (cpu = 0; cpu < cpus; cpu++) {
		record = tracecmd_peek_data(handle, cpu);
		if (record)
			break;
	}
	if (!record)
		die("No records found in file");

	ret = pevent_data_type(pevent, record);
	event = pevent_data_event_from_type(pevent, ret);

	long_size = tracecmd_long_size(handle);

	common_type_field = pevent_find_common_field(event, "common_type");
	if (!common_type_field)
		die("Can't find a 'type' field?");

	common_pid_field = pevent_find_common_field(event, "common_pid");
	if (!common_pid_field)
		die("Can't find a 'pid' field?");

	update_sched_wakeup(pevent);
	update_sched_wakeup_new(pevent);
	update_sched_switch(pevent);
	update_function(pevent);
	update_function_graph_entry(pevent);
	update_function_graph_exit(pevent);
	update_kernel_stack(pevent);

	for (cpu = 0; cpu < cpus; cpu++) {
		for (;;) {
			struct pevent_record *record;

			record = tracecmd_read_data(handle, cpu);
			if (!record)
				break;

			/* If we missed events, just flush out the current stack */
			if (record->missed_events)
				flush_stack();

			process_record(pevent, record);
			free_record(record);
		}
	}

	if (current_pid >= 0)
		save_call_chain(current_pid, ips, ips_idx, 0);
	if (pending_pid >= 0)
		save_call_chain(pending_pid, pending_ips, pending_ips_idx, 1);

	save_stored_stacks();

	sort_chains();
	print_chains(pevent);
}