Skip to content

Commit e1e232c

Browse files
committed
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 <[email protected]> Tested-by: Thomas Gleixner <[email protected]> Reviewed-by: Thomas Gleixner <[email protected]> Appreciated-by: Thomas Gleixner <[email protected]> Signed-off-by: Steven Rostedt <[email protected]>
1 parent 43fe989 commit e1e232c

File tree

1 file changed

+45
-16
lines changed

1 file changed

+45
-16
lines changed

kernel/trace/trace.c

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,17 @@ static int __init set_trace_boot_options(char *str)
181181
}
182182
__setup("trace_options=", set_trace_boot_options);
183183

184+
static char trace_boot_clock_buf[MAX_TRACER_SIZE] __initdata;
185+
static char *trace_boot_clock __initdata;
186+
187+
static int __init set_trace_boot_clock(char *str)
188+
{
189+
strlcpy(trace_boot_clock_buf, str, MAX_TRACER_SIZE);
190+
trace_boot_clock = trace_boot_clock_buf;
191+
return 0;
192+
}
193+
__setup("trace_clock=", set_trace_boot_clock);
194+
184195

185196
unsigned long long ns2usecs(cycle_t nsec)
186197
{
@@ -4746,25 +4757,10 @@ static int tracing_clock_show(struct seq_file *m, void *v)
47464757
return 0;
47474758
}
47484759

4749-
static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
4750-
size_t cnt, loff_t *fpos)
4760+
static int tracing_set_clock(struct trace_array *tr, const char *clockstr)
47514761
{
4752-
struct seq_file *m = filp->private_data;
4753-
struct trace_array *tr = m->private;
4754-
char buf[64];
4755-
const char *clockstr;
47564762
int i;
47574763

4758-
if (cnt >= sizeof(buf))
4759-
return -EINVAL;
4760-
4761-
if (copy_from_user(&buf, ubuf, cnt))
4762-
return -EFAULT;
4763-
4764-
buf[cnt] = 0;
4765-
4766-
clockstr = strstrip(buf);
4767-
47684764
for (i = 0; i < ARRAY_SIZE(trace_clocks); i++) {
47694765
if (strcmp(trace_clocks[i].name, clockstr) == 0)
47704766
break;
@@ -4792,6 +4788,32 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
47924788

47934789
mutex_unlock(&trace_types_lock);
47944790

4791+
return 0;
4792+
}
4793+
4794+
static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
4795+
size_t cnt, loff_t *fpos)
4796+
{
4797+
struct seq_file *m = filp->private_data;
4798+
struct trace_array *tr = m->private;
4799+
char buf[64];
4800+
const char *clockstr;
4801+
int ret;
4802+
4803+
if (cnt >= sizeof(buf))
4804+
return -EINVAL;
4805+
4806+
if (copy_from_user(&buf, ubuf, cnt))
4807+
return -EFAULT;
4808+
4809+
buf[cnt] = 0;
4810+
4811+
clockstr = strstrip(buf);
4812+
4813+
ret = tracing_set_clock(tr, clockstr);
4814+
if (ret)
4815+
return ret;
4816+
47954817
*fpos += cnt;
47964818

47974819
return cnt;
@@ -6574,6 +6596,13 @@ __init static int tracer_alloc_buffers(void)
65746596

65756597
trace_init_cmdlines();
65766598

6599+
if (trace_boot_clock) {
6600+
ret = tracing_set_clock(&global_trace, trace_boot_clock);
6601+
if (ret < 0)
6602+
pr_warning("Trace clock %s not defined, going back to default\n",
6603+
trace_boot_clock);
6604+
}
6605+
65776606
/*
65786607
* register_tracer() might reference current_trace, so it
65796608
* needs to be set before we register anything. This is

0 commit comments

Comments
 (0)