提交 4e3c3333 编写于 作者: I Ingo Molnar 提交者: Thomas Gleixner

ftrace: fix time offset

fix time offset calculations and ordering, plus make code more consistent.
Signed-off-by: NIngo Molnar <mingo@elte.hu>
Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
上级 77a2b37d
...@@ -120,7 +120,7 @@ static DEFINE_SPINLOCK(ftrace_max_lock); ...@@ -120,7 +120,7 @@ static DEFINE_SPINLOCK(ftrace_max_lock);
* structure. (this way the maximum trace is permanently saved, * structure. (this way the maximum trace is permanently saved,
* for later retrieval via /debugfs/tracing/latency_trace) * for later retrieval via /debugfs/tracing/latency_trace)
*/ */
static void notrace static notrace void
__update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
{ {
struct trace_array_cpu *data = tr->data[cpu]; struct trace_array_cpu *data = tr->data[cpu];
...@@ -333,15 +333,16 @@ void unregister_tracer(struct tracer *type) ...@@ -333,15 +333,16 @@ void unregister_tracer(struct tracer *type)
mutex_unlock(&trace_types_lock); mutex_unlock(&trace_types_lock);
} }
void notrace tracing_reset(struct trace_array_cpu *data) notrace void tracing_reset(struct trace_array_cpu *data)
{ {
data->trace_idx = 0; data->trace_idx = 0;
data->trace_current = head_page(data); data->trace_current = head_page(data);
data->trace_current_idx = 0; data->trace_current_idx = 0;
data->time_offset = 0;
} }
#ifdef CONFIG_FTRACE #ifdef CONFIG_FTRACE
static void notrace static notrace void
function_trace_call(unsigned long ip, unsigned long parent_ip) function_trace_call(unsigned long ip, unsigned long parent_ip)
{ {
struct trace_array *tr = &global_trace; struct trace_array *tr = &global_trace;
...@@ -398,7 +399,7 @@ static void trace_init_cmdlines(void) ...@@ -398,7 +399,7 @@ static void trace_init_cmdlines(void)
notrace void trace_stop_cmdline_recording(void); notrace void trace_stop_cmdline_recording(void);
static void notrace trace_save_cmdline(struct task_struct *tsk) static notrace void trace_save_cmdline(struct task_struct *tsk)
{ {
unsigned map; unsigned map;
unsigned idx; unsigned idx;
...@@ -624,6 +625,7 @@ static void *find_next_entry_inc(struct trace_iterator *iter) ...@@ -624,6 +625,7 @@ static void *find_next_entry_inc(struct trace_iterator *iter)
iter->idx++; iter->idx++;
iter->next_idx[next_cpu]++; iter->next_idx[next_cpu]++;
iter->next_page_idx[next_cpu]++; iter->next_page_idx[next_cpu]++;
if (iter->next_page_idx[next_cpu] >= ENTRIES_PER_PAGE) { if (iter->next_page_idx[next_cpu] >= ENTRIES_PER_PAGE) {
struct trace_array_cpu *data = iter->tr->data[next_cpu]; struct trace_array_cpu *data = iter->tr->data[next_cpu];
...@@ -635,19 +637,21 @@ static void *find_next_entry_inc(struct trace_iterator *iter) ...@@ -635,19 +637,21 @@ static void *find_next_entry_inc(struct trace_iterator *iter)
data->trace_pages.next; data->trace_pages.next;
} }
} }
iter->prev_ent = iter->ent;
iter->prev_cpu = iter->cpu;
iter->ent = next; iter->ent = next;
iter->cpu = next_cpu; iter->cpu = next_cpu;
return next ? iter : NULL; return next ? iter : NULL;
} }
static void notrace * static notrace void *s_next(struct seq_file *m, void *v, loff_t *pos)
s_next(struct seq_file *m, void *v, loff_t *pos)
{ {
struct trace_iterator *iter = m->private; struct trace_iterator *iter = m->private;
void *ent;
void *last_ent = iter->ent; void *last_ent = iter->ent;
int i = (int)*pos; int i = (int)*pos;
void *ent;
(*pos)++; (*pos)++;
...@@ -693,6 +697,8 @@ static void *s_start(struct seq_file *m, loff_t *pos) ...@@ -693,6 +697,8 @@ static void *s_start(struct seq_file *m, loff_t *pos)
iter->ent = NULL; iter->ent = NULL;
iter->cpu = 0; iter->cpu = 0;
iter->idx = -1; iter->idx = -1;
iter->prev_ent = NULL;
iter->prev_cpu = -1;
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
iter->next_idx[i] = 0; iter->next_idx[i] = 0;
...@@ -752,7 +758,7 @@ seq_print_sym_offset(struct seq_file *m, const char *fmt, unsigned long address) ...@@ -752,7 +758,7 @@ seq_print_sym_offset(struct seq_file *m, const char *fmt, unsigned long address)
# define IP_FMT "%016lx" # define IP_FMT "%016lx"
#endif #endif
static void notrace static notrace void
seq_print_ip_sym(struct seq_file *m, unsigned long ip, unsigned long sym_flags) seq_print_ip_sym(struct seq_file *m, unsigned long ip, unsigned long sym_flags)
{ {
if (!ip) { if (!ip) {
...@@ -769,7 +775,7 @@ seq_print_ip_sym(struct seq_file *m, unsigned long ip, unsigned long sym_flags) ...@@ -769,7 +775,7 @@ seq_print_ip_sym(struct seq_file *m, unsigned long ip, unsigned long sym_flags)
seq_printf(m, " <" IP_FMT ">", ip); seq_printf(m, " <" IP_FMT ">", ip);
} }
static void notrace print_lat_help_header(struct seq_file *m) static notrace void print_lat_help_header(struct seq_file *m)
{ {
seq_puts(m, "# _------=> CPU# \n"); seq_puts(m, "# _------=> CPU# \n");
seq_puts(m, "# / _-----=> irqs-off \n"); seq_puts(m, "# / _-----=> irqs-off \n");
...@@ -782,14 +788,14 @@ static void notrace print_lat_help_header(struct seq_file *m) ...@@ -782,14 +788,14 @@ static void notrace print_lat_help_header(struct seq_file *m)
seq_puts(m, "# \\ / ||||| \\ | / \n"); seq_puts(m, "# \\ / ||||| \\ | / \n");
} }
static void notrace print_func_help_header(struct seq_file *m) static notrace void print_func_help_header(struct seq_file *m)
{ {
seq_puts(m, "# TASK-PID CPU# TIMESTAMP FUNCTION\n"); seq_puts(m, "# TASK-PID CPU# TIMESTAMP FUNCTION\n");
seq_puts(m, "# | | | | |\n"); seq_puts(m, "# | | | | |\n");
} }
static void notrace static notrace void
print_trace_header(struct seq_file *m, struct trace_iterator *iter) print_trace_header(struct seq_file *m, struct trace_iterator *iter)
{ {
unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
...@@ -858,7 +864,7 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter) ...@@ -858,7 +864,7 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter)
seq_puts(m, "\n"); seq_puts(m, "\n");
} }
static void notrace static notrace void
lat_print_generic(struct seq_file *m, struct trace_entry *entry, int cpu) lat_print_generic(struct seq_file *m, struct trace_entry *entry, int cpu)
{ {
int hardirq, softirq; int hardirq, softirq;
...@@ -895,7 +901,7 @@ lat_print_generic(struct seq_file *m, struct trace_entry *entry, int cpu) ...@@ -895,7 +901,7 @@ lat_print_generic(struct seq_file *m, struct trace_entry *entry, int cpu)
unsigned long preempt_mark_thresh = 100; unsigned long preempt_mark_thresh = 100;
static void notrace static notrace void
lat_print_timestamp(struct seq_file *m, unsigned long long abs_usecs, lat_print_timestamp(struct seq_file *m, unsigned long long abs_usecs,
unsigned long rel_usecs) unsigned long rel_usecs)
{ {
...@@ -910,7 +916,7 @@ lat_print_timestamp(struct seq_file *m, unsigned long long abs_usecs, ...@@ -910,7 +916,7 @@ lat_print_timestamp(struct seq_file *m, unsigned long long abs_usecs,
static const char state_to_char[] = TASK_STATE_TO_CHAR_STR; static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
static void notrace static notrace void
print_lat_fmt(struct seq_file *m, struct trace_iterator *iter, print_lat_fmt(struct seq_file *m, struct trace_iterator *iter,
unsigned int trace_idx, int cpu) unsigned int trace_idx, int cpu)
{ {
...@@ -966,20 +972,50 @@ print_lat_fmt(struct seq_file *m, struct trace_iterator *iter, ...@@ -966,20 +972,50 @@ print_lat_fmt(struct seq_file *m, struct trace_iterator *iter,
} }
} }
static void notrace static notrace void sync_time_offset(struct trace_iterator *iter)
{
struct trace_array_cpu *prev_array, *array;
struct trace_entry *prev_entry, *entry;
cycle_t prev_t, t;
entry = iter->ent;
prev_entry = iter->prev_ent;
if (!prev_entry)
return;
prev_array = iter->tr->data[iter->prev_cpu];
array = iter->tr->data[iter->cpu];
prev_t = prev_entry->t + prev_array->time_offset;
t = entry->t + array->time_offset;
/*
* If time goes backwards we increase the offset of
* the current array, to not have observable time warps.
* This will quickly synchronize the time offsets of
* multiple CPUs:
*/
if (t < prev_t)
array->time_offset += prev_t - t;
}
static notrace void
print_trace_fmt(struct seq_file *m, struct trace_iterator *iter) print_trace_fmt(struct seq_file *m, struct trace_iterator *iter)
{ {
unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK); unsigned long sym_flags = (trace_flags & TRACE_ITER_SYM_MASK);
struct trace_entry *entry = iter->ent; struct trace_entry *entry;
unsigned long usec_rem; unsigned long usec_rem;
unsigned long long t; unsigned long long t;
unsigned long secs; unsigned long secs;
char *comm; char *comm;
int S; int S;
sync_time_offset(iter);
entry = iter->ent;
comm = trace_find_cmdline(iter->ent->pid); comm = trace_find_cmdline(iter->ent->pid);
t = ns2usecs(entry->t); t = ns2usecs(entry->t + iter->tr->data[iter->cpu]->time_offset);
usec_rem = do_div(t, 1000000ULL); usec_rem = do_div(t, 1000000ULL);
secs = (unsigned long)t; secs = (unsigned long)t;
...@@ -1158,7 +1194,7 @@ static int tracing_lt_open(struct inode *inode, struct file *file) ...@@ -1158,7 +1194,7 @@ static int tracing_lt_open(struct inode *inode, struct file *file)
} }
static void notrace * static notrace void *
t_next(struct seq_file *m, void *v, loff_t *pos) t_next(struct seq_file *m, void *v, loff_t *pos)
{ {
struct tracer *t = m->private; struct tracer *t = m->private;
...@@ -1374,8 +1410,7 @@ tracing_ctrl_read(struct file *filp, char __user *ubuf, ...@@ -1374,8 +1410,7 @@ tracing_ctrl_read(struct file *filp, char __user *ubuf,
int r; int r;
r = sprintf(buf, "%ld\n", tr->ctrl); r = sprintf(buf, "%ld\n", tr->ctrl);
return simple_read_from_buffer(ubuf, cnt, ppos, return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
buf, r);
} }
static ssize_t static ssize_t
......
...@@ -56,6 +56,8 @@ struct trace_array_cpu { ...@@ -56,6 +56,8 @@ struct trace_array_cpu {
void *trace_current; void *trace_current;
struct list_head trace_pages; struct list_head trace_pages;
atomic_t disabled; atomic_t disabled;
cycle_t time_offset;
/* these fields get copied into max-trace: */ /* these fields get copied into max-trace: */
unsigned trace_current_idx; unsigned trace_current_idx;
unsigned long trace_idx; unsigned long trace_idx;
...@@ -114,14 +116,19 @@ struct tracer { ...@@ -114,14 +116,19 @@ struct tracer {
struct trace_iterator { struct trace_iterator {
struct trace_array *tr; struct trace_array *tr;
struct tracer *trace; struct tracer *trace;
struct trace_entry *ent; struct trace_entry *ent;
int cpu;
struct trace_entry *prev_ent;
int prev_cpu;
unsigned long iter_flags; unsigned long iter_flags;
loff_t pos; loff_t pos;
unsigned long next_idx[NR_CPUS]; unsigned long next_idx[NR_CPUS];
struct list_head *next_page[NR_CPUS]; struct list_head *next_page[NR_CPUS];
unsigned next_page_idx[NR_CPUS]; unsigned next_page_idx[NR_CPUS];
long idx; long idx;
int cpu;
}; };
void notrace tracing_reset(struct trace_array_cpu *data); void notrace tracing_reset(struct trace_array_cpu *data);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册