コード例 #1
0
static int sched_wakeup_handler(struct trace_seq *s, struct pevent_record *record,
				struct event_format *event, void *context)
{
	struct format_field *field;
	unsigned long long val;

	if (pevent_get_field_val(s, event, "pid", record, &val, 1))
		return trace_seq_putc(s, '!');

	field = pevent_find_any_field(event, "comm");
	if (field) {
		write_and_save_comm(field, record, s, val);
		trace_seq_putc(s, ':');
	}
	trace_seq_printf(s, "%lld", val);

	if (pevent_get_field_val(s, event, "prio", record, &val, 0) == 0)
		trace_seq_printf(s, " [%lld]", val);

	if (pevent_get_field_val(s, event, "success", record, &val, 1) == 0)
		trace_seq_printf(s, " success=%lld", val);

	if (pevent_get_field_val(s, event, "target_cpu", record, &val, 0) == 0)
		trace_seq_printf(s, " CPU:%03llu", val);

	return 0;
}
コード例 #2
0
static int sched_switch_handler(struct trace_seq *s, struct pevent_record *record,
				struct event_format *event, void *context)
{
	struct format_field *field;
	unsigned long long val;

	if (pevent_get_field_val(s, event, "prev_pid", record, &val, 1))
		return trace_seq_putc(s, '!');

	field = pevent_find_any_field(event, "prev_comm");
	if (field) {
		write_and_save_comm(field, record, s, val);
		trace_seq_putc(s, ':');
	}
	trace_seq_printf(s, "%lld ", val);

	if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0)
		trace_seq_printf(s, "[%lld] ", val);

	if (pevent_get_field_val(s,  event, "prev_state", record, &val, 0) == 0)
		write_state(s, val);

	trace_seq_puts(s, " ==> ");

	if (pevent_get_field_val(s, event, "next_pid", record, &val, 1))
		return trace_seq_putc(s, '!');

	field = pevent_find_any_field(event, "next_comm");
	if (field) {
		write_and_save_comm(field, record, s, val);
		trace_seq_putc(s, ':');
	}
	trace_seq_printf(s, "%lld", val);

	if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0)
		trace_seq_printf(s, " [%lld]", val);

	return 0;
}
コード例 #3
0
static struct filter_arg *
create_arg_item(struct event_format *event, const char *token,
		enum event_type type, char **error_str)
{
	struct format_field *field;
	struct filter_arg *arg;

	arg = allocate_arg();

