diff mbox

[ODP/PATCH] Remove race condition and simplify barrier implementation

Message ID 1395247593-2941-1-git-send-email-bill.fischofer@linaro.org
State Superseded, archived
Headers show

Commit Message

Bill Fischofer March 19, 2014, 4:46 p.m. UTC
Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
---
 include/odp_barrier.h                       |  3 +-
 platform/linux-generic/source/odp_barrier.c | 46 +++++++++++++----------------
 2 files changed, 21 insertions(+), 28 deletions(-)

1.8.3.2

Comments

Maxim Uvarov March 19, 2014, 4:49 p.m. UTC | #1
Bill, can you please add v1, v2, v3 for the patches for better thread 
separation?

Thanks,
Maxim.

On 03/19/2014 08:46 PM, Bill Fischofer wrote:
> Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
> ---
>   include/odp_barrier.h                       |  3 +-
>   platform/linux-generic/source/odp_barrier.c | 46 +++++++++++++----------------
>   2 files changed, 21 insertions(+), 28 deletions(-)
>
> diff --git a/include/odp_barrier.h b/include/odp_barrier.h
> index bb4a6c5..0a1404b 100644
> --- a/include/odp_barrier.h
> +++ b/include/odp_barrier.h
> @@ -28,8 +28,7 @@ extern "C" {
>    */
>   typedef struct odp_barrier_t {
>   	int              count;
> -	odp_atomic_int_t in;
> -	odp_atomic_int_t out;
> +	odp_atomic_int_t bar;
>   } odp_barrier_t;
>   
>   
> diff --git a/platform/linux-generic/source/odp_barrier.c b/platform/linux-generic/source/odp_barrier.c
> index 64fbdb9..9dc6fb5 100644
> --- a/platform/linux-generic/source/odp_barrier.c
> +++ b/platform/linux-generic/source/odp_barrier.c
> @@ -11,41 +11,35 @@
>   void odp_barrier_init_count(odp_barrier_t *barrier, int count)
>   {
>   	barrier->count = count;
> -	barrier->in    = 0;
> -	barrier->out   = count - 1;
> -	odp_sync_stores();
> +	barrier->bar = 0;
> +	odp_sync_stores();
>   }
>   
> +/*
> + * Efficient barrier_sync -
> + *
> + *   Barriers are initialized with a count of the number of callers
> + *   that must sync on the barrier before any may proceed.
> + *
> + *   To avoid race conditions and to permit the barrier to be fully
> + *   reusable, the barrier value cycles between 0..2*count-1. When
> + *   synchronizing the wasless variable simply tracks which half of
> + *   the cycle the barrier was in upon entry.  Exit is when the
> + *   barrier crosses to the other half of the cycle.
> + */
>   
>   void odp_barrier_sync(odp_barrier_t *barrier)
>   {
>   	int count;
> +	int wasless;
>   
> -	odp_sync_stores();
> -
> -	count = odp_atomic_fetch_inc_int(&barrier->in);
> -
> -	if (count == barrier->count - 1) {
> -		/* If last thread, release others */
> -		barrier->in = 0;
> -		odp_sync_stores();
> -
> -		/* Wait for others to exit */
> -		while (barrier->out)
> -			odp_spin();
> -
> -		/* Ready, reset out counter */
> -		barrier->out = barrier->count - 1;
> -		odp_sync_stores();
> +	wasless = barrier->bar < barrier->count;
> +	count = odp_atomic_fetch_inc_int(&barrier->bar);
>   
> +	if (count == 2*barrier->count-1) {
> +		barrier->bar = 0;
>   	} else {
> -		/* Wait for the last thread*/
> -		while (barrier->in)
> -			odp_spin();
> -
> -		/* Ready */
> -		odp_atomic_dec_int(&barrier->out);
> -		odp_mem_barrier();
> +	  while ((barrier->bar < barrier->count) == wasless)
> +	    odp_spin();
>   	}
>   }
Bill Fischofer March 19, 2014, 4:53 p.m. UTC | #2
OK, do you want me to do that for this version or is it OK and will do that
if there are any follow-ons?

Bill


On Wed, Mar 19, 2014 at 11:49 AM, Maxim Uvarov <maxim.uvarov@linaro.org>wrote:

> Bill, can you please add v1, v2, v3 for the patches for better thread
> separation?
>
> Thanks,
> Maxim.
>
>
> On 03/19/2014 08:46 PM, Bill Fischofer wrote:
>
>> Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>
>> ---
>>   include/odp_barrier.h                       |  3 +-
>>   platform/linux-generic/source/odp_barrier.c | 46
>> +++++++++++++----------------
>>   2 files changed, 21 insertions(+), 28 deletions(-)
>>
>> diff --git a/include/odp_barrier.h b/include/odp_barrier.h
>> index bb4a6c5..0a1404b 100644
>> --- a/include/odp_barrier.h
>> +++ b/include/odp_barrier.h
>> @@ -28,8 +28,7 @@ extern "C" {
>>    */
>>   typedef struct odp_barrier_t {
>>         int              count;
>> -       odp_atomic_int_t in;
>> -       odp_atomic_int_t out;
>> +       odp_atomic_int_t bar;
>>   } odp_barrier_t;
>>     diff --git a/platform/linux-generic/source/odp_barrier.c
>> b/platform/linux-generic/source/odp_barrier.c
>> index 64fbdb9..9dc6fb5 100644
>> --- a/platform/linux-generic/source/odp_barrier.c
>> +++ b/platform/linux-generic/source/odp_barrier.c
>> @@ -11,41 +11,35 @@
>>   void odp_barrier_init_count(odp_barrier_t *barrier, int count)
>>   {
>>         barrier->count = count;
>> -       barrier->in    = 0;
>> -       barrier->out   = count - 1;
>> -       odp_sync_stores();
>> +       barrier->bar = 0;
>> +       odp_sync_stores();
>>   }
>>   +/*
>> + * Efficient barrier_sync -
>> + *
>> + *   Barriers are initialized with a count of the number of callers
>> + *   that must sync on the barrier before any may proceed.
>> + *
>> + *   To avoid race conditions and to permit the barrier to be fully
>> + *   reusable, the barrier value cycles between 0..2*count-1. When
>> + *   synchronizing the wasless variable simply tracks which half of
>> + *   the cycle the barrier was in upon entry.  Exit is when the
>> + *   barrier crosses to the other half of the cycle.
>> + */
>>     void odp_barrier_sync(odp_barrier_t *barrier)
>>   {
>>         int count;
>> +       int wasless;
>>   -     odp_sync_stores();
>> -
>> -       count = odp_atomic_fetch_inc_int(&barrier->in);
>> -
>> -       if (count == barrier->count - 1) {
>> -               /* If last thread, release others */
>> -               barrier->in = 0;
>> -               odp_sync_stores();
>> -
>> -               /* Wait for others to exit */
>> -               while (barrier->out)
>> -                       odp_spin();
>> -
>> -               /* Ready, reset out counter */
>> -               barrier->out = barrier->count - 1;
>> -               odp_sync_stores();
>> +       wasless = barrier->bar < barrier->count;
>> +       count = odp_atomic_fetch_inc_int(&barrier->bar);
>>   +     if (count == 2*barrier->count-1) {
>> +               barrier->bar = 0;
>>         } else {
>> -               /* Wait for the last thread*/
>> -               while (barrier->in)
>> -                       odp_spin();
>> -
>> -               /* Ready */
>> -               odp_atomic_dec_int(&barrier->out);
>> -               odp_mem_barrier();
>> +         while ((barrier->bar < barrier->count) == wasless)
>> +           odp_spin();
>>         }
>>   }
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "LNG ODP Sub-team - lng-odp@linaro.org" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to lng-odp+unsubscribe@linaro.org.
> To post to this group, send email to lng-odp@linaro.org.
> Visit this group at http://groups.google.com/a/linaro.org/group/lng-odp/.
> To view this discussion on the web visit https://groups.google.com/a/
> linaro.org/d/msgid/lng-odp/5329CAA7.3030606%40linaro.org.
>
> For more options, visit https://groups.google.com/a/linaro.org/d/optout.
>
Maxim Uvarov March 19, 2014, 4:55 p.m. UTC | #3
On 03/19/2014 08:53 PM, Bill Fischofer wrote:
> OK, do you want me to do that for this version or is it OK and will do 
> that if there are any follow-ons?
>
> Bill
>
yes, please. It will help to see the latest version for everyone.

Maxim.

>
> On Wed, Mar 19, 2014 at 11:49 AM, Maxim Uvarov 
> <maxim.uvarov@linaro.org <mailto:maxim.uvarov@linaro.org>> wrote:
>
>     Bill, can you please add v1, v2, v3 for the patches for better
>     thread separation?
>
>     Thanks,
>     Maxim.
>
>
>     On 03/19/2014 08:46 PM, Bill Fischofer wrote:
>
>         Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org
>         <mailto:bill.fischofer@linaro.org>>
>         ---
>           include/odp_barrier.h                       |  3 +-
>           platform/linux-generic/source/odp_barrier.c | 46
>         +++++++++++++----------------
>           2 files changed, 21 insertions(+), 28 deletions(-)
>
>         diff --git a/include/odp_barrier.h b/include/odp_barrier.h
>         index bb4a6c5..0a1404b 100644
>         --- a/include/odp_barrier.h
>         +++ b/include/odp_barrier.h
>         @@ -28,8 +28,7 @@ extern "C" {
>            */
>           typedef struct odp_barrier_t {
>                 int              count;
>         -       odp_atomic_int_t in;
>         -       odp_atomic_int_t out;
>         +       odp_atomic_int_t bar;
>           } odp_barrier_t;
>             diff --git a/platform/linux-generic/source/odp_barrier.c
>         b/platform/linux-generic/source/odp_barrier.c
>         index 64fbdb9..9dc6fb5 100644
>         --- a/platform/linux-generic/source/odp_barrier.c
>         +++ b/platform/linux-generic/source/odp_barrier.c
>         @@ -11,41 +11,35 @@
>           void odp_barrier_init_count(odp_barrier_t *barrier, int count)
>           {
>                 barrier->count = count;
>         -       barrier->in    = 0;
>         -       barrier->out   = count - 1;
>         -       odp_sync_stores();
>         +       barrier->bar = 0;
>         +       odp_sync_stores();
>           }
>           +/*
>         + * Efficient barrier_sync -
>         + *
>         + *   Barriers are initialized with a count of the number of
>         callers
>         + *   that must sync on the barrier before any may proceed.
>         + *
>         + *   To avoid race conditions and to permit the barrier to be
>         fully
>         + *   reusable, the barrier value cycles between 0..2*count-1.
>         When
>         + *   synchronizing the wasless variable simply tracks which
>         half of
>         + *   the cycle the barrier was in upon entry.  Exit is when the
>         + *   barrier crosses to the other half of the cycle.
>         + */
>             void odp_barrier_sync(odp_barrier_t *barrier)
>           {
>                 int count;
>         +       int wasless;
>           -     odp_sync_stores();
>         -
>         -       count = odp_atomic_fetch_inc_int(&barrier->in);
>         -
>         -       if (count == barrier->count - 1) {
>         -               /* If last thread, release others */
>         -               barrier->in = 0;
>         -               odp_sync_stores();
>         -
>         -               /* Wait for others to exit */
>         -               while (barrier->out)
>         -                       odp_spin();
>         -
>         -               /* Ready, reset out counter */
>         -               barrier->out = barrier->count - 1;
>         -               odp_sync_stores();
>         +       wasless = barrier->bar < barrier->count;
>         +       count = odp_atomic_fetch_inc_int(&barrier->bar);
>           +     if (count == 2*barrier->count-1) {
>         +               barrier->bar = 0;
>                 } else {
>         -               /* Wait for the last thread*/
>         -               while (barrier->in)
>         -                       odp_spin();
>         -
>         -               /* Ready */
>         -               odp_atomic_dec_int(&barrier->out);
>         -               odp_mem_barrier();
>         +         while ((barrier->bar < barrier->count) == wasless)
>         +           odp_spin();
>                 }
>           }
>
>
>     -- 
>     You received this message because you are subscribed to the Google
>     Groups "LNG ODP Sub-team - lng-odp@linaro.org
>     <mailto:lng-odp@linaro.org>" group.
>     To unsubscribe from this group and stop receiving emails from it,
>     send an email to lng-odp+unsubscribe@linaro.org
>     <mailto:lng-odp%2Bunsubscribe@linaro.org>.
>     To post to this group, send email to lng-odp@linaro.org
>     <mailto:lng-odp@linaro.org>.
>     Visit this group at
>     http://groups.google.com/a/linaro.org/group/lng-odp/.
>     To view this discussion on the web visit
>     https://groups.google.com/a/linaro.org/d/msgid/lng-odp/5329CAA7.3030606%40linaro.org.
>
>
>     For more options, visit
>     https://groups.google.com/a/linaro.org/d/optout.
>
>
Bill Fischofer March 19, 2014, 4:56 p.m. UTC | #4
Done.  Latest patch is marked v3.

Bill


On Wed, Mar 19, 2014 at 11:55 AM, Maxim Uvarov <maxim.uvarov@linaro.org>wrote:

> On 03/19/2014 08:53 PM, Bill Fischofer wrote:
>
>> OK, do you want me to do that for this version or is it OK and will do
>> that if there are any follow-ons?
>>
>> Bill
>>
>>  yes, please. It will help to see the latest version for everyone.
>
> Maxim.
>
>
>> On Wed, Mar 19, 2014 at 11:49 AM, Maxim Uvarov <maxim.uvarov@linaro.org<mailto:
>> maxim.uvarov@linaro.org>> wrote:
>>
>>     Bill, can you please add v1, v2, v3 for the patches for better
>>     thread separation?
>>
>>     Thanks,
>>     Maxim.
>>
>>
>>     On 03/19/2014 08:46 PM, Bill Fischofer wrote:
>>
>>         Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org
>>         <mailto:bill.fischofer@linaro.org>>
>>
>>         ---
>>           include/odp_barrier.h                       |  3 +-
>>           platform/linux-generic/source/odp_barrier.c | 46
>>         +++++++++++++----------------
>>           2 files changed, 21 insertions(+), 28 deletions(-)
>>
>>         diff --git a/include/odp_barrier.h b/include/odp_barrier.h
>>         index bb4a6c5..0a1404b 100644
>>         --- a/include/odp_barrier.h
>>         +++ b/include/odp_barrier.h
>>         @@ -28,8 +28,7 @@ extern "C" {
>>            */
>>           typedef struct odp_barrier_t {
>>                 int              count;
>>         -       odp_atomic_int_t in;
>>         -       odp_atomic_int_t out;
>>         +       odp_atomic_int_t bar;
>>           } odp_barrier_t;
>>             diff --git a/platform/linux-generic/source/odp_barrier.c
>>         b/platform/linux-generic/source/odp_barrier.c
>>         index 64fbdb9..9dc6fb5 100644
>>         --- a/platform/linux-generic/source/odp_barrier.c
>>         +++ b/platform/linux-generic/source/odp_barrier.c
>>         @@ -11,41 +11,35 @@
>>           void odp_barrier_init_count(odp_barrier_t *barrier, int count)
>>           {
>>                 barrier->count = count;
>>         -       barrier->in    = 0;
>>         -       barrier->out   = count - 1;
>>         -       odp_sync_stores();
>>         +       barrier->bar = 0;
>>         +       odp_sync_stores();
>>           }
>>           +/*
>>         + * Efficient barrier_sync -
>>         + *
>>         + *   Barriers are initialized with a count of the number of
>>         callers
>>         + *   that must sync on the barrier before any may proceed.
>>         + *
>>         + *   To avoid race conditions and to permit the barrier to be
>>         fully
>>         + *   reusable, the barrier value cycles between 0..2*count-1.
>>         When
>>         + *   synchronizing the wasless variable simply tracks which
>>         half of
>>         + *   the cycle the barrier was in upon entry.  Exit is when the
>>         + *   barrier crosses to the other half of the cycle.
>>         + */
>>             void odp_barrier_sync(odp_barrier_t *barrier)
>>           {
>>                 int count;
>>         +       int wasless;
>>           -     odp_sync_stores();
>>         -
>>         -       count = odp_atomic_fetch_inc_int(&barrier->in);
>>         -
>>         -       if (count == barrier->count - 1) {
>>         -               /* If last thread, release others */
>>         -               barrier->in = 0;
>>         -               odp_sync_stores();
>>         -
>>         -               /* Wait for others to exit */
>>         -               while (barrier->out)
>>         -                       odp_spin();
>>         -
>>         -               /* Ready, reset out counter */
>>         -               barrier->out = barrier->count - 1;
>>         -               odp_sync_stores();
>>         +       wasless = barrier->bar < barrier->count;
>>         +       count = odp_atomic_fetch_inc_int(&barrier->bar);
>>           +     if (count == 2*barrier->count-1) {
>>         +               barrier->bar = 0;
>>                 } else {
>>         -               /* Wait for the last thread*/
>>         -               while (barrier->in)
>>         -                       odp_spin();
>>         -
>>         -               /* Ready */
>>         -               odp_atomic_dec_int(&barrier->out);
>>         -               odp_mem_barrier();
>>         +         while ((barrier->bar < barrier->count) == wasless)
>>         +           odp_spin();
>>                 }
>>           }
>>
>>
>>     --     You received this message because you are subscribed to the
>> Google
>>     Groups "LNG ODP Sub-team - lng-odp@linaro.org
>>     <mailto:lng-odp@linaro.org>" group.
>>
>>     To unsubscribe from this group and stop receiving emails from it,
>>     send an email to lng-odp+unsubscribe@linaro.org
>>     <mailto:lng-odp%2Bunsubscribe@linaro.org>.
>>
>>     To post to this group, send email to lng-odp@linaro.org
>>     <mailto:lng-odp@linaro.org>.
>>
>>     Visit this group at
>>     http://groups.google.com/a/linaro.org/group/lng-odp/.
>>     To view this discussion on the web visit
>>     https://groups.google.com/a/linaro.org/d/msgid/lng-odp/
>> 5329CAA7.3030606%40linaro.org.
>>
>>
>>     For more options, visit
>>     https://groups.google.com/a/linaro.org/d/optout.
>>
>>
>>
>
diff mbox

Patch

diff --git a/include/odp_barrier.h b/include/odp_barrier.h
index bb4a6c5..0a1404b 100644
--- a/include/odp_barrier.h
+++ b/include/odp_barrier.h
@@ -28,8 +28,7 @@  extern "C" {
  */
 typedef struct odp_barrier_t {
 	int              count;
-	odp_atomic_int_t in;
-	odp_atomic_int_t out;
+	odp_atomic_int_t bar;
 } odp_barrier_t;
 
 
diff --git a/platform/linux-generic/source/odp_barrier.c b/platform/linux-generic/source/odp_barrier.c
index 64fbdb9..9dc6fb5 100644
--- a/platform/linux-generic/source/odp_barrier.c
+++ b/platform/linux-generic/source/odp_barrier.c
@@ -11,41 +11,35 @@ 
 void odp_barrier_init_count(odp_barrier_t *barrier, int count)
 {
 	barrier->count = count;
-	barrier->in    = 0;
-	barrier->out   = count - 1;
-	odp_sync_stores();
+	barrier->bar = 0;
+	odp_sync_stores();
 }
 
+/*
+ * Efficient barrier_sync -
+ *
+ *   Barriers are initialized with a count of the number of callers
+ *   that must sync on the barrier before any may proceed.
+ *
+ *   To avoid race conditions and to permit the barrier to be fully
+ *   reusable, the barrier value cycles between 0..2*count-1. When
+ *   synchronizing the wasless variable simply tracks which half of
+ *   the cycle the barrier was in upon entry.  Exit is when the
+ *   barrier crosses to the other half of the cycle.
+ */
 
 void odp_barrier_sync(odp_barrier_t *barrier)
 {
 	int count;
+	int wasless;
 
-	odp_sync_stores();
-
-	count = odp_atomic_fetch_inc_int(&barrier->in);
-
-	if (count == barrier->count - 1) {
-		/* If last thread, release others */
-		barrier->in = 0;
-		odp_sync_stores();
-
-		/* Wait for others to exit */
-		while (barrier->out)
-			odp_spin();
-
-		/* Ready, reset out counter */
-		barrier->out = barrier->count - 1;
-		odp_sync_stores();
+	wasless = barrier->bar < barrier->count;
+	count = odp_atomic_fetch_inc_int(&barrier->bar);
 
+	if (count == 2*barrier->count-1) {
+		barrier->bar = 0;
 	} else {
-		/* Wait for the last thread*/
-		while (barrier->in)
-			odp_spin();
-
-		/* Ready */
-		odp_atomic_dec_int(&barrier->out);
-		odp_mem_barrier();
+	  while ((barrier->bar < barrier->count) == wasless)
+	    odp_spin();
 	}
 }
--