From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 10.99.1.138 with SMTP id 132mr4018447pgb.162.1494080231079; Sat, 06 May 2017 07:17:11 -0700 (PDT) X-Received: by 10.157.4.34 with SMTP id 31mr811168otc.2.1494080231035; Sat, 06 May 2017 07:17:11 -0700 (PDT) Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!news.glorb.com!c26no978023itd.0!news-out.google.com!x200ni4008itb.0!nntp.google.com!c26no981438itd.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Sat, 6 May 2017 07:17:10 -0700 (PDT) In-Reply-To: Complaints-To: groups-abuse@google.com Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=173.71.201.205; posting-account=QF6XPQoAAABce2NyPxxDAaKdAkN6RgAf NNTP-Posting-Host: 173.71.201.205 References: User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <36434cd8-bc44-4d4a-957d-987fdf106be7@googlegroups.com> Subject: Re: Portable memory barrier? From: Jere Injection-Date: Sat, 06 May 2017 14:17:11 +0000 Content-Type: text/plain; charset=UTF-8 Xref: news.eternal-september.org comp.lang.ada:46681 Date: 2017-05-06T07:17:10-07:00 List-Id: On Saturday, May 6, 2017 at 4:47:59 AM UTC-4, Jeffrey R. Carter wrote: > On 05/06/2017 04:23 AM, Jere wrote: > > > > In one procedure (Producer's Put procedure), I run into the situation where I > > need to update the buffer, then the index (in that order) to ensure that the > > consumer doesn't see the index change before the data is actually there. > > > > From a compiler optimization perspective, I believe I can tackle this with > > the Volatile pragma/aspect. Assuming it works like it does in C, volatile > > variables have to have their accesses in sequence. I think the RM also > > reflects this [0]? > > Volatile means that something other than the program may change the value. It > also means that all tasks of the program see the same sequence of updates. It > does not mean that accesses are non-overlapping. If task A does > > I := I + 1; > > and task B does > > if I > 0 then > > with I marked Volatile, then A may update half of I, B read the partly updated > value, and then A complete its update. > > Atomic means Volatile plus all access are sequential; in the example, if A > begins to update I, B won't read it until A's update is complete. > > For your purposes, marking the (type of the) indices as Atomic should be all you > need. Thanks for the response! I'm good with all that. I'm more worried about situations like these: Task A: -- Do some checks to make sure buffer not full -- Not full, so put data My_Array(Put_Index) := Some_Value; if Put_Index = Buffer_Size then Put_Index := 0; else Put_Index := Put_Index + 1; end if; Task B: if Put_Index = Get_Index then -- empty return False; end if; Result_Value := My_Array(Get_Index); -- Do other operations that update Get_Index Assuming the indexes are atomic and volatile, then I am not worried about partial writes to the indexes. I"m more worried about some architectures that allow for instruction reordering. What I don't want to happen is in Task A that the store to My_Array happens after the update to the Put_Index. If that happens, then there are cases where Task B verifies the buffer isn't empty and tries to access the array but Task A hasn't gotten around to updating the array because the CPU decided to rearrange the stores. In C++, I would handle this with a fence, which is part of the standard. My_Array[Put_Index] = Some_Value; //force CPU to do the previous store before doing ones after the fence std::atomic_thread_fence(std::memory_order_release); if (Put_Index == Buffer_Size){ Put_Index = 0; else Put_Index++; } With that I know that architectures that do reordering and supply a means to prevent that, the appropriate mechanism will be used to ensure Put_Index is updated after My_Array; I'm not so much worried about atomic vs non atomic updates as I am sequential updates of different variables. I'm looking for a language defined way in Ada (or in GNAT if not) that will implement a fence like mechanism on architectures that require it. Side note: If I read it right, you seemed to indicate that volatile has nothing to do with sequence. I'm no Ada expert, so I wanted to ask your interpretation of section 16/3 of C.6. I'm used to C and C++ where if you have two volatile variables being updated like this: Vol_Var_1 = 0; Vol_Var_2 = 23; That the C and C++ standard guarantees the "compiler" will not reorder those two statements. Note this says nothing about atomicness (which is only one reason among others why Volatile is not sufficient for threading). It also doesn't prevent the processor from reordering them. When I read that section in C.6 of the RM, the verbage made me think Ada also prevented the compiler from reordering the statements (again no relation to atomicness or CPU reordering). Is this not the case?