	switch (type) {

	case EVENT_SQUOTE:
	case EVENT_DQUOTE:
		arg->type = FILTER_ARG_VALUE;
		arg->value.type =
			type == EVENT_DQUOTE ? FILTER_STRING : FILTER_CHAR;
		arg->value.str = strdup(token);
		if (!arg->value.str)
			die("malloc string");
		break;
	case EVENT_ITEM:
		/* if it is a number, then convert it */
		if (isdigit(token[0])) {
			arg->type = FILTER_ARG_VALUE;
			arg->value.type = FILTER_NUMBER;
			arg->value.val = strtoull(token, NULL, 0);
			break;
		}
		/* Consider this a field */
		field = pevent_find_any_field(event, token);
		if (!field) {
			if (strcmp(token, COMM) != 0) {
				/* not a field, Make it false */
				arg->type = FILTER_ARG_BOOLEAN;
				arg->boolean.value = FILTER_FALSE;
				break;
			}
			/* If token is 'COMM' then it is special */
			field = &comm;
		}
		arg->type = FILTER_ARG_FIELD;
		arg->field.field = field;
		break;
	default:
		free_arg(arg);
		show_error(error_str, "expected a value but found %s",
			   token);
		return NULL;
	}
	return arg;
}
コード例 #4
0
unsigned long long
raw_field_value(struct event_format *event, const char *name, void *data)
{
	struct format_field *field;
	unsigned long long val;

	field = pevent_find_any_field(event, name);
	if (!field)
		return 0ULL;

	pevent_read_number_field(field, data, &val);

	return val;
}
コード例 #5
0
void *raw_field_ptr(struct event_format *event, const char *name, void *data)
{
	struct format_field *field;

	field = pevent_find_any_field(event, name);
	if (!field)
		return NULL;

	if (field->flags & FIELD_IS_DYNAMIC) {
		int offset;

		offset = *(int *)(data + field->offset);
		offset &= 0xffff;

		return data + offset;
	}

	return data + field->offset;
}
コード例 #6
0
ファイル: do_process.cpp プロジェクト: tomspur/powertop
void perf_process_bundle::handle_trace_point(void *trace, int cpu, uint64_t time)
{
	struct event_format *event;
	struct pevent_record rec; /* holder */
	struct format_field *field;
	unsigned long long val;
	int type;
	int ret;

	rec.data = trace;

	type = pevent_data_type(perf_event::pevent, &rec);
	event = pevent_find_event(perf_event::pevent, type);
	if (!event)
		return;

	if (time < first_stamp)
		first_stamp = time;

	if (time > last_stamp) {
		last_stamp = time;
		measurement_time = (0.0001 + last_stamp - first_stamp) / 1000000000 ;
	}

	if (strcmp(event->name, "sched_switch") == 0) {
		class process *old_proc = NULL;
		class process *new_proc  = NULL;
		const char *next_comm;
		int next_pid;
		int prev_pid;

		field = pevent_find_any_field(event, "next_comm");
		if (!field || !(field->flags & FIELD_IS_STRING))
			return; /* ?? */
	
		next_comm = get_pevent_field_str(trace, event, field);

		ret = pevent_get_field_val(NULL, event, "next_pid", &rec, &val, 0);
		if (ret < 0)
			return;
		next_pid = (int)val;

		ret = pevent_get_field_val(NULL, event, "prev_pid", &rec, &val, 0);
		if (ret < 0)
			return;
		prev_pid = (int)val;

		/* find new process pointer */
		new_proc = find_create_process(next_comm, next_pid);

		/* find the old process pointer */

		while  (consumer_depth(cpu) > 1) {
			pop_consumer(cpu);
		}

		if (consumer_depth(cpu) == 1)
			old_proc = (class process *)current_consumer(cpu);

		if (old_proc && strcmp(old_proc->name(), "process"))
			old_proc = NULL;

		/* retire the old process */

		if (old_proc) {
			old_proc->deschedule_thread(time, prev_pid);
			old_proc->waker = NULL;
		}

		if (consumer_depth(cpu))
			pop_consumer(cpu);

		push_consumer(cpu, new_proc);

		/* start new process */
		new_proc->schedule_thread(time, next_pid);

		if (strncmp(next_comm,"migration/", 10) && strncmp(next_comm,"kworker/", 8) && strncmp(next_comm, "kondemand/",10)) {
			if (next_pid) {
				/* If someone woke us up.. blame him instead */
				if (new_proc->waker) {
					change_blame(cpu, new_proc->waker, LEVEL_PROCESS);
				} else {
					change_blame(cpu, new_proc, LEVEL_PROCESS);
				}
			}

			consume_blame(cpu);
		}
		new_proc->waker = NULL;
	}
	else if (strcmp(event->name, "sched_wakeup") == 0) {
		class power_consumer *from = NULL;
		class process *dest_proc = NULL;  
		class process *from_proc = NULL; 
		const char *comm;
		int flags;
		int pid;

		ret = pevent_get_common_field_val(NULL, event, "common_flags", &rec, &val, 0);
		if (ret < 0)
			return;
		flags = (int)val;

		if ( (flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ)) {
			class timer *timer;
			timer = (class timer *) current_consumer(cpu);
			if (timer && strcmp(timer->name(), "timer")==0) {
				if (strcmp(timer->handler, "delayed_work_timer_fn") &&
				    strcmp(timer->handler, "hrtimer_wakeup") &&
				    strcmp(timer->handler, "it_real_fn"))
					from = timer;
			}
			/* woken from interrupt */
			/* TODO: find the current irq handler and set "from" to that */
		} else {
			from = current_consumer(cpu);
		}


		field = pevent_find_any_field(event, "comm");

		if (!field || !(field->flags & FIELD_IS_STRING))
 			return; 

		comm = get_pevent_field_str(trace, event, field);

		ret = pevent_get_field_val(NULL, event, "pid", &rec, &val, 0);
		if (ret < 0)
			return;
		pid = (int)val;

		dest_proc = find_create_process(comm, pid);

		if (from && strcmp(from->name(), "process")!=0){
			/* not a process doing the wakeup */
			from = NULL;
			from_proc = NULL;
		} else {
			from_proc = (class process *) from;
		}

		if (from_proc && (dest_proc->running == 0) && (dest_proc->waker == NULL) && (pid != 0) && !dont_blame_me(from_proc->comm))
			dest_proc->waker = from;
		if (from)
			dest_proc->last_waker = from;

		/* Account processes that wake up X specially */
		if (from && dest_proc && comm_is_xorg(dest_proc->comm))
			from->xwakes ++ ;

	}
	else if (strcmp(event->name, "irq_handler_entry") == 0) {
		class interrupt *irq = NULL;
		const char *handler;
		int nr;

		field = pevent_find_any_field(event, "name");
		if (!field || !(field->flags & FIELD_IS_STRING))
			return; /* ?? */

		handler = get_pevent_field_str(trace, event, field);

		ret = pevent_get_field_val(NULL, event, "irq", &rec, &val, 0);
		if (ret < 0)
			return;
		nr = (int)val;

		irq = find_create_interrupt(handler, nr, cpu);


		push_consumer(cpu, irq);

		irq->start_interrupt(time);

		if (strstr(irq->handler, "timer") ==NULL)
			change_blame(cpu, irq, LEVEL_HARDIRQ);

	}

	else if (strcmp(event->name, "irq_handler_exit") == 0) {
		class interrupt *irq = NULL;
		uint64_t t;

		/* find interrupt (top of stack) */
		irq = (class interrupt *)current_consumer(cpu);
		if (!irq || strcmp(irq->name(), "interrupt"))
			return;
		pop_consumer(cpu);
		/* retire interrupt */
		t = irq->end_interrupt(time);
		consumer_child_time(cpu, t);
	}

	else if (strcmp(event->name, "softirq_entry") == 0) {
		class interrupt *irq = NULL;
		const char *handler = NULL;
		int vec;

		ret = pevent_get_field_val(NULL, event, "vec", &rec, &val, 0);
                if (ret < 0) {
                        fprintf(stderr, "softirq_entry event returned no vector number?\n");
                        return;
                }
		vec = (int)val;

		if (vec <= 9)
			handler = softirqs[vec];

		if (!handler)
			return;

		irq = find_create_interrupt(handler, vec, cpu);

		push_consumer(cpu, irq);

		irq->start_interrupt(time);
		change_blame(cpu, irq, LEVEL_SOFTIRQ);
	}
	else if (strcmp(event->name, "softirq_exit") == 0) {
		class interrupt *irq = NULL;
		uint64_t t;

		irq = (class interrupt *) current_consumer(cpu);
		if (!irq  || strcmp(irq->name(), "interrupt"))
			return;
		pop_consumer(cpu);
		/* pop irq */
		t = irq->end_interrupt(time);
		consumer_child_time(cpu, t);
	}
	else if (strcmp(event->name, "timer_expire_entry") == 0) {
		class timer *timer = NULL;
		uint64_t function;
		uint64_t tmr;

		ret = pevent_get_field_val(NULL, event, "function", &rec, &val, 0);
		if (ret < 0) {
			fprintf(stderr, "timer_expire_entry event returned no fucntion value?\n");
			return;
		}
		function = (uint64_t)val;

		timer = find_create_timer(function);

		if (timer->is_deferred())
			return;

		ret = pevent_get_field_val(NULL, event, "timer", &rec, &val, 0);
		if (ret < 0) {
			fprintf(stderr, "softirq_entry event returned no timer ?\n");
			return;
		}
		tmr = (uint64_t)val;

		push_consumer(cpu, timer);
		timer->fire(time, tmr);

		if (strcmp(timer->handler, "delayed_work_timer_fn"))
			change_blame(cpu, timer, LEVEL_TIMER);
	}
	else if (strcmp(event->name, "timer_expire_exit") == 0) {
		class timer *timer = NULL;
		uint64_t tmr;
		uint64_t t;

		ret = pevent_get_field_val(NULL, event, "timer", &rec, &val, 0);
		if (ret < 0)
			return;
		tmr = (uint64_t)val;

		timer = (class timer *) current_consumer(cpu);
		if (!timer || strcmp(timer->name(), "timer")) {
			return;
		}
		pop_consumer(cpu);
		t = timer->done(time, tmr);
		consumer_child_time(cpu, t);
	}
	else if (strcmp(event->name, "hrtimer_expire_entry") == 0) {
		class timer *timer = NULL;
		uint64_t function;
		uint64_t tmr;

		ret = pevent_get_field_val(NULL, event, "function", &rec, &val, 0);
		if (ret < 0)
			return;
		function = (uint64_t)val;

		timer = find_create_timer(function);

		ret = pevent_get_field_val(NULL, event, "hrtimer", &rec, &val, 0);
		if (ret < 0)
			return;
		tmr = (uint64_t)val;

		push_consumer(cpu, timer);
		timer->fire(time, tmr);

		if (strcmp(timer->handler, "delayed_work_timer_fn"))
			change_blame(cpu, timer, LEVEL_TIMER);
	}
	else if (strcmp(event->name, "hrtimer_expire_exit") == 0) {
		class timer *timer = NULL;
		uint64_t tmr;
		uint64_t t;

		timer = (class timer *) current_consumer(cpu);
		if (!timer || strcmp(timer->name(), "timer")) {
			return;
		}

		ret = pevent_get_field_val(NULL, event, "hrtimer", &rec, &val, 0);
		if (ret < 0)
			return;
		tmr = (uint64_t)val;

		pop_consumer(cpu);
		t = timer->done(time, tmr);
		consumer_child_time(cpu, t);
	}
	else if (strcmp(event->name, "workqueue_execute_start") == 0) {
		class work *work = NULL;
		uint64_t function;
		uint64_t wk;

		ret = pevent_get_field_val(NULL, event, "function", &rec, &val, 0);
		if (ret < 0)
			return;
		function = (uint64_t)val;

		ret = pevent_get_field_val(NULL, event, "work", &rec, &val, 0);
		if (ret < 0)
			return;
		wk = (uint64_t)val;

		work = find_create_work(function);


		push_consumer(cpu, work);
		work->fire(time, wk);


		if (strcmp(work->handler, "do_dbs_timer") != 0 && strcmp(work->handler, "vmstat_update") != 0)
			change_blame(cpu, work, LEVEL_WORK);
	}
	else if (strcmp(event->name, "workqueue_execute_end") == 0) {
		class work *work = NULL;
		uint64_t t;
		uint64_t wk;

		ret = pevent_get_field_val(NULL, event, "work", &rec, &val, 0);
		if (ret < 0)
			return;
		wk = (uint64_t)val;

		work = (class work *) current_consumer(cpu);
		if (!work || strcmp(work->name(), "work")) {
			return;
		}
		pop_consumer(cpu);
		t = work->done(time, wk);
		consumer_child_time(cpu, t);
	}
	else if (strcmp(event->name, "cpu_idle") == 0) {
		ret = pevent_get_field_val(NULL, event, "state", &rec, &val, 0);
		if (val == 4294967295)
			consume_blame(cpu);
		else
			set_wakeup_pending(cpu);
	}
	else if (strcmp(event->name, "power_start") == 0) {
		set_wakeup_pending(cpu);
	}
	else if (strcmp(event->name, "power_end") == 0) {
		consume_blame(cpu);
	}
	else if (strcmp(event->name, "i915_gem_ring_dispatch") == 0
	 || strcmp(event->name, "i915_gem_request_submit") == 0) {
		/* any kernel contains only one of the these tracepoints,
		 * the latter one got replaced by the former one */
		class power_consumer *consumer = NULL;
		int flags;

		ret = pevent_get_common_field_val(NULL, event, "common_flags", &rec, &val, 0);
		if (ret < 0)
			return;
		flags = (int)val;

		consumer = current_consumer(cpu);
		/* currently we don't count graphic requests submitted from irq contect */
		if ( (flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ)) {
			consumer = NULL;
		}


		/* if we are X, and someone just woke us, account the GPU op to the guy waking us */
		if (consumer && strcmp(consumer->name(), "process")==0) {
			class process *proc = NULL;
			proc = (class process *) consumer;
			if (comm_is_xorg(proc->comm) && proc->last_waker) {
				consumer = proc->last_waker;
			}
		}



		if (consumer) {
			consumer->gpu_ops++;
		}
	}
	else if (strcmp(event->name, "writeback_inode_dirty") == 0) {
		static uint64_t prev_time;
		class power_consumer *consumer = NULL;
		int dev;

		consumer = current_consumer(cpu);

		ret = pevent_get_field_val(NULL, event, "dev", &rec, &val, 0);
		if (ret < 0)
			
			return;
		dev = (int)val;

		if (consumer && strcmp(consumer->name(),
			"process")==0 && dev > 0) {

			consumer->disk_hits++;

			/* if the previous inode dirty was > 1 second ago, it becomes a hard hit */
			if ((time - prev_time) > 1000000000)
				consumer->hard_disk_hits++;

			prev_time = time;
		}
	}
}
コード例 #7
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);
}