ftrace: force recording
Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
This commit is contained in:
parent
57f50be14d
commit
e1c08bdd9f
2 changed files with 55 additions and 0 deletions
|
@ -54,6 +54,8 @@ struct dyn_ftrace {
|
|||
unsigned long flags;
|
||||
};
|
||||
|
||||
int ftrace_force_update(void);
|
||||
|
||||
/* defined in arch */
|
||||
extern int ftrace_ip_converted(unsigned long ip);
|
||||
extern unsigned char *ftrace_nop_replace(void);
|
||||
|
@ -66,6 +68,8 @@ extern int ftrace_update_ftrace_func(ftrace_func_t func);
|
|||
extern void ftrace_caller(void);
|
||||
extern void ftrace_call(void);
|
||||
extern void mcount_call(void);
|
||||
#else
|
||||
# define ftrace_force_update() do { } while (0)
|
||||
#endif
|
||||
|
||||
static inline void tracer_disable(void)
|
||||
|
|
|
@ -146,6 +146,10 @@ static int notrace __unregister_ftrace_function(struct ftrace_ops *ops)
|
|||
|
||||
#ifdef CONFIG_DYNAMIC_FTRACE
|
||||
|
||||
static struct task_struct *ftraced_task;
|
||||
static DECLARE_WAIT_QUEUE_HEAD(ftraced_waiters);
|
||||
static unsigned long ftraced_iteration_counter;
|
||||
|
||||
enum {
|
||||
FTRACE_ENABLE_CALLS = (1 << 0),
|
||||
FTRACE_DISABLE_CALLS = (1 << 1),
|
||||
|
@ -590,9 +594,12 @@ static int notrace ftraced(void *ignore)
|
|||
ftraced_trigger = 0;
|
||||
ftrace_record_suspend--;
|
||||
}
|
||||
ftraced_iteration_counter++;
|
||||
mutex_unlock(&ftraced_lock);
|
||||
mutex_unlock(&ftrace_sysctl_lock);
|
||||
|
||||
wake_up_interruptible(&ftraced_waiters);
|
||||
|
||||
ftrace_shutdown_replenish();
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
@ -1050,6 +1057,49 @@ static struct file_operations ftrace_filter_fops = {
|
|||
.release = ftrace_filter_release,
|
||||
};
|
||||
|
||||
/**
|
||||
* ftrace_force_update - force an update to all recording ftrace functions
|
||||
*
|
||||
* The ftrace dynamic update daemon only wakes up once a second.
|
||||
* There may be cases where an update needs to be done immediately
|
||||
* for tests or internal kernel tracing to begin. This function
|
||||
* wakes the daemon to do an update and will not return until the
|
||||
* update is complete.
|
||||
*/
|
||||
int ftrace_force_update(void)
|
||||
{
|
||||
unsigned long last_counter;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
int ret = 0;
|
||||
|
||||
if (!ftraced_task)
|
||||
return -ENODEV;
|
||||
|
||||
mutex_lock(&ftraced_lock);
|
||||
last_counter = ftraced_iteration_counter;
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
add_wait_queue(&ftraced_waiters, &wait);
|
||||
|
||||
do {
|
||||
mutex_unlock(&ftraced_lock);
|
||||
wake_up_process(ftraced_task);
|
||||
schedule();
|
||||
mutex_lock(&ftraced_lock);
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR;
|
||||
break;
|
||||
}
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
} while (last_counter == ftraced_iteration_counter);
|
||||
|
||||
mutex_unlock(&ftraced_lock);
|
||||
remove_wait_queue(&ftraced_waiters, &wait);
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __init int ftrace_init_debugfs(void)
|
||||
{
|
||||
struct dentry *d_tracer;
|
||||
|
@ -1095,6 +1145,7 @@ static int __init notrace ftrace_dynamic_init(void)
|
|||
return -1;
|
||||
|
||||
last_ftrace_enabled = ftrace_enabled = 1;
|
||||
ftraced_task = p;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue