Re: [RFC PATCH 10/14] ring_buffer: Fix more races when terminating the producer in the benchmark

2015-09-07 Thread Oleg Nesterov
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

2015-09-04 Thread Petr Mladek
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

2015-08-03 Thread Steven Rostedt
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

2015-07-28 Thread Petr Mladek
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) {
-