mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 22:51:35 +00:00
tracing: Add trace_clock=<clock> kernel parameter
Being able to change the trace clock at boot can be advantageous if you need a better source of when things happen across CPUs. The default trace clock is the fastest, but it uses local clocks which may not be synced across CPUs and it does not let you know when events took place with respect to events on other CPUs. The global trace clock can help in this case, and if you do not care about timings, the counter "clock" is the best, as that is just a simple atomic counter that is incremented for every event. Usage is to add "trace_clock=counter" on the kernel command line. You can replace counter with "global" or any of the clocks listed in /sys/kernel/debug/tracing/trace_clock Suggested-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Appreciated-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
43fe98913c
commit
e1e232ca6b
@ -181,6 +181,17 @@ static int __init set_trace_boot_options(char *str)
|
||||
}
|
||||
__setup("trace_options=", set_trace_boot_options);
|
||||
|
||||
static char trace_boot_clock_buf[MAX_TRACER_SIZE] __initdata;
|
||||
static char *trace_boot_clock __initdata;
|
||||
|
||||
static int __init set_trace_boot_clock(char *str)
|
||||
{
|
||||
strlcpy(trace_boot_clock_buf, str, MAX_TRACER_SIZE);
|
||||
trace_boot_clock = trace_boot_clock_buf;
|
||||
return 0;
|
||||
}
|
||||
__setup("trace_clock=", set_trace_boot_clock);
|
||||
|
||||
|
||||
unsigned long long ns2usecs(cycle_t nsec)
|
||||
{
|
||||
@ -4746,25 +4757,10 @@ static int tracing_clock_show(struct seq_file *m, void *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
|
||||
size_t cnt, loff_t *fpos)
|
||||
static int tracing_set_clock(struct trace_array *tr, const char *clockstr)
|
||||
{
|
||||
struct seq_file *m = filp->private_data;
|
||||
struct trace_array *tr = m->private;
|
||||
char buf[64];
|
||||
const char *clockstr;
|
||||
int i;
|
||||
|
||||
if (cnt >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&buf, ubuf, cnt))
|
||||
return -EFAULT;
|
||||
|
||||
buf[cnt] = 0;
|
||||
|
||||
clockstr = strstrip(buf);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(trace_clocks); i++) {
|
||||
if (strcmp(trace_clocks[i].name, clockstr) == 0)
|
||||
break;
|
||||
@ -4792,6 +4788,32 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
|
||||
|
||||
mutex_unlock(&trace_types_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
|
||||
size_t cnt, loff_t *fpos)
|
||||
{
|
||||
struct seq_file *m = filp->private_data;
|
||||
struct trace_array *tr = m->private;
|
||||
char buf[64];
|
||||
const char *clockstr;
|
||||
int ret;
|
||||
|
||||
if (cnt >= sizeof(buf))
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(&buf, ubuf, cnt))
|
||||
return -EFAULT;
|
||||
|
||||
buf[cnt] = 0;
|
||||
|
||||
clockstr = strstrip(buf);
|
||||
|
||||
ret = tracing_set_clock(tr, clockstr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*fpos += cnt;
|
||||
|
||||
return cnt;
|
||||
@ -6574,6 +6596,13 @@ __init static int tracer_alloc_buffers(void)
|
||||
|
||||
trace_init_cmdlines();
|
||||
|
||||
if (trace_boot_clock) {
|
||||
ret = tracing_set_clock(&global_trace, trace_boot_clock);
|
||||
if (ret < 0)
|
||||
pr_warning("Trace clock %s not defined, going back to default\n",
|
||||
trace_boot_clock);
|
||||
}
|
||||
|
||||
/*
|
||||
* register_tracer() might reference current_trace, so it
|
||||
* needs to be set before we register anything. This is
|
||||
|
Loading…
Reference in New Issue
Block a user