diff options
Diffstat (limited to 'kernel/trace/ring_buffer_benchmark.c')
| -rw-r--r-- | kernel/trace/ring_buffer_benchmark.c | 79 |
1 files changed, 44 insertions, 35 deletions
diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index a1503a027ee2..6df9a83e20d7 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c | |||
| @@ -24,8 +24,8 @@ struct rb_page { | |||
| 24 | static int wakeup_interval = 100; | 24 | static int wakeup_interval = 100; |
| 25 | 25 | ||
| 26 | static int reader_finish; | 26 | static int reader_finish; |
| 27 | static struct completion read_start; | 27 | static DECLARE_COMPLETION(read_start); |
| 28 | static struct completion read_done; | 28 | static DECLARE_COMPLETION(read_done); |
| 29 | 29 | ||
| 30 | static struct ring_buffer *buffer; | 30 | static struct ring_buffer *buffer; |
| 31 | static struct task_struct *producer; | 31 | static struct task_struct *producer; |
| @@ -60,12 +60,12 @@ MODULE_PARM_DESC(consumer_fifo, "fifo prio for consumer"); | |||
| 60 | 60 | ||
| 61 | static int read_events; | 61 | static int read_events; |
| 62 | 62 | ||
| 63 | static int kill_test; | 63 | static int test_error; |
| 64 | 64 | ||
| 65 | #define KILL_TEST() \ | 65 | #define TEST_ERROR() \ |
| 66 | do { \ | 66 | do { \ |
| 67 | if (!kill_test) { \ | 67 | if (!test_error) { \ |
| 68 | kill_test = 1; \ | 68 | test_error = 1; \ |
| 69 | WARN_ON(1); \ | 69 | WARN_ON(1); \ |
| 70 | } \ | 70 | } \ |
| 71 | } while (0) | 71 | } while (0) |
| @@ -75,6 +75,11 @@ enum event_status { | |||
| 75 | EVENT_DROPPED, | 75 | EVENT_DROPPED, |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | static bool break_test(void) | ||
| 79 | { | ||
| 80 | return test_error || kthread_should_stop(); | ||
| 81 | } | ||
| 82 | |||
| 78 | static enum event_status read_event(int cpu) | 83 | static enum event_status read_event(int cpu) |
| 79 | { | 84 | { |
| 80 | struct ring_buffer_event *event; | 85 | struct ring_buffer_event *event; |
| @@ -87,7 +92,7 @@ static enum event_status read_event(int cpu) | |||
| 87 | 92 | ||
| 88 | entry = ring_buffer_event_data(event); | 93 | entry = ring_buffer_event_data(event); |
| 89 | if (*entry != cpu) { | 94 | if (*entry != cpu) { |
| 90 | KILL_TEST(); | 95 | TEST_ERROR(); |
| 91 | return EVENT_DROPPED; | 96 | return EVENT_DROPPED; |
| 92 | } | 97 | } |
| 93 | 98 | ||
| @@ -115,10 +120,10 @@ static enum event_status read_page(int cpu) | |||
| 115 | rpage = bpage; | 120 | rpage = bpage; |
| 116 | /* The commit may have missed event flags set, clear them */ | 121 | /* The commit may have missed event flags set, clear them */ |
| 117 | commit = local_read(&rpage->commit) & 0xfffff; | 122 | commit = local_read(&rpage->commit) & 0xfffff; |
| 118 | for (i = 0; i < commit && !kill_test; i += inc) { | 123 | for (i = 0; i < commit && !test_error ; i += inc) { |
| 119 | 124 | ||
| 120 | if (i >= (PAGE_SIZE - offsetof(struct rb_page, data))) { | 125 | if (i >= (PAGE_SIZE - offsetof(struct rb_page, data))) { |
| 121 | KILL_TEST(); | 126 | TEST_ERROR(); |
| 122 | break; | 127 | break; |
| 123 | } | 128 | } |
| 124 | 129 | ||
| @@ -128,7 +133,7 @@ static enum event_status read_page(int cpu) | |||
| 128 | case RINGBUF_TYPE_PADDING: | 133 | case RINGBUF_TYPE_PADDING: |
| 129 | /* failed writes may be discarded events */ | 134 | /* failed writes may be discarded events */ |
| 130 | if (!event->time_delta) | 135 | if (!event->time_delta) |
| 131 | KILL_TEST(); | 136 | TEST_ERROR(); |
| 132 | inc = event->array[0] + 4; | 137 | inc = event->array[0] + 4; |
| 133 | break; | 138 | break; |
| 134 | case RINGBUF_TYPE_TIME_EXTEND: | 139 | case RINGBUF_TYPE_TIME_EXTEND: |
| @@ -137,12 +142,12 @@ static enum event_status read_page(int cpu) | |||
| 137 | case 0: | 142 | case 0: |
| 138 | entry = ring_buffer_event_data(event); | 143 | entry = ring_buffer_event_data(event); |
| 139 | if (*entry != cpu) { | 144 | if (*entry != cpu) { |
| 140 | KILL_TEST(); | 145 | TEST_ERROR(); |
| 141 | break; | 146 | break; |
| 142 | } | 147 | } |
| 143 | read++; | 148 | read++; |
| 144 | if (!event->array[0]) { | 149 | if (!event->array[0]) { |
| 145 | KILL_TEST(); | 150 | TEST_ERROR(); |
| 146 | break; | 151 | break; |
| 147 | } | 152 | } |
| 148 | inc = event->array[0] + 4; | 153 | inc = event->array[0] + 4; |
| @@ -150,17 +155,17 @@ static enum event_status read_page(int cpu) | |||
| 150 | default: | 155 | default: |
| 151 | entry = ring_buffer_event_data(event); | 156 | entry = ring_buffer_event_data(event); |
| 152 | if (*entry != cpu) { | 157 | if (*entry != cpu) { |
| 153 | KILL_TEST(); | 158 | TEST_ERROR(); |
| 154 | break; | 159 | break; |
| 155 | } | 160 | } |
| 156 | read++; | 161 | read++; |
| 157 | inc = ((event->type_len + 1) * 4); | 162 | inc = ((event->type_len + 1) * 4); |
| 158 | } | 163 | } |
| 159 | if (kill_test) | 164 | if (test_error) |
| 160 | break; | 165 | break; |
| 161 | 166 | ||
| 162 | if (inc <= 0) { | 167 | if (inc <= 0) { |
| 163 | KILL_TEST(); | 168 | TEST_ERROR(); |
| 164 | break; | 169 | break; |
| 165 | } | 170 | } |
| 166 | } | 171 | } |
| @@ -178,10 +183,14 @@ static void ring_buffer_consumer(void) | |||
| 178 | read_events ^= 1; | 183 | read_events ^= 1; |
| 179 | 184 | ||
| 180 | read = 0; | 185 | read = 0; |
| 181 | while (!reader_finish && !kill_test) { | 186 | /* |
| 182 | int found; | 187 | * Continue running until the producer specifically asks to stop |
| 188 | * and is ready for the completion. | ||
| 189 | */ | ||
| 190 | while (!READ_ONCE(reader_finish)) { | ||
| 191 | int found = 1; | ||
| 183 | 192 | ||
| 184 | do { | 193 | while (found && !test_error) { |
| 185 | int cpu; | 194 | int cpu; |
| 186 | 195 | ||
| 187 | found = 0; | 196 | found = 0; |
| @@ -193,19 +202,25 @@ static void ring_buffer_consumer(void) | |||
| 193 | else | 202 | else |
| 194 | stat = read_page(cpu); | 203 | stat = read_page(cpu); |
| 195 | 204 | ||
| 196 | if (kill_test) | 205 | if (test_error) |
| 197 | break; | 206 | break; |
| 207 | |||
| 198 | if (stat == EVENT_FOUND) | 208 | if (stat == EVENT_FOUND) |
| 199 | found = 1; | 209 | found = 1; |
| 210 | |||
| 200 | } | 211 | } |
| 201 | } while (found && !kill_test); | 212 | } |
| 202 | 213 | ||
| 214 | /* Wait till the producer wakes us up when there is more data | ||
| 215 | * available or when the producer wants us to finish reading. | ||
| 216 | */ | ||
| 203 | set_current_state(TASK_INTERRUPTIBLE); | 217 | set_current_state(TASK_INTERRUPTIBLE); |
| 204 | if (reader_finish) | 218 | if (reader_finish) |
| 205 | break; | 219 | break; |
| 206 | 220 | ||
| 207 | schedule(); | 221 | schedule(); |
| 208 | } | 222 | } |
| 223 | __set_current_state(TASK_RUNNING); | ||
| 209 | reader_finish = 0; | 224 | reader_finish = 0; |
| 210 | complete(&read_done); | 225 | complete(&read_done); |
| 211 | } | 226 | } |
| @@ -263,10 +278,7 @@ static void ring_buffer_producer(void) | |||
| 263 | if (cnt % wakeup_interval) | 278 | if (cnt % wakeup_interval) |
| 264 | cond_resched(); | 279 | cond_resched(); |
| 265 | #endif | 280 | #endif |
| 266 | if (kthread_should_stop()) | 281 | } while (ktime_before(end_time, timeout) && !break_test()); |
| 267 | kill_test = 1; | ||
| 268 | |||
| 269 | } while (ktime_before(end_time, timeout) && !kill_test); | ||
| 270 | trace_printk("End ring buffer hammer\n"); | 282 | trace_printk("End ring buffer hammer\n"); |
| 271 | 283 | ||
| 272 | if (consumer) { | 284 | if (consumer) { |
| @@ -276,8 +288,6 @@ static void ring_buffer_producer(void) | |||
| 276 | /* the completions must be visible before the finish var */ | 288 | /* the completions must be visible before the finish var */ |
| 277 | smp_wmb(); | 289 | smp_wmb(); |
| 278 | reader_finish = 1; | 290 | reader_finish = 1; |
| 279 | /* finish var visible before waking up the consumer */ | ||
| 280 | smp_wmb(); | ||
| 281 | wake_up_process(consumer); | 291 | wake_up_process(consumer); |
| 282 | wait_for_completion(&read_done); | 292 | wait_for_completion(&read_done); |
| 283 | } | 293 | } |
| @@ -287,7 +297,7 @@ static void ring_buffer_producer(void) | |||
| 287 | entries = ring_buffer_entries(buffer); | 297 | entries = ring_buffer_entries(buffer); |
| 288 | overruns = ring_buffer_overruns(buffer); | 298 | overruns = ring_buffer_overruns(buffer); |
| 289 | 299 | ||
| 290 | if (kill_test && !kthread_should_stop()) | 300 | if (test_error) |
| 291 | trace_printk("ERROR!\n"); | 301 | trace_printk("ERROR!\n"); |
| 292 | 302 | ||
| 293 | if (!disable_reader) { | 303 | if (!disable_reader) { |
| @@ -368,15 +378,14 @@ static void wait_to_die(void) | |||
| 368 | 378 | ||
| 369 | static int ring_buffer_consumer_thread(void *arg) | 379 | static int ring_buffer_consumer_thread(void *arg) |
| 370 | { | 380 | { |
| 371 | while (!kthread_should_stop() && !kill_test) { | 381 | while (!break_test()) { |
| 372 | complete(&read_start); | 382 | complete(&read_start); |
| 373 | 383 | ||
| 374 | ring_buffer_consumer(); | 384 | ring_buffer_consumer(); |
| 375 | 385 | ||
| 376 | set_current_state(TASK_INTERRUPTIBLE); | 386 | set_current_state(TASK_INTERRUPTIBLE); |
| 377 | if (kthread_should_stop() || kill_test) | 387 | if (break_test()) |
| 378 | break; | 388 | break; |
| 379 | |||
| 380 | schedule(); | 389 | schedule(); |
| 381 | } | 390 | } |
| 382 | __set_current_state(TASK_RUNNING); | 391 | __set_current_state(TASK_RUNNING); |
| @@ -389,27 +398,27 @@ static int ring_buffer_consumer_thread(void *arg) | |||
| 389 | 398 | ||
| 390 | static int ring_buffer_producer_thread(void *arg) | 399 | static int ring_buffer_producer_thread(void *arg) |
| 391 | { | 400 | { |
| 392 | init_completion(&read_start); | 401 | while (!break_test()) { |
| 393 | |||
| 394 | while (!kthread_should_stop() && !kill_test) { | ||
| 395 | ring_buffer_reset(buffer); | 402 | ring_buffer_reset(buffer); |
| 396 | 403 | ||
| 397 | if (consumer) { | 404 | if (consumer) { |
| 398 | smp_wmb(); | ||
| 399 | wake_up_process(consumer); | 405 | wake_up_process(consumer); |
| 400 | wait_for_completion(&read_start); | 406 | wait_for_completion(&read_start); |
| 401 | } | 407 | } |
| 402 | 408 | ||
| 403 | ring_buffer_producer(); | 409 | ring_buffer_producer(); |
| 404 | if (kill_test) | 410 | if (break_test()) |
| 405 | goto out_kill; | 411 | goto out_kill; |
| 406 | 412 | ||
| 407 | trace_printk("Sleeping for 10 secs\n"); | 413 | trace_printk("Sleeping for 10 secs\n"); |
| 408 | set_current_state(TASK_INTERRUPTIBLE); | 414 | set_current_state(TASK_INTERRUPTIBLE); |
| 415 | if (break_test()) | ||
| 416 | goto out_kill; | ||
| 409 | schedule_timeout(HZ * SLEEP_TIME); | 417 | schedule_timeout(HZ * SLEEP_TIME); |
| 410 | } | 418 | } |
| 411 | 419 | ||
| 412 | out_kill: | 420 | out_kill: |
| 421 | __set_current_state(TASK_RUNNING); | ||
| 413 | if (!kthread_should_stop()) | 422 | if (!kthread_should_stop()) |
| 414 | wait_to_die(); | 423 | wait_to_die(); |
| 415 | 424 | ||
