comp.lang.ada
 help / color / mirror / Atom feed
From: Jere <jhb.chat@gmail.com>
Subject: Re: Portable memory barrier?
Date: Tue, 9 May 2017 15:26:26 -0700 (PDT)
Date: 2017-05-09T15:26:26-07:00	[thread overview]
Message-ID: <5b1473fe-c0df-424f-bf22-12ba51db9353@googlegroups.com> (raw)
In-Reply-To: <7b1446ef-8e5f-4f3f-803d-b5a2f47bae0e@googlegroups.com>

On Tuesday, May 9, 2017 at 12:32:38 AM UTC-4, Robert Eachus wrote:
> > I am still digesting some of this, so forgive the simple question:
> > 
> > What prevents the last 3 lines from being reordered like this:
> > r1 := r1 + 1;
> > (Write_Index'Address) := r1;
> > (r3) := r4;
> 
> See above.  Writes cannot be moved past writes.  In practice the write pipe does some magic combining writes to the same cache line, etc.  But it maintains the order on writes to cache.  If you have the right equipment you can peek and see that the writes to main memory are misordered, or even missing.  But without a signal analyzer or some such, you can't peek at main memory bypassing the cache. 

Again, thanks for the responses.

I wanted to get back to this.  I wanted to do some testing, so I generated an 
example of two tasks that each update an index and then copy another (2 stores 
and a load).  I ran it on two different intel processors (all I had to test 
with): i7-4702MQ and i7-6700.  In both cases, there was CPU instruction 
reordering on the two stores (generated assembly had them in the correct order).  
ON the first processor I was running GCC 4.1.2 and pragma Atomic was not working 
as Randy described, so I had to insert a makeshift fence (I declared a protected 
object), which prevented the reordering.  On the second processor I was running 
GCC 4.9.3 which properly inserted synchronization primitives to prevent CPU 
instruction reordering, but if I enabled the GNAT pragma to turn off those 
primitives, it operated like the GCC 4.1.2 version.

I'll put the test code below.  I hope it illustrates the issue I was trying
to describe earlier.

Test_Reorder.ads
********************************************************************************
package Test_Reorder is
   procedure Run;
end Test_Reorder;


Test_Reorder.adb
********************************************************************************
pragma Ada_95;

with Ada.Numerics.Discrete_Random;
with Ada.Text_IO;

package body Test_Reorder is
   
   X      : Integer := 0; 
   Y      : Integer := 0; 
   X_Copy : Integer := 0; 
   Y_Copy : Integer := 0; 
   
   -- In GCC 4.9.3, these pragmas are sufficient
   -- to prevent reordering.  Not in GCC 4.1.2 though
   pragma Atomic(X);
   pragma Atomic(Y);     
   pragma Atomic(X_Copy);
   pragma Atomic(Y_Copy);
   
   -- Uncomment these to get CPU instruction reordering in 4.9.3
--     pragma Disable_Atomic_Synchronization(X);
--     pragma Disable_Atomic_Synchronization(Y);
--     pragma Disable_Atomic_Synchronization(X_Copy);
--     pragma Disable_Atomic_Synchronization(Y_Copy);
   
   package Positive_Random is new Ada.Numerics.Discrete_Random(Positive);
   
   Generator : Positive_Random.Generator;
   
   function Random_Number return Natural is
   begin
      return Positive_Random.Random(Generator) mod 8;
   end Random_Number;
   
   task Task1 is
      entry Start;
      entry Stop;
   end Task1;
   
   task Task2 is
      entry Start;
      entry Stop;
   end Task2;
   
   task body Task1 is
   begin
      loop
         accept Start;
         -- Delay a random amount of time
         while Random_Number /= 0 loop
            null;
         end loop;
         
         X := 1;  -- In GCC 4.1.2 I need to insert a fence after this
         Y_Copy := Y;
         
         accept Stop;         
      end loop;
   end Task1;
   
   task body Task2 is
   begin
      loop
         accept Start;
         -- Delay a random amount of time
         while Random_Number /= 0 loop
            null;
         end loop;
         
         Y := 1;   -- In GCC 4.1.2 I need to insert a fence after this
         X_Copy := X;
         
         accept Stop;         
      end loop;
   end Task2;
   
   procedure Run is 
      Detections : Natural := 0;
      Iterations : Natural := 0;
   begin
      Positive_Random.Reset(Generator);
      
      loop
         X := 0;
         Y := 0;
         Task1.Start;
         Task2.Start;
         
         Task1.Stop;
         Task2.Stop;
         
         Iterations := Iterations + 1;

         -- If both are 0, then at least one got reordered
         if X_Copy = 0 and Y_Copy = 0 then
            Detections := Detections + 1;
            Ada.Text_IO.Put_Line
               (Integer'Image(Detections)
                & " reorders found in "
                & Integer'Image(Iterations)
                & " iterations");
         end if;
         
      end loop;
   end Run;
end Test_Reorder;

  parent reply	other threads:[~2017-05-09 22:26 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-05-06  2:23 Portable memory barrier? Jere
2017-05-06  8:47 ` Jeffrey R. Carter
2017-05-06 14:17   ` Jere
2017-05-06 19:08     ` Dennis Lee Bieber
2017-05-06 19:26     ` Jeffrey R. Carter
2017-05-06 19:41     ` Jeffrey R. Carter
2017-05-06 20:42       ` Niklas Holsti
2017-05-09 19:49     ` Randy Brukardt
2017-05-09 22:07       ` Jere
2017-05-11  1:14         ` Randy Brukardt
2017-05-10 18:28       ` Shark8
2017-05-11  1:17         ` Randy Brukardt
2017-05-11 16:23           ` Jeffrey R. Carter
2017-05-07 20:18 ` Robert Eachus
2017-05-08  7:45   ` Dmitry A. Kazakov
2017-05-08 15:56     ` Robert Eachus
2017-05-08 16:22       ` Dmitry A. Kazakov
2017-05-08 18:39         ` Robert Eachus
2017-05-08 19:18         ` Robert Eachus
2017-05-08 21:09           ` Dmitry A. Kazakov
2017-05-08 23:24             ` Robert Eachus
2017-05-09  0:30               ` Jere
2017-05-09  4:02                 ` Robert Eachus
2017-05-09  4:32                 ` Robert Eachus
2017-05-09  4:44                   ` Robert Eachus
2017-05-09 22:26                   ` Jere [this message]
2017-05-09 20:01                 ` Randy Brukardt
2017-05-09 19:57               ` Randy Brukardt
2017-05-10  0:51                 ` Jere
2017-05-10  5:25                   ` J-P. Rosen
2017-05-10 22:56                     ` Jere
2017-05-11  7:36                       ` Dmitry A. Kazakov
2017-05-13 20:25                         ` Jere
2017-05-10  7:13                   ` Dmitry A. Kazakov
2017-05-10 16:45                     ` Robert Eachus
2017-05-10 17:28                       ` Simon Wright
2017-05-10 23:21                     ` Jere
2017-05-11  0:47                       ` Randy Brukardt
2017-05-13 20:11                         ` Jere
2017-05-15 22:33                           ` Randy Brukardt
2017-05-10 23:30                     ` Jere
2017-05-11  0:38                     ` Randy Brukardt
2017-05-10 16:38                   ` Jeffrey R. Carter
2017-05-10 23:40                     ` Jere
2017-05-10 16:19                 ` Robert Eachus
2017-05-11  1:02                   ` Randy Brukardt
2017-05-11  1:51                     ` Robert Eachus
2017-05-15 22:45                       ` Randy Brukardt
2017-05-08 20:29         ` Niklas Holsti
2017-05-08 21:09           ` Dmitry A. Kazakov
2017-05-09  4:34             ` Niklas Holsti
2017-05-09  6:16               ` Niklas Holsti
2017-05-09  8:34                 ` Dmitry A. Kazakov
2017-05-09 20:18                 ` Randy Brukardt
2017-05-09 20:10           ` Randy Brukardt
2017-05-09  0:05         ` Jere
2017-05-09  8:26           ` Dmitry A. Kazakov
2017-05-09 19:53         ` Randy Brukardt
2017-05-09 20:27           ` Dmitry A. Kazakov
2017-05-11  0:35             ` Randy Brukardt
2017-05-11  8:24               ` Dmitry A. Kazakov
2017-05-15 22:53                 ` Randy Brukardt
2017-05-18 17:44                   ` Dmitry A. Kazakov
2017-05-18 21:01                     ` Randy Brukardt
2017-05-19  7:54                       ` Dmitry A. Kazakov
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox