Commit c7aafc54 authored by Ingo Molnar's avatar Ingo Molnar Committed by Thomas Gleixner

ftrace: cleanups

factor out code and clean it up.
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 60a11774
...@@ -69,7 +69,7 @@ extern void ftrace_caller(void); ...@@ -69,7 +69,7 @@ extern void ftrace_caller(void);
extern void ftrace_call(void); extern void ftrace_call(void);
extern void mcount_call(void); extern void mcount_call(void);
#else #else
# define ftrace_force_update() do { } while (0) # define ftrace_force_update() ({ 0; })
#endif #endif
static inline void tracer_disable(void) static inline void tracer_disable(void)
......
...@@ -1152,10 +1152,10 @@ static int __init notrace ftrace_dynamic_init(void) ...@@ -1152,10 +1152,10 @@ static int __init notrace ftrace_dynamic_init(void)
core_initcall(ftrace_dynamic_init); core_initcall(ftrace_dynamic_init);
#else #else
# define ftrace_startup() do { } while (0) # define ftrace_startup() do { } while (0)
# define ftrace_shutdown() do { } while (0) # define ftrace_shutdown() do { } while (0)
# define ftrace_startup_sysctl() do { } while (0) # define ftrace_startup_sysctl() do { } while (0)
# define ftrace_shutdown_sysctl() do { } while (0) # define ftrace_shutdown_sysctl() do { } while (0)
#endif /* CONFIG_DYNAMIC_FTRACE */ #endif /* CONFIG_DYNAMIC_FTRACE */
/** /**
......
...@@ -142,12 +142,59 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) ...@@ -142,12 +142,59 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
tracing_record_cmdline(current); tracing_record_cmdline(current);
} }
void check_pages(struct trace_array_cpu *data)
{
struct page *page, *tmp;
BUG_ON(data->trace_pages.next->prev != &data->trace_pages);
BUG_ON(data->trace_pages.prev->next != &data->trace_pages);
list_for_each_entry_safe(page, tmp, &data->trace_pages, lru) {
BUG_ON(page->lru.next->prev != &page->lru);
BUG_ON(page->lru.prev->next != &page->lru);
}
}
void *head_page(struct trace_array_cpu *data)
{
struct page *page;
check_pages(data);
if (list_empty(&data->trace_pages))
return NULL;
page = list_entry(data->trace_pages.next, struct page, lru);
BUG_ON(&page->lru == &data->trace_pages);
return page_address(page);
}
notrace static void
flip_trace(struct trace_array_cpu *tr1, struct trace_array_cpu *tr2)
{
struct list_head flip_pages;
INIT_LIST_HEAD(&flip_pages);
tr1->trace_current = NULL;
memcpy(&tr1->trace_current_idx, &tr2->trace_current_idx,
sizeof(struct trace_array_cpu) -
offsetof(struct trace_array_cpu, trace_current_idx));
check_pages(tr1);
check_pages(tr2);
list_splice_init(&tr1->trace_pages, &flip_pages);
list_splice_init(&tr2->trace_pages, &tr1->trace_pages);
list_splice_init(&flip_pages, &tr2->trace_pages);
BUG_ON(!list_empty(&flip_pages));
check_pages(tr1);
check_pages(tr2);
}
notrace void 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; struct trace_array_cpu *data;
void *save_trace;
struct list_head save_pages;
int i; int i;
WARN_ON_ONCE(!irqs_disabled()); WARN_ON_ONCE(!irqs_disabled());
...@@ -155,11 +202,7 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) ...@@ -155,11 +202,7 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
/* clear out all the previous traces */ /* clear out all the previous traces */
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
data = tr->data[i]; data = tr->data[i];
save_trace = max_tr.data[i]->trace; flip_trace(max_tr.data[i], data);
save_pages = max_tr.data[i]->trace_pages;
memcpy(max_tr.data[i], data, sizeof(*data));
data->trace = save_trace;
data->trace_pages = save_pages;
tracing_reset(data); tracing_reset(data);
} }
...@@ -177,8 +220,6 @@ notrace void ...@@ -177,8 +220,6 @@ notrace void
update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu) update_max_tr_single(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];
void *save_trace;
struct list_head save_pages;
int i; int i;
WARN_ON_ONCE(!irqs_disabled()); WARN_ON_ONCE(!irqs_disabled());
...@@ -186,11 +227,8 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu) ...@@ -186,11 +227,8 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
for_each_possible_cpu(i) for_each_possible_cpu(i)
tracing_reset(max_tr.data[i]); tracing_reset(max_tr.data[i]);
save_trace = max_tr.data[cpu]->trace; flip_trace(max_tr.data[cpu], data);
save_pages = max_tr.data[cpu]->trace_pages;
memcpy(max_tr.data[cpu], data, sizeof(*data));
data->trace = save_trace;
data->trace_pages = save_pages;
tracing_reset(data); tracing_reset(data);
__update_max_tr(tr, tsk, cpu); __update_max_tr(tr, tsk, cpu);
...@@ -234,9 +272,9 @@ int register_tracer(struct tracer *type) ...@@ -234,9 +272,9 @@ int register_tracer(struct tracer *type)
* If we fail, we do not register this tracer. * If we fail, we do not register this tracer.
*/ */
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
if (!data->trace)
continue;
data = tr->data[i]; data = tr->data[i];
if (!head_page(data))
continue;
tracing_reset(data); tracing_reset(data);
} }
current_trace = type; current_trace = type;
...@@ -298,7 +336,7 @@ void unregister_tracer(struct tracer *type) ...@@ -298,7 +336,7 @@ void unregister_tracer(struct tracer *type)
void notrace tracing_reset(struct trace_array_cpu *data) void notrace tracing_reset(struct trace_array_cpu *data)
{ {
data->trace_idx = 0; data->trace_idx = 0;
data->trace_current = data->trace; data->trace_current = head_page(data);
data->trace_current_idx = 0; data->trace_current_idx = 0;
} }
...@@ -425,26 +463,31 @@ notrace void tracing_record_cmdline(struct task_struct *tsk) ...@@ -425,26 +463,31 @@ notrace void tracing_record_cmdline(struct task_struct *tsk)
} }
static inline notrace struct trace_entry * static inline notrace struct trace_entry *
tracing_get_trace_entry(struct trace_array *tr, tracing_get_trace_entry(struct trace_array *tr, struct trace_array_cpu *data)
struct trace_array_cpu *data)
{ {
unsigned long idx, idx_next; unsigned long idx, idx_next;
struct trace_entry *entry; struct trace_entry *entry;
struct page *page;
struct list_head *next; struct list_head *next;
struct page *page;
data->trace_idx++; data->trace_idx++;
idx = data->trace_current_idx; idx = data->trace_current_idx;
idx_next = idx + 1; idx_next = idx + 1;
BUG_ON(idx * TRACE_ENTRY_SIZE >= PAGE_SIZE);
entry = data->trace_current + idx * TRACE_ENTRY_SIZE; entry = data->trace_current + idx * TRACE_ENTRY_SIZE;
if (unlikely(idx_next >= ENTRIES_PER_PAGE)) { if (unlikely(idx_next >= ENTRIES_PER_PAGE)) {
page = virt_to_page(data->trace_current); page = virt_to_page(data->trace_current);
if (unlikely(&page->lru == data->trace_pages.prev)) /*
next = data->trace_pages.next; * Roundrobin - but skip the head (which is not a real page):
else */
next = page->lru.next; next = page->lru.next;
if (unlikely(next == &data->trace_pages))
next = next->next;
BUG_ON(next == &data->trace_pages);
page = list_entry(next, struct page, lru); page = list_entry(next, struct page, lru);
data->trace_current = page_address(page); data->trace_current = page_address(page);
idx_next = 0; idx_next = 0;
...@@ -456,18 +499,17 @@ tracing_get_trace_entry(struct trace_array *tr, ...@@ -456,18 +499,17 @@ tracing_get_trace_entry(struct trace_array *tr,
} }
static inline notrace void static inline notrace void
tracing_generic_entry_update(struct trace_entry *entry, tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags)
unsigned long flags)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
unsigned long pc; unsigned long pc;
pc = preempt_count(); pc = preempt_count();
entry->idx = atomic_inc_return(&tracer_counter); entry->idx = atomic_inc_return(&tracer_counter);
entry->preempt_count = pc & 0xff; entry->preempt_count = pc & 0xff;
entry->pid = tsk->pid; entry->pid = tsk->pid;
entry->t = now(raw_smp_processor_id()); entry->t = now(raw_smp_processor_id());
entry->flags = (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | entry->flags = (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) |
((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) | ((pc & HARDIRQ_MASK) ? TRACE_FLAG_HARDIRQ : 0) |
((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) | ((pc & SOFTIRQ_MASK) ? TRACE_FLAG_SOFTIRQ : 0) |
...@@ -476,16 +518,15 @@ tracing_generic_entry_update(struct trace_entry *entry, ...@@ -476,16 +518,15 @@ tracing_generic_entry_update(struct trace_entry *entry,
notrace void notrace void
ftrace(struct trace_array *tr, struct trace_array_cpu *data, ftrace(struct trace_array *tr, struct trace_array_cpu *data,
unsigned long ip, unsigned long parent_ip, unsigned long ip, unsigned long parent_ip, unsigned long flags)
unsigned long flags)
{ {
struct trace_entry *entry; struct trace_entry *entry;
entry = tracing_get_trace_entry(tr, data); entry = tracing_get_trace_entry(tr, data);
tracing_generic_entry_update(entry, flags); tracing_generic_entry_update(entry, flags);
entry->type = TRACE_FN; entry->type = TRACE_FN;
entry->fn.ip = ip; entry->fn.ip = ip;
entry->fn.parent_ip = parent_ip; entry->fn.parent_ip = parent_ip;
} }
notrace void notrace void
...@@ -496,7 +537,7 @@ tracing_sched_switch_trace(struct trace_array *tr, ...@@ -496,7 +537,7 @@ tracing_sched_switch_trace(struct trace_array *tr,
{ {
struct trace_entry *entry; struct trace_entry *entry;
entry = tracing_get_trace_entry(tr, data); entry = tracing_get_trace_entry(tr, data);
tracing_generic_entry_update(entry, flags); tracing_generic_entry_update(entry, flags);
entry->type = TRACE_CTX; entry->type = TRACE_CTX;
entry->ctx.prev_pid = prev->pid; entry->ctx.prev_pid = prev->pid;
...@@ -540,6 +581,8 @@ trace_entry_idx(struct trace_array *tr, struct trace_array_cpu *data, ...@@ -540,6 +581,8 @@ trace_entry_idx(struct trace_array *tr, struct trace_array_cpu *data,
} }
page = list_entry(iter->next_page[cpu], struct page, lru); page = list_entry(iter->next_page[cpu], struct page, lru);
BUG_ON(&data->trace_pages == &page->lru);
array = page_address(page); array = page_address(page);
return &array[iter->next_page_idx[cpu]]; return &array[iter->next_page_idx[cpu]];
...@@ -554,7 +597,7 @@ find_next_entry(struct trace_iterator *iter, int *ent_cpu) ...@@ -554,7 +597,7 @@ find_next_entry(struct trace_iterator *iter, int *ent_cpu)
int cpu; int cpu;
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
if (!tr->data[cpu]->trace) if (!head_page(tr->data[cpu]))
continue; continue;
ent = trace_entry_idx(tr, tr->data[cpu], iter, cpu); ent = trace_entry_idx(tr, tr->data[cpu], iter, cpu);
if (ent && if (ent &&
...@@ -762,7 +805,7 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter) ...@@ -762,7 +805,7 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter)
name = type->name; name = type->name;
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
if (tr->data[cpu]->trace) { if (head_page(tr->data[cpu])) {
total += tr->data[cpu]->trace_idx; total += tr->data[cpu]->trace_idx;
if (tr->data[cpu]->trace_idx > tr->entries) if (tr->data[cpu]->trace_idx > tr->entries)
entries += tr->entries; entries += tr->entries;
...@@ -975,8 +1018,7 @@ static int trace_empty(struct trace_iterator *iter) ...@@ -975,8 +1018,7 @@ static int trace_empty(struct trace_iterator *iter)
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
data = iter->tr->data[cpu]; data = iter->tr->data[cpu];
if (data->trace && if (head_page(data) && data->trace_idx)
data->trace_idx)
return 0; return 0;
} }
return 1; return 1;
...@@ -1576,9 +1618,9 @@ static struct tracer no_tracer __read_mostly = ...@@ -1576,9 +1618,9 @@ static struct tracer no_tracer __read_mostly =
static int trace_alloc_page(void) static int trace_alloc_page(void)
{ {
struct trace_array_cpu *data; struct trace_array_cpu *data;
void *array;
struct page *page, *tmp; struct page *page, *tmp;
LIST_HEAD(pages); LIST_HEAD(pages);
void *array;
int i; int i;
/* first allocate a page for each CPU */ /* first allocate a page for each CPU */
...@@ -1610,14 +1652,14 @@ static int trace_alloc_page(void) ...@@ -1610,14 +1652,14 @@ static int trace_alloc_page(void)
for_each_possible_cpu(i) { for_each_possible_cpu(i) {
data = global_trace.data[i]; data = global_trace.data[i];
page = list_entry(pages.next, struct page, lru); page = list_entry(pages.next, struct page, lru);
list_del(&page->lru); list_del_init(&page->lru);
list_add_tail(&page->lru, &data->trace_pages); list_add_tail(&page->lru, &data->trace_pages);
ClearPageLRU(page); ClearPageLRU(page);
#ifdef CONFIG_TRACER_MAX_TRACE #ifdef CONFIG_TRACER_MAX_TRACE
data = max_tr.data[i]; data = max_tr.data[i];
page = list_entry(pages.next, struct page, lru); page = list_entry(pages.next, struct page, lru);
list_del(&page->lru); list_del_init(&page->lru);
list_add_tail(&page->lru, &data->trace_pages); list_add_tail(&page->lru, &data->trace_pages);
SetPageLRU(page); SetPageLRU(page);
#endif #endif
...@@ -1628,7 +1670,7 @@ static int trace_alloc_page(void) ...@@ -1628,7 +1670,7 @@ static int trace_alloc_page(void)
free_pages: free_pages:
list_for_each_entry_safe(page, tmp, &pages, lru) { list_for_each_entry_safe(page, tmp, &pages, lru) {
list_del(&page->lru); list_del_init(&page->lru);
__free_page(page); __free_page(page);
} }
return -ENOMEM; return -ENOMEM;
...@@ -1654,7 +1696,6 @@ __init static int tracer_alloc_buffers(void) ...@@ -1654,7 +1696,6 @@ __init static int tracer_alloc_buffers(void)
"for trace buffer!\n"); "for trace buffer!\n");
goto free_buffers; goto free_buffers;
} }
data->trace = array;
/* set the array to the list */ /* set the array to the list */
INIT_LIST_HEAD(&data->trace_pages); INIT_LIST_HEAD(&data->trace_pages);
...@@ -1671,7 +1712,6 @@ __init static int tracer_alloc_buffers(void) ...@@ -1671,7 +1712,6 @@ __init static int tracer_alloc_buffers(void)
"for trace buffer!\n"); "for trace buffer!\n");
goto free_buffers; goto free_buffers;
} }
max_tr.data[i]->trace = array;
INIT_LIST_HEAD(&max_tr.data[i]->trace_pages); INIT_LIST_HEAD(&max_tr.data[i]->trace_pages);
page = virt_to_page(array); page = virt_to_page(array);
...@@ -1716,24 +1756,22 @@ __init static int tracer_alloc_buffers(void) ...@@ -1716,24 +1756,22 @@ __init static int tracer_alloc_buffers(void)
struct page *page, *tmp; struct page *page, *tmp;
struct trace_array_cpu *data = global_trace.data[i]; struct trace_array_cpu *data = global_trace.data[i];
if (data && data->trace) { if (data) {
list_for_each_entry_safe(page, tmp, list_for_each_entry_safe(page, tmp,
&data->trace_pages, lru) { &data->trace_pages, lru) {
list_del(&page->lru); list_del_init(&page->lru);
__free_page(page); __free_page(page);
} }
data->trace = NULL;
} }
#ifdef CONFIG_TRACER_MAX_TRACE #ifdef CONFIG_TRACER_MAX_TRACE
data = max_tr.data[i]; data = max_tr.data[i];
if (data && data->trace) { if (data) {
list_for_each_entry_safe(page, tmp, list_for_each_entry_safe(page, tmp,
&data->trace_pages, lru) { &data->trace_pages, lru) {
list_del(&page->lru); list_del_init(&page->lru);
__free_page(page); __free_page(page);
} }
data->trace = NULL;
} }
#endif #endif
} }
......
...@@ -53,12 +53,12 @@ struct trace_entry { ...@@ -53,12 +53,12 @@ struct trace_entry {
* the trace, etc.) * the trace, etc.)
*/ */
struct trace_array_cpu { struct trace_array_cpu {
void *trace;
void *trace_current; void *trace_current;
unsigned trace_current_idx;
struct list_head trace_pages; struct list_head trace_pages;
unsigned long trace_idx;
atomic_t disabled; atomic_t disabled;
/* these fields get copied into max-trace: */
unsigned trace_current_idx;
unsigned long trace_idx;
unsigned long saved_latency; unsigned long saved_latency;
unsigned long critical_start; unsigned long critical_start;
unsigned long critical_end; unsigned long critical_end;
...@@ -216,4 +216,6 @@ extern int trace_selftest_startup_sched_switch(struct tracer *trace, ...@@ -216,4 +216,6 @@ extern int trace_selftest_startup_sched_switch(struct tracer *trace,
#endif #endif
#endif /* CONFIG_FTRACE_STARTUP_TEST */ #endif /* CONFIG_FTRACE_STARTUP_TEST */
extern void *head_page(struct trace_array_cpu *data);
#endif /* _LINUX_KERNEL_TRACE_H */ #endif /* _LINUX_KERNEL_TRACE_H */
...@@ -144,7 +144,7 @@ check_critical_timing(struct trace_array *tr, ...@@ -144,7 +144,7 @@ check_critical_timing(struct trace_array *tr,
if (!report_latency(delta)) if (!report_latency(delta))
goto out; goto out;
spin_lock(&max_trace_lock); spin_lock_irqsave(&max_trace_lock, flags);
/* check if we are still the max latency */ /* check if we are still the max latency */
if (!report_latency(delta)) if (!report_latency(delta))
...@@ -165,32 +165,24 @@ check_critical_timing(struct trace_array *tr, ...@@ -165,32 +165,24 @@ check_critical_timing(struct trace_array *tr,
update_max_tr_single(tr, current, cpu); update_max_tr_single(tr, current, cpu);
if (tracing_thresh) if (tracing_thresh) {
printk(KERN_INFO "(%16s-%-5d|#%d): %lu us critical section " printk(KERN_INFO "(%16s-%-5d|#%d):"
"violates %lu us threshold.\n" " %lu us critical section violates %lu us threshold.\n",
" => started at timestamp %lu: ",
current->comm, current->pid, current->comm, current->pid,
raw_smp_processor_id(), raw_smp_processor_id(),
latency, nsecs_to_usecs(tracing_thresh), t0); latency, nsecs_to_usecs(tracing_thresh));
else } else {
printk(KERN_INFO "(%16s-%-5d|#%d):" printk(KERN_INFO "(%16s-%-5d|#%d):"
" new %lu us maximum-latency " " new %lu us maximum-latency critical section.\n",
"critical section.\n => started at timestamp %lu: ",
current->comm, current->pid, current->comm, current->pid,
raw_smp_processor_id(), raw_smp_processor_id(),
latency, t0); latency);
}
print_symbol(KERN_CONT "<%s>\n", data->critical_start);
printk(KERN_CONT " => ended at timestamp %lu: ", t1);
print_symbol(KERN_CONT "<%s>\n", data->critical_end);
dump_stack();
t1 = nsecs_to_usecs(now(cpu));
printk(KERN_CONT " => dump-end timestamp %lu\n\n", t1);
max_sequence++; max_sequence++;
out_unlock: out_unlock:
spin_unlock(&max_trace_lock); spin_unlock_irqrestore(&max_trace_lock, flags);
out: out:
data->critical_sequence = max_sequence; data->critical_sequence = max_sequence;
...@@ -216,7 +208,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip) ...@@ -216,7 +208,7 @@ start_critical_timing(unsigned long ip, unsigned long parent_ip)
cpu = raw_smp_processor_id(); cpu = raw_smp_processor_id();
data = tr->data[cpu]; data = tr->data[cpu];
if (unlikely(!data) || unlikely(!data->trace) || if (unlikely(!data) || unlikely(!head_page(data)) ||
atomic_read(&data->disabled)) atomic_read(&data->disabled))
return; return;
...@@ -256,7 +248,7 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip) ...@@ -256,7 +248,7 @@ stop_critical_timing(unsigned long ip, unsigned long parent_ip)
cpu = raw_smp_processor_id(); cpu = raw_smp_processor_id();
data = tr->data[cpu]; data = tr->data[cpu];
if (unlikely(!data) || unlikely(!data->trace) || if (unlikely(!data) || unlikely(!head_page(data)) ||
!data->critical_start || atomic_read(&data->disabled)) !data->critical_start || atomic_read(&data->disabled))
return; return;
......
...@@ -107,24 +107,18 @@ wakeup_sched_switch(struct task_struct *prev, struct task_struct *next) ...@@ -107,24 +107,18 @@ wakeup_sched_switch(struct task_struct *prev, struct task_struct *next)
update_max_tr(tr, wakeup_task, wakeup_cpu); update_max_tr(tr, wakeup_task, wakeup_cpu);
if (tracing_thresh) { if (tracing_thresh) {
printk(KERN_INFO "(%16s-%-5d|#%d): %lu us wakeup latency " printk(KERN_INFO "(%16s-%-5d|#%d):"
"violates %lu us threshold.\n" " %lu us wakeup latency violates %lu us threshold.\n",
" => started at timestamp %lu: ",
wakeup_task->comm, wakeup_task->pid, wakeup_task->comm, wakeup_task->pid,
raw_smp_processor_id(), raw_smp_processor_id(),
latency, nsecs_to_usecs(tracing_thresh), t0); latency, nsecs_to_usecs(tracing_thresh));
} else { } else {
printk(KERN_INFO "(%16s-%-5d|#%d): new %lu us maximum " printk(KERN_INFO "(%16s-%-5d|#%d):"
"wakeup latency.\n => started at timestamp %lu: ", " new %lu us maximum wakeup latency.\n",
wakeup_task->comm, wakeup_task->pid, wakeup_task->comm, wakeup_task->pid,
cpu, latency, t0); cpu, latency);
} }
printk(KERN_CONT " ended at timestamp %lu: ", t1);
dump_stack();
t1 = nsecs_to_usecs(now(cpu));
printk(KERN_CONT " dump-end timestamp %lu\n\n", t1);
out_unlock: out_unlock:
__wakeup_reset(tr); __wakeup_reset(tr);
spin_unlock_irqrestore(&wakeup_lock, flags); spin_unlock_irqrestore(&wakeup_lock, flags);
......
/* Include in trace.c */ /* Include in trace.c */
#include <linux/kthread.h> #include <linux/kthread.h>
#include <linux/delay.h>
static inline int trace_valid_entry(struct trace_entry *entry) static inline int trace_valid_entry(struct trace_entry *entry)
{ {
...@@ -15,28 +16,29 @@ static inline int trace_valid_entry(struct trace_entry *entry) ...@@ -15,28 +16,29 @@ static inline int trace_valid_entry(struct trace_entry *entry)
static int static int
trace_test_buffer_cpu(struct trace_array *tr, struct trace_array_cpu *data) trace_test_buffer_cpu(struct trace_array *tr, struct trace_array_cpu *data)
{ {
struct page *page;
struct trace_entry *entries; struct trace_entry *entries;
struct page *page;
int idx = 0; int idx = 0;
int i; int i;
BUG_ON(list_empty(&data->trace_pages));
page = list_entry(data->trace_pages.next, struct page, lru); page = list_entry(data->trace_pages.next, struct page, lru);
entries = page_address(page); entries = page_address(page);
if (data->trace != entries) if (head_page(data) != entries)
goto failed; goto failed;
/* /*
* The starting trace buffer always has valid elements, * The starting trace buffer always has valid elements,
* if any element exits. * if any element exists.
*/ */
entries = data->trace; entries = head_page(data);
for (i = 0; i < tr->entries; i++) { for (i = 0; i < tr->entries; i++) {
if (i < data->trace_idx && if (i < data->trace_idx && !trace_valid_entry(&entries[idx])) {
!trace_valid_entry(&entries[idx])) { printk(KERN_CONT ".. invalid entry %d ",
printk(KERN_CONT ".. invalid entry %d ", entries[idx].type); entries[idx].type);
goto failed; goto failed;
} }
...@@ -80,11 +82,10 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count) ...@@ -80,11 +82,10 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
int ret = 0; int ret = 0;
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
if (!tr->data[cpu]->trace) if (!head_page(tr->data[cpu]))
continue; continue;
cnt += tr->data[cpu]->trace_idx; cnt += tr->data[cpu]->trace_idx;
printk("%d: count = %ld\n", cpu, cnt);
ret = trace_test_buffer_cpu(tr, tr->data[cpu]); ret = trace_test_buffer_cpu(tr, tr->data[cpu]);
if (ret) if (ret)
...@@ -117,6 +118,8 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr) ...@@ -117,6 +118,8 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
} }
/* start the tracing */ /* start the tracing */
ftrace_enabled = 1;
tr->ctrl = 1; tr->ctrl = 1;
trace->init(tr); trace->init(tr);
/* Sleep for a 1/10 of a second */ /* Sleep for a 1/10 of a second */
...@@ -124,6 +127,8 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr) ...@@ -124,6 +127,8 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr)
/* stop the tracing. */ /* stop the tracing. */
tr->ctrl = 0; tr->ctrl = 0;
trace->ctrl_update(tr); trace->ctrl_update(tr);
ftrace_enabled = 0;
/* check the trace buffer */ /* check the trace buffer */
ret = trace_test_buffer(tr, &count); ret = trace_test_buffer(tr, &count);
trace->reset(tr); trace->reset(tr);
...@@ -328,7 +333,7 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr) ...@@ -328,7 +333,7 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
/* create a high prio thread */ /* create a high prio thread */
p = kthread_run(trace_wakeup_test_thread, &isrt, "ftrace-test"); p = kthread_run(trace_wakeup_test_thread, &isrt, "ftrace-test");
if (!IS_ERR(p)) { if (IS_ERR(p)) {
printk(KERN_CONT "Failed to create ftrace wakeup test thread "); printk(KERN_CONT "Failed to create ftrace wakeup test thread ");
return -1; return -1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment