tracing: Clean up scheduling in trace_wakeup_test_thread()
Peter's new debugging tool triggers when tasks exit with !TASK_RUNNING. The code in trace_wakeup_test_thread() also has a single schedule() call that should be encompassed by a loop. This cleans up the code a little to make it a bit more robust and also makes the return exit properly with TASK_RUNNING. Link: http://lkml.kernel.org/p/20141008135216.76142204@gandalf.local.home Reported-by: Peter Zijlstra <peterz@infradead.org> Acked-by: Peter Zijlstra <peterz@infreadead.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
fe0e01c77d
commit
addff1feb0
|
@ -1025,6 +1025,12 @@ trace_selftest_startup_nop(struct tracer *trace, struct trace_array *tr)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SCHED_TRACER
|
#ifdef CONFIG_SCHED_TRACER
|
||||||
|
|
||||||
|
struct wakeup_test_data {
|
||||||
|
struct completion is_ready;
|
||||||
|
int go;
|
||||||
|
};
|
||||||
|
|
||||||
static int trace_wakeup_test_thread(void *data)
|
static int trace_wakeup_test_thread(void *data)
|
||||||
{
|
{
|
||||||
/* Make this a -deadline thread */
|
/* Make this a -deadline thread */
|
||||||
|
@ -1034,51 +1040,56 @@ static int trace_wakeup_test_thread(void *data)
|
||||||
.sched_deadline = 10000000ULL,
|
.sched_deadline = 10000000ULL,
|
||||||
.sched_period = 10000000ULL
|
.sched_period = 10000000ULL
|
||||||
};
|
};
|
||||||
struct completion *x = data;
|
struct wakeup_test_data *x = data;
|
||||||
|
|
||||||
sched_setattr(current, &attr);
|
sched_setattr(current, &attr);
|
||||||
|
|
||||||
/* Make it know we have a new prio */
|
/* Make it know we have a new prio */
|
||||||
complete(x);
|
complete(&x->is_ready);
|
||||||
|
|
||||||
/* now go to sleep and let the test wake us up */
|
/* now go to sleep and let the test wake us up */
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
while (!x->go) {
|
||||||
schedule();
|
schedule();
|
||||||
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
complete(x);
|
complete(&x->is_ready);
|
||||||
|
|
||||||
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
|
||||||
/* we are awake, now wait to disappear */
|
/* we are awake, now wait to disappear */
|
||||||
while (!kthread_should_stop()) {
|
while (!kthread_should_stop()) {
|
||||||
/*
|
schedule();
|
||||||
* This will likely be the system top priority
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
* task, do short sleeps to let others run.
|
|
||||||
*/
|
|
||||||
msleep(100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__set_current_state(TASK_RUNNING);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
|
trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
|
||||||
{
|
{
|
||||||
unsigned long save_max = tr->max_latency;
|
unsigned long save_max = tr->max_latency;
|
||||||
struct task_struct *p;
|
struct task_struct *p;
|
||||||
struct completion is_ready;
|
struct wakeup_test_data data;
|
||||||
unsigned long count;
|
unsigned long count;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
init_completion(&is_ready);
|
memset(&data, 0, sizeof(data));
|
||||||
|
|
||||||
|
init_completion(&data.is_ready);
|
||||||
|
|
||||||
/* create a -deadline thread */
|
/* create a -deadline thread */
|
||||||
p = kthread_run(trace_wakeup_test_thread, &is_ready, "ftrace-test");
|
p = kthread_run(trace_wakeup_test_thread, &data, "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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure the thread is running at -deadline policy */
|
/* make sure the thread is running at -deadline policy */
|
||||||
wait_for_completion(&is_ready);
|
wait_for_completion(&data.is_ready);
|
||||||
|
|
||||||
/* start the tracing */
|
/* start the tracing */
|
||||||
ret = tracer_init(trace, tr);
|
ret = tracer_init(trace, tr);
|
||||||
|
@ -1099,18 +1110,20 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr)
|
||||||
msleep(100);
|
msleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
init_completion(&is_ready);
|
init_completion(&data.is_ready);
|
||||||
|
|
||||||
|
data.go = 1;
|
||||||
|
/* memory barrier is in the wake_up_process() */
|
||||||
|
|
||||||
wake_up_process(p);
|
wake_up_process(p);
|
||||||
|
|
||||||
/* Wait for the task to wake up */
|
/* Wait for the task to wake up */
|
||||||
wait_for_completion(&is_ready);
|
wait_for_completion(&data.is_ready);
|
||||||
|
|
||||||
/* stop the tracing. */
|
/* stop the tracing. */
|
||||||
tracing_stop();
|
tracing_stop();
|
||||||
/* check both trace buffers */
|
/* check both trace buffers */
|
||||||
ret = trace_test_buffer(&tr->trace_buffer, NULL);
|
ret = trace_test_buffer(&tr->trace_buffer, NULL);
|
||||||
printk("ret = %d\n", ret);
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = trace_test_buffer(&tr->max_buffer, &count);
|
ret = trace_test_buffer(&tr->max_buffer, &count);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue