Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b8ecad8b authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'perf/core' of...

Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/urgent
parents eea4a0b1 8bfb5e7d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -410,7 +410,7 @@ extern void open_softirq(int nr, void (*action)(struct softirq_action *));
extern void softirq_init(void);
static inline void __raise_softirq_irqoff(unsigned int nr)
{
	trace_softirq_raise((struct softirq_action *)(unsigned long)nr, NULL);
	trace_softirq_raise(nr);
	or_softirq_pending(1UL << nr);
}

+20 −34
Original line number Diff line number Diff line
@@ -86,76 +86,62 @@ TRACE_EVENT(irq_handler_exit,

DECLARE_EVENT_CLASS(softirq,

	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
	TP_PROTO(unsigned int vec_nr),

	TP_ARGS(h, vec),
	TP_ARGS(vec_nr),

	TP_STRUCT__entry(
		__field(	int,	vec			)
		__field(	unsigned int,	vec	)
	),

	TP_fast_assign(
		if (vec)
			__entry->vec = (int)(h - vec);
		else
			__entry->vec = (int)(long)h;
		__entry->vec = vec_nr;
	),

	TP_printk("vec=%d [action=%s]", __entry->vec,
	TP_printk("vec=%u [action=%s]", __entry->vec,
		  show_softirq_name(__entry->vec))
);

/**
 * softirq_entry - called immediately before the softirq handler
 * @h: pointer to struct softirq_action
 * @vec: pointer to first struct softirq_action in softirq_vec array
 * @vec_nr:  softirq vector number
 *
 * The @h parameter, contains a pointer to the struct softirq_action
 * which has a pointer to the action handler that is called. By subtracting
 * the @vec pointer from the @h pointer, we can determine the softirq
 * number. Also, when used in combination with the softirq_exit tracepoint
 * we can determine the softirq latency.
 * When used in combination with the softirq_exit tracepoint
 * we can determine the softirq handler runtine.
 */
DEFINE_EVENT(softirq, softirq_entry,

	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
	TP_PROTO(unsigned int vec_nr),

	TP_ARGS(h, vec)
	TP_ARGS(vec_nr)
);

/**
 * softirq_exit - called immediately after the softirq handler returns
 * @h: pointer to struct softirq_action
 * @vec: pointer to first struct softirq_action in softirq_vec array
 * @vec_nr:  softirq vector number
 *
 * The @h parameter contains a pointer to the struct softirq_action
 * that has handled the softirq. By subtracting the @vec pointer from
 * the @h pointer, we can determine the softirq number. Also, when used in
 * combination with the softirq_entry tracepoint we can determine the softirq
 * latency.
 * When used in combination with the softirq_entry tracepoint
 * we can determine the softirq handler runtine.
 */
DEFINE_EVENT(softirq, softirq_exit,

	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
	TP_PROTO(unsigned int vec_nr),

	TP_ARGS(h, vec)
	TP_ARGS(vec_nr)
);

/**
 * softirq_raise - called immediately when a softirq is raised
 * @h: pointer to struct softirq_action
 * @vec: pointer to first struct softirq_action in softirq_vec array
 * @vec_nr:  softirq vector number
 *
 * The @h parameter contains a pointer to the softirq vector number which is
 * raised. @vec is NULL and it means @h includes vector number not
 * softirq_action. When used in combination with the softirq_entry tracepoint
 * we can determine the softirq raise latency.
 * When used in combination with the softirq_entry tracepoint
 * we can determine the softirq raise to run latency.
 */
DEFINE_EVENT(softirq, softirq_raise,

	TP_PROTO(struct softirq_action *h, struct softirq_action *vec),
	TP_PROTO(unsigned int vec_nr),

	TP_ARGS(h, vec)
	TP_ARGS(vec_nr)
);

#endif /*  _TRACE_IRQ_H */
+9 −7
Original line number Diff line number Diff line
@@ -229,18 +229,20 @@ asmlinkage void __do_softirq(void)

	do {
		if (pending & 1) {
			unsigned int vec_nr = h - softirq_vec;
			int prev_count = preempt_count();
			kstat_incr_softirqs_this_cpu(h - softirq_vec);

			trace_softirq_entry(h, softirq_vec);
			kstat_incr_softirqs_this_cpu(vec_nr);

			trace_softirq_entry(vec_nr);
			h->action(h);
			trace_softirq_exit(h, softirq_vec);
			trace_softirq_exit(vec_nr);
			if (unlikely(prev_count != preempt_count())) {
				printk(KERN_ERR "huh, entered softirq %td %s %p"
				printk(KERN_ERR "huh, entered softirq %u %s %p"
				       "with preempt_count %08x,"
				       " exited with %08x?\n", h - softirq_vec,
				       softirq_to_name[h - softirq_vec],
				       h->action, prev_count, preempt_count());
				       " exited with %08x?\n", vec_nr,
				       softirq_to_name[vec_nr], h->action,
				       prev_count, preempt_count());
				preempt_count() = prev_count;
			}

+17 −1
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@ or
or
'perf probe' --list
or
'perf probe' --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]'
'perf probe' [options] --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]'
or
'perf probe' [options] --vars='PROBEPOINT'

DESCRIPTION
-----------
@@ -31,6 +33,11 @@ OPTIONS
--vmlinux=PATH::
	Specify vmlinux path which has debuginfo (Dwarf binary).

-m::
--module=MODNAME::
	Specify module name in which perf-probe searches probe points
	or lines.

-s::
--source=PATH::
	Specify path to kernel source.
@@ -57,6 +64,15 @@ OPTIONS
	Show source code lines which can be probed. This needs an argument
	which specifies a range of the source code. (see LINE SYNTAX for detail)

-V::
--vars=::
	Show available local variables at given probe point. The argument
	syntax is same as PROBE SYNTAX, but NO ARGs.

--externs::
	(Only for --vars) Show external defined variables in addition to local
	variables.

-f::
--force::
	Forcibly add events with existing name.
+67 −11
Original line number Diff line number Diff line
@@ -50,14 +50,17 @@ static struct {
	bool list_events;
	bool force_add;
	bool show_lines;
	bool show_vars;
	bool show_ext_vars;
	bool mod_events;
	int nevents;
	struct perf_probe_event events[MAX_PROBES];
	struct strlist *dellist;
	struct line_range line_range;
	const char *target_module;
	int max_probe_points;
} params;


/* Parse an event definition. Note that any error must die. */
static int parse_probe_event(const char *str)
{
@@ -92,6 +95,7 @@ static int parse_probe_event_argv(int argc, const char **argv)
	len = 0;
	for (i = 0; i < argc; i++)
		len += sprintf(&buf[len], "%s ", argv[i]);
	params.mod_events = true;
	ret = parse_probe_event(buf);
	free(buf);
	return ret;
@@ -100,9 +104,10 @@ static int parse_probe_event_argv(int argc, const char **argv)
static int opt_add_probe_event(const struct option *opt __used,
			      const char *str, int unset __used)
{
	if (str)
	if (str) {
		params.mod_events = true;
		return parse_probe_event(str);
	else
	} else
		return 0;
}

@@ -110,6 +115,7 @@ static int opt_del_probe_event(const struct option *opt __used,
			       const char *str, int unset __used)
{
	if (str) {
		params.mod_events = true;
		if (!params.dellist)
			params.dellist = strlist__new(true, NULL);
		strlist__add(params.dellist, str);
@@ -130,6 +136,25 @@ static int opt_show_lines(const struct option *opt __used,

	return ret;
}

static int opt_show_vars(const struct option *opt __used,
			 const char *str, int unset __used)
{
	struct perf_probe_event *pev = &params.events[params.nevents];
	int ret;

	if (!str)
		return 0;

	ret = parse_probe_event(str);
	if (!ret && pev->nargs != 0) {
		pr_err("  Error: '--vars' doesn't accept arguments.\n");
		return -EINVAL;
	}
	params.show_vars = true;

	return ret;
}
#endif

static const char * const probe_usage[] = {
@@ -138,7 +163,8 @@ static const char * const probe_usage[] = {
	"perf probe [<options>] --del '[GROUP:]EVENT' ...",
	"perf probe --list",
#ifdef DWARF_SUPPORT
	"perf probe --line 'LINEDESC'",
	"perf probe [<options>] --line 'LINEDESC'",
	"perf probe [<options>] --vars 'PROBEPOINT'",
#endif
	NULL
};
@@ -180,10 +206,17 @@ static const struct option options[] = {
	OPT_CALLBACK('L', "line", NULL,
		     "FUNC[:RLN[+NUM|-RLN2]]|SRC:ALN[+NUM|-ALN2]",
		     "Show source code lines.", opt_show_lines),
	OPT_CALLBACK('V', "vars", NULL,
		     "FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT",
		     "Show accessible variables on PROBEDEF", opt_show_vars),
	OPT_BOOLEAN('\0', "externs", &params.show_ext_vars,
		    "Show external variables too (with --vars only)"),
	OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
		   "file", "vmlinux pathname"),
	OPT_STRING('s', "source", &symbol_conf.source_prefix,
		   "directory", "path to kernel source"),
	OPT_STRING('m', "module", &params.target_module,
		   "modname", "target module name"),
#endif
	OPT__DRY_RUN(&probe_event_dry_run),
	OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
@@ -217,7 +250,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
		usage_with_options(probe_usage, options);

	if (params.list_events) {
		if (params.nevents != 0 || params.dellist) {
		if (params.mod_events) {
			pr_err("  Error: Don't use --list with --add/--del.\n");
			usage_with_options(probe_usage, options);
		}
@@ -225,6 +258,10 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
			pr_err("  Error: Don't use --list with --line.\n");
			usage_with_options(probe_usage, options);
		}
		if (params.show_vars) {
			pr_err(" Error: Don't use --list with --vars.\n");
			usage_with_options(probe_usage, options);
		}
		ret = show_perf_probe_events();
		if (ret < 0)
			pr_err("  Error: Failed to show event list. (%d)\n",
@@ -234,17 +271,35 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)

#ifdef DWARF_SUPPORT
	if (params.show_lines) {
		if (params.nevents != 0 || params.dellist) {
			pr_warning("  Error: Don't use --line with"
		if (params.mod_events) {
			pr_err("  Error: Don't use --line with"
			       " --add/--del.\n");
			usage_with_options(probe_usage, options);
		}
		if (params.show_vars) {
			pr_err(" Error: Don't use --line with --vars.\n");
			usage_with_options(probe_usage, options);
		}

		ret = show_line_range(&params.line_range);
		ret = show_line_range(&params.line_range, params.target_module);
		if (ret < 0)
			pr_err("  Error: Failed to show lines. (%d)\n", ret);
		return ret;
	}
	if (params.show_vars) {
		if (params.mod_events) {
			pr_err("  Error: Don't use --vars with"
			       " --add/--del.\n");
			usage_with_options(probe_usage, options);
		}
		ret = show_available_vars(params.events, params.nevents,
					  params.max_probe_points,
					  params.target_module,
					  params.show_ext_vars);
		if (ret < 0)
			pr_err("  Error: Failed to show vars. (%d)\n", ret);
		return ret;
	}
#endif

	if (params.dellist) {
@@ -258,8 +313,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)

	if (params.nevents) {
		ret = add_perf_probe_events(params.events, params.nevents,
					    params.force_add,
					    params.max_probe_points);
					    params.max_probe_points,
					    params.target_module,
					    params.force_add);
		if (ret < 0) {
			pr_err("  Error: Failed to add events. (%d)\n", ret);
			return ret;
Loading