forked from Minki/linux
f306cc82a9
The trace event filters are still tied to event calls rather than event files, which means you don't get what you'd expect when using filters in the multibuffer case: Before: # echo 'bytes_alloc > 8192' > /sys/kernel/debug/tracing/events/kmem/kmalloc/filter # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/filter bytes_alloc > 8192 # mkdir /sys/kernel/debug/tracing/instances/test1 # echo 'bytes_alloc > 2048' > /sys/kernel/debug/tracing/instances/test1/events/kmem/kmalloc/filter # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/filter bytes_alloc > 2048 # cat /sys/kernel/debug/tracing/instances/test1/events/kmem/kmalloc/filter bytes_alloc > 2048 Setting the filter in tracing/instances/test1/events shouldn't affect the same event in tracing/events as it does above. After: # echo 'bytes_alloc > 8192' > /sys/kernel/debug/tracing/events/kmem/kmalloc/filter # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/filter bytes_alloc > 8192 # mkdir /sys/kernel/debug/tracing/instances/test1 # echo 'bytes_alloc > 2048' > /sys/kernel/debug/tracing/instances/test1/events/kmem/kmalloc/filter # cat /sys/kernel/debug/tracing/events/kmem/kmalloc/filter bytes_alloc > 8192 # cat /sys/kernel/debug/tracing/instances/test1/events/kmem/kmalloc/filter bytes_alloc > 2048 We'd like to just move the filter directly from ftrace_event_call to ftrace_event_file, but there are a couple cases that don't yet have multibuffer support and therefore have to continue using the current event_call-based filters. For those cases, a new USE_CALL_FILTER bit is added to the event_call flags, whose main purpose is to keep the old behavior for those cases until they can be updated with multibuffer support; at that point, the USE_CALL_FILTER flag (and the new associated call_filter_check_discard() function) can go away. The multibuffer support also made filter_current_check_discard() redundant, so this change removes that function as well and replaces it with filter_check_discard() (or call_filter_check_discard() as appropriate). Link: http://lkml.kernel.org/r/f16e9ce4270c62f46b2e966119225e1c3cca7e60.1382620672.git.tom.zanussi@linux.intel.com Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
248 lines
5.8 KiB
C
248 lines
5.8 KiB
C
/*
|
|
* trace context switch
|
|
*
|
|
* Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com>
|
|
*
|
|
*/
|
|
#include <linux/module.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/kallsyms.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/ftrace.h>
|
|
#include <trace/events/sched.h>
|
|
|
|
#include "trace.h"
|
|
|
|
static struct trace_array *ctx_trace;
|
|
static int __read_mostly tracer_enabled;
|
|
static int sched_ref;
|
|
static DEFINE_MUTEX(sched_register_mutex);
|
|
static int sched_stopped;
|
|
|
|
|
|
void
|
|
tracing_sched_switch_trace(struct trace_array *tr,
|
|
struct task_struct *prev,
|
|
struct task_struct *next,
|
|
unsigned long flags, int pc)
|
|
{
|
|
struct ftrace_event_call *call = &event_context_switch;
|
|
struct ring_buffer *buffer = tr->trace_buffer.buffer;
|
|
struct ring_buffer_event *event;
|
|
struct ctx_switch_entry *entry;
|
|
|
|
event = trace_buffer_lock_reserve(buffer, TRACE_CTX,
|
|
sizeof(*entry), flags, pc);
|
|
if (!event)
|
|
return;
|
|
entry = ring_buffer_event_data(event);
|
|
entry->prev_pid = prev->pid;
|
|
entry->prev_prio = prev->prio;
|
|
entry->prev_state = prev->state;
|
|
entry->next_pid = next->pid;
|
|
entry->next_prio = next->prio;
|
|
entry->next_state = next->state;
|
|
entry->next_cpu = task_cpu(next);
|
|
|
|
if (!call_filter_check_discard(call, entry, buffer, event))
|
|
trace_buffer_unlock_commit(buffer, event, flags, pc);
|
|
}
|
|
|
|
static void
|
|
probe_sched_switch(void *ignore, struct task_struct *prev, struct task_struct *next)
|
|
{
|
|
struct trace_array_cpu *data;
|
|
unsigned long flags;
|
|
int cpu;
|
|
int pc;
|
|
|
|
if (unlikely(!sched_ref))
|
|
return;
|
|
|
|
tracing_record_cmdline(prev);
|
|
tracing_record_cmdline(next);
|
|
|
|
if (!tracer_enabled || sched_stopped)
|
|
return;
|
|
|
|
pc = preempt_count();
|
|
local_irq_save(flags);
|
|
cpu = raw_smp_processor_id();
|
|
data = per_cpu_ptr(ctx_trace->trace_buffer.data, cpu);
|
|
|
|
if (likely(!atomic_read(&data->disabled)))
|
|
tracing_sched_switch_trace(ctx_trace, prev, next, flags, pc);
|
|
|
|
local_irq_restore(flags);
|
|
}
|
|
|
|
void
|
|
tracing_sched_wakeup_trace(struct trace_array *tr,
|
|
struct task_struct *wakee,
|
|
struct task_struct *curr,
|
|
unsigned long flags, int pc)
|
|
{
|
|
struct ftrace_event_call *call = &event_wakeup;
|
|
struct ring_buffer_event *event;
|
|
struct ctx_switch_entry *entry;
|
|
struct ring_buffer *buffer = tr->trace_buffer.buffer;
|
|
|
|
event = trace_buffer_lock_reserve(buffer, TRACE_WAKE,
|
|
sizeof(*entry), flags, pc);
|
|
if (!event)
|
|
return;
|
|
entry = ring_buffer_event_data(event);
|
|
entry->prev_pid = curr->pid;
|
|
entry->prev_prio = curr->prio;
|
|
entry->prev_state = curr->state;
|
|
entry->next_pid = wakee->pid;
|
|
entry->next_prio = wakee->prio;
|
|
entry->next_state = wakee->state;
|
|
entry->next_cpu = task_cpu(wakee);
|
|
|
|
if (!call_filter_check_discard(call, entry, buffer, event))
|
|
trace_buffer_unlock_commit(buffer, event, flags, pc);
|
|
}
|
|
|
|
static void
|
|
probe_sched_wakeup(void *ignore, struct task_struct *wakee, int success)
|
|
{
|
|
struct trace_array_cpu *data;
|
|
unsigned long flags;
|
|
int cpu, pc;
|
|
|
|
if (unlikely(!sched_ref))
|
|
return;
|
|
|
|
tracing_record_cmdline(current);
|
|
|
|
if (!tracer_enabled || sched_stopped)
|
|
return;
|
|
|
|
pc = preempt_count();
|
|
local_irq_save(flags);
|
|
cpu = raw_smp_processor_id();
|
|
data = per_cpu_ptr(ctx_trace->trace_buffer.data, cpu);
|
|
|
|
if (likely(!atomic_read(&data->disabled)))
|
|
tracing_sched_wakeup_trace(ctx_trace, wakee, current,
|
|
flags, pc);
|
|
|
|
local_irq_restore(flags);
|
|
}
|
|
|
|
static int tracing_sched_register(void)
|
|
{
|
|
int ret;
|
|
|
|
ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL);
|
|
if (ret) {
|
|
pr_info("wakeup trace: Couldn't activate tracepoint"
|
|
" probe to kernel_sched_wakeup\n");
|
|
return ret;
|
|
}
|
|
|
|
ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
|
|
if (ret) {
|
|
pr_info("wakeup trace: Couldn't activate tracepoint"
|
|
" probe to kernel_sched_wakeup_new\n");
|
|
goto fail_deprobe;
|
|
}
|
|
|
|
ret = register_trace_sched_switch(probe_sched_switch, NULL);
|
|
if (ret) {
|
|
pr_info("sched trace: Couldn't activate tracepoint"
|
|
" probe to kernel_sched_switch\n");
|
|
goto fail_deprobe_wake_new;
|
|
}
|
|
|
|
return ret;
|
|
fail_deprobe_wake_new:
|
|
unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
|
|
fail_deprobe:
|
|
unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
|
|
return ret;
|
|
}
|
|
|
|
static void tracing_sched_unregister(void)
|
|
{
|
|
unregister_trace_sched_switch(probe_sched_switch, NULL);
|
|
unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL);
|
|
unregister_trace_sched_wakeup(probe_sched_wakeup, NULL);
|
|
}
|
|
|
|
static void tracing_start_sched_switch(void)
|
|
{
|
|
mutex_lock(&sched_register_mutex);
|
|
if (!(sched_ref++))
|
|
tracing_sched_register();
|
|
mutex_unlock(&sched_register_mutex);
|
|
}
|
|
|
|
static void tracing_stop_sched_switch(void)
|
|
{
|
|
mutex_lock(&sched_register_mutex);
|
|
if (!(--sched_ref))
|
|
tracing_sched_unregister();
|
|
mutex_unlock(&sched_register_mutex);
|
|
}
|
|
|
|
void tracing_start_cmdline_record(void)
|
|
{
|
|
tracing_start_sched_switch();
|
|
}
|
|
|
|
void tracing_stop_cmdline_record(void)
|
|
{
|
|
tracing_stop_sched_switch();
|
|
}
|
|
|
|
/**
|
|
* tracing_start_sched_switch_record - start tracing context switches
|
|
*
|
|
* Turns on context switch tracing for a tracer.
|
|
*/
|
|
void tracing_start_sched_switch_record(void)
|
|
{
|
|
if (unlikely(!ctx_trace)) {
|
|
WARN_ON(1);
|
|
return;
|
|
}
|
|
|
|
tracing_start_sched_switch();
|
|
|
|
mutex_lock(&sched_register_mutex);
|
|
tracer_enabled++;
|
|
mutex_unlock(&sched_register_mutex);
|
|
}
|
|
|
|
/**
|
|
* tracing_stop_sched_switch_record - start tracing context switches
|
|
*
|
|
* Turns off context switch tracing for a tracer.
|
|
*/
|
|
void tracing_stop_sched_switch_record(void)
|
|
{
|
|
mutex_lock(&sched_register_mutex);
|
|
tracer_enabled--;
|
|
WARN_ON(tracer_enabled < 0);
|
|
mutex_unlock(&sched_register_mutex);
|
|
|
|
tracing_stop_sched_switch();
|
|
}
|
|
|
|
/**
|
|
* tracing_sched_switch_assign_trace - assign a trace array for ctx switch
|
|
* @tr: trace array pointer to assign
|
|
*
|
|
* Some tracers might want to record the context switches in their
|
|
* trace. This function lets those tracers assign the trace array
|
|
* to use.
|
|
*/
|
|
void tracing_sched_switch_assign_trace(struct trace_array *tr)
|
|
{
|
|
ctx_trace = tr;
|
|
}
|
|
|