Re: [RFC PATCH 10/14] ring_buffer: Fix more races when terminating the producer in the benchmark
Sorry, I didn't read these emails, and I never looked at this code... Can't understand what are you talking about but a minor nit anyway ;) On 09/04, Petr Mladek wrote: > > + __set_current_state(TASK_RUNNING); > if (!kthread_should_stop()) > wait_to_die(); I bet this wait_to_die() can die, consumer/producer can simply exit. Just you need get_task_struct() after kthread_create(), and put_task_struct() after kthread_stop(). Oleg. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC PATCH 10/14] ring_buffer: Fix more races when terminating the producer in the benchmark
On Mon 2015-08-03 14:33:23, Steven Rostedt wrote: > On Tue, 28 Jul 2015 16:39:27 +0200 > Petr Mladek wrote: > > > @@ -384,7 +389,7 @@ static int ring_buffer_consumer_thread(void *arg) > > > > static int ring_buffer_producer_thread(void *arg) > > { > > - while (!kthread_should_stop() && !kill_test) { > > + while (!break_test()) { > > ring_buffer_reset(buffer); > > > > if (consumer) { > > @@ -393,11 +398,15 @@ static int ring_buffer_producer_thread(void *arg) > > } > > > > ring_buffer_producer(); > > - if (kill_test) > > + if (break_test()) > > goto out_kill; > > > > trace_printk("Sleeping for 10 secs\n"); > > set_current_state(TASK_INTERRUPTIBLE); > > + if (break_test()) { > > + __set_current_state(TASK_RUNNING); > > Move the setting of the current state to after the out_kill label. Please, find below the updated version of this patch. I also reverted some changes in the consumer code. It never stays in a loop for too long and it must stay in ring_buffer_producer() until "reader_finish" variable is set. >From 7f5b1a5b8cf8248245897b55ffc51a6d74c8e15b Mon Sep 17 00:00:00 2001 From: Petr Mladek Date: Fri, 19 Jun 2015 14:38:36 +0200 Subject: [PATCH 2/2] ring_buffer: Fix more races when terminating the producer in the benchmark The commit b44754d8262d3aab8 ("ring_buffer: Allow to exit the ring buffer benchmark immediately") added a hack into ring_buffer_producer() that set @kill_test when kthread_should_stop() returned true. It improved the situation a lot. It stopped the kthread in most cases because the producer spent most of the time in the patched while cycle. But there are still few possible races when kthread_should_stop() is set outside of the cycle. Then we do not set @kill_test and some other checks pass. This patch adds a better fix. It renames @test_kill/TEST_KILL() into a better descriptive @test_error/TEST_ERROR(). Also it introduces break_test() function that checks for both @test_error and kthread_should_stop(). The new function is used in the producer when the check for @test_error is not enough. It is not used in the consumer because its state is manipulated by the producer via the "reader_finish" variable. Also we add a missing check into ring_buffer_producer_thread() between setting TASK_INTERRUPTIBLE and calling schedule_timeout(). Otherwise, we might miss a wakeup from kthread_stop(). Signed-off-by: Petr Mladek --- kernel/trace/ring_buffer_benchmark.c | 54 +++- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index 045e0a24c2a0..d1bfe4399e96 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c @@ -60,12 +60,12 @@ MODULE_PARM_DESC(consumer_fifo, "fifo prio for consumer"); static int read_events; -static int kill_test; +static int test_error; -#define KILL_TEST()\ +#define TEST_ERROR() \ do {\ - if (!kill_test) { \ - kill_test = 1; \ + if (!test_error) { \ + test_error = 1; \ WARN_ON(1); \ } \ } while (0) @@ -75,6 +75,11 @@ enum event_status { EVENT_DROPPED, }; +static bool break_test(void) +{ + return test_error || kthread_should_stop(); +} + static enum event_status read_event(int cpu) { struct ring_buffer_event *event; @@ -87,7 +92,7 @@ static enum event_status read_event(int cpu) entry = ring_buffer_event_data(event); if (*entry != cpu) { - KILL_TEST(); + TEST_ERROR(); return EVENT_DROPPED; } @@ -115,10 +120,10 @@ static enum event_status read_page(int cpu) rpage = bpage; /* The commit may have missed event flags set, clear them */ commit = local_read(&rpage->commit) & 0xf; - for (i = 0; i < commit && !kill_test; i += inc) { + for (i = 0; i < commit && !test_error ; i += inc) { if (i >= (PAGE_SIZE - offsetof(struct rb_page, data))) { - KILL_TEST(); + TEST_ERROR(); break; } @@ -128,7 +133,7 @@ static enum event_status read_page(int cpu) case RINGBUF_TYPE_PADDING: /* failed writes may be discarded events */ if (!event->time_delta) - KILL_TEST(); + TEST_ERROR();
Re: [RFC PATCH 10/14] ring_buffer: Fix more races when terminating the producer in the benchmark
On Tue, 28 Jul 2015 16:39:27 +0200 Petr Mladek wrote: > @@ -384,7 +389,7 @@ static int ring_buffer_consumer_thread(void *arg) > > static int ring_buffer_producer_thread(void *arg) > { > - while (!kthread_should_stop() && !kill_test) { > + while (!break_test()) { > ring_buffer_reset(buffer); > > if (consumer) { > @@ -393,11 +398,15 @@ static int ring_buffer_producer_thread(void *arg) > } > > ring_buffer_producer(); > - if (kill_test) > + if (break_test()) > goto out_kill; > > trace_printk("Sleeping for 10 secs\n"); > set_current_state(TASK_INTERRUPTIBLE); > + if (break_test()) { > + __set_current_state(TASK_RUNNING); Move the setting of the current state to after the out_kill label. -- Steve > + goto out_kill; > + } > schedule_timeout(HZ * SLEEP_TIME); > } > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[RFC PATCH 10/14] ring_buffer: Fix more races when terminating the producer in the benchmark
The commit b44754d8262d3aab8 ("ring_buffer: Allow to exit the ring buffer benchmark immediately") added a hack into ring_buffer_producer() that set @kill_test when kthread_should_stop() returned true. It improved the situation a lot. It stopped the kthread in most cases because the producer spent most of the time in the patched while cycle. But there are still few possible races when kthread_should_stop() is set outside of the cycle. Then we do not set @kill_test and some other checks pass. This patch adds a better fix. It renames @test_kill/TEST_KILL() into a better descriptive @test_error/TEST_ERROR(). Also it introduces break_test() function that checks for both @test_error and kthread_should_stop(). Finally, the new function is used on many locations when the check for @test_error is not enough. Also it adds a missing check into ring_buffer_producer_thread() between setting TASK_INTERRUPTIBLE and calling schedule_timeout(). Otherwise, we might miss a wakeup from kthread_stop(). Finally, it adds the same check also into ring_buffer_consumer() between setting TASK_INTERRUPTIBLE and calling schedule_timeout(). Well, I added this one just for paranoid reasons. If we are here the producer should have been destroyed before and it should have set @reader_finish. But better be safe. Signed-off-by: Petr Mladek --- kernel/trace/ring_buffer_benchmark.c | 65 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/kernel/trace/ring_buffer_benchmark.c b/kernel/trace/ring_buffer_benchmark.c index ccb1a0b95f64..10e0ec9b797f 100644 --- a/kernel/trace/ring_buffer_benchmark.c +++ b/kernel/trace/ring_buffer_benchmark.c @@ -60,12 +60,12 @@ MODULE_PARM_DESC(consumer_fifo, "fifo prio for consumer"); static int read_events; -static int kill_test; +static int test_error; -#define KILL_TEST()\ +#define TEST_ERROR() \ do {\ - if (!kill_test) { \ - kill_test = 1; \ + if (!test_error) { \ + test_error = 1; \ WARN_ON(1); \ } \ } while (0) @@ -75,6 +75,11 @@ enum event_status { EVENT_DROPPED, }; +static bool break_test(void) +{ + return test_error || kthread_should_stop(); +} + static enum event_status read_event(int cpu) { struct ring_buffer_event *event; @@ -87,7 +92,7 @@ static enum event_status read_event(int cpu) entry = ring_buffer_event_data(event); if (*entry != cpu) { - KILL_TEST(); + TEST_ERROR(); return EVENT_DROPPED; } @@ -115,10 +120,13 @@ static enum event_status read_page(int cpu) rpage = bpage; /* The commit may have missed event flags set, clear them */ commit = local_read(&rpage->commit) & 0xf; - for (i = 0; i < commit && !kill_test; i += inc) { + for (i = 0; i < commit ; i += inc) { + + if (break_test()) + break; if (i >= (PAGE_SIZE - offsetof(struct rb_page, data))) { - KILL_TEST(); + TEST_ERROR(); break; } @@ -128,7 +136,7 @@ static enum event_status read_page(int cpu) case RINGBUF_TYPE_PADDING: /* failed writes may be discarded events */ if (!event->time_delta) - KILL_TEST(); + TEST_ERROR(); inc = event->array[0] + 4; break; case RINGBUF_TYPE_TIME_EXTEND: @@ -137,12 +145,12 @@ static enum event_status read_page(int cpu) case 0: entry = ring_buffer_event_data(event); if (*entry != cpu) { - KILL_TEST(); + TEST_ERROR(); break; } read++; if (!event->array[0]) { - KILL_TEST(); + TEST_ERROR(); break; } inc = event->array[0] + 4; @@ -150,17 +158,17 @@ static enum event_status read_page(int cpu) default: entry = ring_buffer_event_data(event); if (*entry != cpu) { -