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 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Simon Clubley Newsgroups: comp.lang.ada Subject: Re: Oberon and Wirthian languages Date: Tue, 22 Apr 2014 20:46:40 +0000 (UTC) Organization: A noiseless patient Spider Message-ID: References: <1ljwj8f.1wqbhvuabsdw1N%csampson@inetworld.net> <51c7d6d4-e3be-44d5-a4ce-f7e875345588@googlegroups.com> <%J32v.70539$kp1.45343@fx14.iad> <8761m535e4.fsf_-_@ludovic-brenta.org> Injection-Date: Tue, 22 Apr 2014 20:46:40 +0000 (UTC) Injection-Info: mx05.eternal-september.org; posting-host="e458ff8b81bc0c159989eb0e36c6e372"; logging-data="20028"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19HzHkJd0aHqUbE+oHOZDpJJ1jrtZiroCU=" User-Agent: slrn/0.9.8.1 (VMS/Multinet) Cancel-Lock: sha1:zRHCnQkNTPSfdCJn2XjN+7ljmIk= Xref: news.eternal-september.org comp.lang.ada:19502 Date: 2014-04-22T20:46:40+00:00 List-Id: On 2014-04-22, Niklas Holsti wrote: > On 14-04-22 15:25 , Simon Clubley wrote: >> >> In general memory mapped I/O you have to do a register read/modify bit >> field/register write sequence in units of the register size. >> >> Consider a atomic record with 3 bit fields called A, B and C. >> >> Now consider a Ada record assignment statement which sets the values of >> the 3 bit fields. The question is how is the assignment to the 3 bit >> fields turned into code ? > > If the record variable Rec has the Atomic aspect, then by the Ada RM any > assignment Rec := expr must write Rec exactly once, indivisibly, and > this write should (per implementation advice) be implemented by a single > store instruction. This applies whatever the right-hand-side expr is. > > Note, however, that if the right-hand-side expr includes some references > to (i.e. reads of) Rec, then there is no guarantee that the read-write > sequence as a whole is indivisible. > >> Is it something like this (which is how it looks in C with masks): > > Here one should separate between C 2011 on the one hand and earlier C > standards on the other. (For C 2011 my reference is the "final" draft > N1570, which is on the web.) > I was recently pointed to this document over in comp.arch.embedded and it's on my list of things to read but I have not yet done that. My knowledge of C comes from versions of C prior to C 2011. > In C 2011, a "compound assignment is a read-modify-write operation with > memory_order_seq_cst memory order semantics". That is, in C 2011 an > update like "v &= mask", where v is an _Atomic variable, is an atomic > *update* with respect to other C threads (but perhaps not with respect > to other memory bus activity; I admit to an incomplete understanding > here). I admit I have not read the C 2011 standard yet, but I don't see how protecting against other memory bus activity is possible when you have interrupts active (unless you turn off interrupts during the update sequence). Declaring something as "_Atomic" doesn't change the fact it's still a read/modify/write sequence which is generated for most processors. > Note that this is rather different from the meaning of the Atomic > aspect in Ada, which only makes each read indivisible, and each write > indivisible, but does not guarantee indivisibility of some > read-modify-write sequence. > And I don't see how the C 2011 version does either when the same variable is referenced in both a interrupt handler and the main program. > In earlier C standards such as the 1999 standard, the only concept of > atomicity was the predefined type sig_atomic_t, which corresponds > closely to the Ada Atomic aspect, that is, the whole variable can be > read or written with one memory access. > >> ldr r2, [r3, #register_offset] >> -- Load device register contents into r2 >> -- r3 contains device base address >> orr r2, r2, #1 -- Set bit field A to 1 >> {Additional code here to modify bitfields B and C} >> str r2, [r3, #register_offset] >> -- Write all changes to device register at once > > Yes, this looks like an Ada assignment of the form > > Tmp := Rec; > Rec := (A => 1, B => expr1, C => expr2, D => Tmp.D, E => Tmp.E, ...); > > where Rec has aspect Atomic and assuming that the compiler was able to > optimize out the "no effect" expressions for the unchanged components D, > E, .... Note that the following "simpler" assignment > > Rec := (A => 1, B => expr1, C => expr2, D => Rec.D, E => Rec.E, ...); > > cannot give the code above -- the two (or more) uses of Rec in the > aggregate force the code to read (load) Rec two (or more) times, because > an Atomic variable is also Volatile. (That is how I understand it, but > I'm not entirely sure if each appearance of an object's name in the > source code as a primary implies the evaluation of the object and > therefore a "read" of the object.) This assumes a reasonable > implementation of the Volatile aspect. > Ok, now that's interesting. I would not have assumed the compiler would do the read multiple times in this specific case. I would have assumed the Volatile attribute would be satisfied in this specific case by doing the read _once_ at the start of the generated code and only generating code to modify the A, B and C bitfields before writing everything back in one step by using a single store opcode. >> or is the Ada compiler allowed to do this: >> >> ldr r2, [r3, #register_offset] >> orr r2, r2, #1 -- Set bit field A to 1 >> str r2, [r3, #register_offset] -- Update bit field A only >> >> ldr r2, [r3, #register_offset] >> {Code here to modify bitfield B} >> str r2, [r3, #register_offset] -- Update bit field B only >> >> ldr r2, [r3, #register_offset] >> {Code here to modify bitfield C} >> str r2, [r3, #register_offset] -- Update bit field C only > > No, three stores to Rec can result only if the source code contains > three assignments to Rec as a whole, or some assignments to components > of Rec. > Good. That's what I thought/hoped, but I wasn't 100% sure after reading the Ada 95 RM. >> Ie: performs a atomic update of each bit field, > > In what sense do you call these bit-field updates "atomic"? > When the update is done using a single store to update all the changes to the device register in one non-interruptible opcode. It's also what I understand the Ada 95 RM to mean as well. Thank you for having taken the time to write the detailed analysis above; it was very helpful seeing another person's understanding of these issues. Thanks, Simon. -- Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP Microsoft: Bringing you 1980s technology to a 21st century world