diff options
author | Steven Rostedt <rostedt@goodmis.org> | 2014-10-08 13:52:16 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-10-09 11:15:08 -0400 |
commit | addff1feb02b03cb766b9a611c6b2cebf29bc285 (patch) | |
tree | faf54b05294f2feac72d62ebafb2fcbe959185e0 /kernel/trace | |
parent | fe0e01c77dd9f7a60916aec2149d8a1182baf63c (diff) |
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>
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace_selftest.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 5ef60499dc8e..593f52b73551 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c | |||
@@ -1025,6 +1025,12 @@ trace_selftest_startup_nop(struct tracer *trace, struct trace_array *tr) | |||
1025 | #endif | 1025 | #endif |
1026 | 1026 | ||
1027 | #ifdef CONFIG_SCHED_TRACER | 1027 | #ifdef CONFIG_SCHED_TRACER |
1028 | |||
1029 | struct wakeup_test_data { | ||
1030 | struct completion is_ready; | ||
1031 | int go; | ||
1032 | }; | ||
1033 | |||
1028 | static int trace_wakeup_test_thread(void *data) | 1034 | static int trace_wakeup_test_thread(void *data) |
1029 | { | 1035 | { |
1030 | /* Make this a -deadline thread */ | 1036 | /* Make this a -deadline thread */ |
@@ -1034,51 +1040,56 @@ static int trace_wakeup_test_thread(void *data) | |||
1034 | .sched_deadline = 10000000ULL, | 1040 | .sched_deadline = 10000000ULL, |
1035 | .sched_period = 10000000ULL | 1041 | .sched_period = 10000000ULL |
1036 | }; | 1042 | }; |
1037 | struct completion *x = data; | 1043 | struct wakeup_test_data *x = data; |
1038 | 1044 | ||
1039 | sched_setattr(current, &attr); | 1045 | sched_setattr(current, &attr); |
1040 | 1046 | ||
1041 | /* Make it know we have a new prio */ | 1047 | /* Make it know we have a new prio */ |
1042 | complete(x); | 1048 | complete(&x->is_ready); |
1043 | 1049 | ||
1044 | /* now go to sleep and let the test wake us up */ | 1050 | /* now go to sleep and let the test wake us up */ |
1045 | set_current_state(TASK_INTERRUPTIBLE); | 1051 | set_current_state(TASK_INTERRUPTIBLE); |
1046 | schedule(); | 1052 | while (!x->go) { |
1053 | schedule(); | ||
1054 | set_current_state(TASK_INTERRUPTIBLE); | ||
1055 | } | ||
1047 | 1056 | ||
1048 | complete(x); | 1057 | complete(&x->is_ready); |
1058 | |||
1059 | set_current_state(TASK_INTERRUPTIBLE); | ||
1049 | 1060 | ||
1050 | /* we are awake, now wait to disappear */ | 1061 | /* we are awake, now wait to disappear */ |
1051 | while (!kthread_should_stop()) { | 1062 | while (!kthread_should_stop()) { |
1052 | /* | 1063 | schedule(); |
1053 | * This will likely be the system top priority | 1064 | set_current_state(TASK_INTERRUPTIBLE); |
1054 | * task, do short sleeps to let others run. | ||
1055 | */ | ||
1056 | msleep(100); | ||
1057 | } | 1065 | } |
1058 | 1066 | ||
1067 | __set_current_state(TASK_RUNNING); | ||
1068 | |||
1059 | return 0; | 1069 | return 0; |
1060 | } | 1070 | } |
1061 | |||
1062 | int | 1071 | int |
1063 | trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr) | 1072 | trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr) |
1064 | { | 1073 | { |
1065 | unsigned long save_max = tr->max_latency; | 1074 | unsigned long save_max = tr->max_latency; |
1066 | struct task_struct *p; | 1075 | struct task_struct *p; |
1067 | struct completion is_ready; | 1076 | struct wakeup_test_data data; |
1068 | unsigned long count; | 1077 | unsigned long count; |
1069 | int ret; | 1078 | int ret; |
1070 | 1079 | ||
1071 | init_completion(&is_ready); | 1080 | memset(&data, 0, sizeof(data)); |
1081 | |||
1082 | init_completion(&data.is_ready); | ||
1072 | 1083 | ||
1073 | /* create a -deadline thread */ | 1084 | /* create a -deadline thread */ |
1074 | p = kthread_run(trace_wakeup_test_thread, &is_ready, "ftrace-test"); | 1085 | p = kthread_run(trace_wakeup_test_thread, &data, "ftrace-test"); |
1075 | if (IS_ERR(p)) { | 1086 | if (IS_ERR(p)) { |
1076 | printk(KERN_CONT "Failed to create ftrace wakeup test thread "); | 1087 | printk(KERN_CONT "Failed to create ftrace wakeup test thread "); |
1077 | return -1; | 1088 | return -1; |
1078 | } | 1089 | } |
1079 | 1090 | ||
1080 | /* make sure the thread is running at -deadline policy */ | 1091 | /* make sure the thread is running at -deadline policy */ |
1081 | wait_for_completion(&is_ready); | 1092 | wait_for_completion(&data.is_ready); |
1082 | 1093 | ||
1083 | /* start the tracing */ | 1094 | /* start the tracing */ |
1084 | ret = tracer_init(trace, tr); | 1095 | ret = tracer_init(trace, tr); |
@@ -1099,18 +1110,20 @@ trace_selftest_startup_wakeup(struct tracer *trace, struct trace_array *tr) | |||
1099 | msleep(100); | 1110 | msleep(100); |
1100 | } | 1111 | } |
1101 | 1112 | ||
1102 | init_completion(&is_ready); | 1113 | init_completion(&data.is_ready); |
1114 | |||
1115 | data.go = 1; | ||
1116 | /* memory barrier is in the wake_up_process() */ | ||
1103 | 1117 | ||
1104 | wake_up_process(p); | 1118 | wake_up_process(p); |
1105 | 1119 | ||
1106 | /* Wait for the task to wake up */ | 1120 | /* Wait for the task to wake up */ |
1107 | wait_for_completion(&is_ready); | 1121 | wait_for_completion(&data.is_ready); |
1108 | 1122 | ||
1109 | /* stop the tracing. */ | 1123 | /* stop the tracing. */ |
1110 | tracing_stop(); | 1124 | tracing_stop(); |
1111 | /* check both trace buffers */ | 1125 | /* check both trace buffers */ |
1112 | ret = trace_test_buffer(&tr->trace_buffer, NULL); | 1126 | ret = trace_test_buffer(&tr->trace_buffer, NULL); |
1113 | printk("ret = %d\n", ret); | ||
1114 | if (!ret) | 1127 | if (!ret) |
1115 | ret = trace_test_buffer(&tr->max_buffer, &count); | 1128 | ret = trace_test_buffer(&tr->max_buffer, &count); |
1116 | 1129 | ||