[Info-vax] yet another sys$qiow question

George Cornelius cornelius at eisner.decus.org
Mon Aug 24 15:07:33 EDT 2015


In article <c3df2959-7432-45f5-8eef-9b0fac0d9e67 at googlegroups.com>, John Reagan <xyzzy1959 at gmail.com> writes:
>[Bob Gezelter] wrote:
>> Going back to Code Generation 101, I would think that a "volatile" would
>> only be relevant within a basic block. As I recall, the definition of a basic
>> block is "one entrance, one exit". Thus, an out-of-line subroutine call
>> ends a basic block by definition.

[...]

John, I have to apologize for starting this long subthread and walking
away for awhile.
 
> Memory barriers and calls have nothing in common.  Reading the Alpha SRM (s=
> ection 5.6.3, Implied Barriers) goes out of its way to say "There are no im=
> plied barriers in Alpha. If an implied barrier for functionally correct acc=
> ess to shared data, it must be written as an explicit instruction."  It the=
> n goes on to list things that have no built-in memory barrier just to pound=
> the point home (entry to PALcode, sending and receiving interrupts, return=
> ing from exceptions/interrupts/machine-checks, swapping context, invalidati=
> ng the translation buffer).  None of those impact any pending reads/writes.

Yes, I noticed the item which states that there are no implied barriers, and
also noticed an item which states that one should not expect the compilers
to insert memory barriers.
 
> As for volatile IOSBs, consider that you have an IOSB, you pass it to $QIO,=
> and keep processing.  Somewhere in the future that I/O will complete, some=
> system level AST will write into that IOSB.  So from your program's point =
> of view, that IOSB gets a new value "between instructions".  You might even=
> be looping on that IOSB waiting for it to turn from 0 to non-0.  You'll ne=
> ed volatile for that.

Please note that this was all in the context of a conversation I was having
with Bob G. and with Hoff, about examining IOSB's and I/O buffers without
fully synchonizing per the Programming Concepts manual.

Hoff questioned my suggestion that buffers should be declared volatile.
Bob wondered why I would even dare look into a buffer given that the
specifications are that its contents must be considered to be
undefined, (and of course in some cases in flux: think direct I/O
and retries), until a status code has been stored in the IOSB.

So I found myself defending things that had nothing to do with the
original context of my post.  Bob G. and Hoff were completely correct,
but in defense of the disputed item in that post - answering "Why
on earth would you want to do _that_?" - I brought up things I had
done a lifetime ago in entirely different environments, including
within interrupt service routines, and which, it turns out, I have not
been doing in VMS except in experiments to determine how the system
might be behaving under the covers.

In the end, though, I stated something which at one time was in
fact true: as soon as you could see a nonzero status value in the
lowest order word of the IOSB, it is safe to look in the buffer.

It turns out, and I in fact had once known, that this is an incorrect
assumption on a multiprocessor Alpha.

[Note that I have been setting my IOSB's volatile, but only
rarely my I/O buffers, and it is clear from the discussion that
neither of these is necessary in typical uses of system services].

The problem for me arose in the cases where would I say "I wonder
if that I/O happened to have completed aleady?", and I see the
status value is stored. In that case I believe an Alpha memory
barrier instruction is needed if I want to continue and treat the
I/O as being truly complete, and the reasoning is that _while_
my code was executing the interrupt servicing code could have
been executing on another processor.  If I happen to see a status
value in the IOSB, it is clear from the other processor's point
of view the buffer is safe; but from my processor, due to memory
write reordering, I must either issue an MB instruction, or
actually perform a system service aimed at synchronizing I/O,
before I make use of anything other than that one particular
word I examined in the IOSB.

The officially sanctioned synchronization service would be $SYNCH,
but, as a side effect, most other synchronization type services,
e.g., $WAITFR, basically guarantee the issuance a memory barrier,
and, since this will happen within the same code stream/thread as
mine, could be assumed to protect me adequately. In general, if I
_happen_ _to_ _notice_ that the IOSB status value is nonzero,
I really should execute some kind of synchronization service just
to assure it is safe to continue.

Similar considerations apply to operations involving other
system services which complete asynchronously.

So, yes, I believe the code in the examples in the system
service related manuals and in the programming concepts
manual can be relied upon.  The two caveats are:

 o You need appropriate _volatile_ declarations if you
   will be watching for an IOSB or an item in your I/O buffer
   to change if that change will occur independently of a
   sequence of code(basic block?) uninterrupted by calls to
   separately compiled routines.

 o You will need a memory barrier, or a call to _any_
   system synchronization class service, in order to
   be sure you can examine your I/O buffer once you
   have seen an IOSB status value stored but have not
   officially waited for completion via a synchronization
   service.

It is the second item which is a special requirement
introduced with the Alpha, I believe, and which was the crux
of the issue that arose in my discussion with Hoff and Bob G.

So as I indicated, the weakly volatile compiler flagging
you mentioned is all that is needed if you are very careful
to follow what's in the manual and never examine the IOSB,
or the buffer, without using a system service to assure that
you have a true completion.

George



More information about the Info-vax mailing list