[comp.sys.transputer] Anarchic protocol ANY

COS99284@UFRJ.BITNET (Luiz Felipe Perrone) (05/16/91)

Dear netters,

  I have tried to use channels of protocol ANY in a very particular
situation and my results were very strange. I use ANY channels so
that one process can send various items of different types of data
to another process that will route the message and save one copy of it.
This latter process must see this message as an array of bytes and
forward it to the apropriate receiver as another array of bytes. Upon
receiving this message the receiver would break the array of bytes into
pieces corresponding to the same types sent by the first process.

  In occam part of this would correspond to (sorry, I can't use square
brackets in my terminal, I'll use parenthesis instead) the following code:
  Obs: the channel is global and declared as CHAN OF ANY; all messages
       are made of a header and a text of variable size

  Process 1 :
      REAL32 r:
      INT i, s, h1, h2:
      BOOL b:
      REAL64 x:
      SEQ
        r := 1.5 (REAL32)
        i := 1
        b := TRUE
        x := 3.1516 (REAL64)
        s :=17 -- size of message text in bytes
        h1, h2 := 0, 0
        to.p2 ! h1; h2; s; r; i; b; x

  Process 2:
      INT h1, h2, i, s:
      (100)BYTE buffer:
      SEQ
        to.p2 ? h1; h2; s::buffer


  Placing STOPs here and there I have observed that Process 1 finishes and
so it sends the message successfully. But what I'm trying to explain is why
Process 2 never finishes. I have some wild guesses such as: the code the
compiler generates for the input command in 2, is not appropriate to receive
the message text (s::buffer) because the channel to.p2 was declared as CHAN
OF ANY and not CHAN OF INT; INT; INT::()INT. Another one is that I may be
experiencing some alignment problem due to retyping conversions.

  If someone knows why this happens or how I could send one message of varying
length with any number of items of any type to a process that will see this
message as a well defined header plus a text defined as an array of bytes
of varying length, please let me know as soon as possible.

  I'm using this in the project of simulation kernel and I have to provide
an elegant, flexible and easy to use interface between the simulator and
the user's logical processes.

  Thank you all.

------------------------------------------------------------------------
Luiz Felipe Perrone
MSc student - COPPE - Dept. of Systems Engineering and Computer Science
Universidade Federal do Rio de Janeiro - Brazil
E-mail: COS99284@UFRJ (BITNET)
Mailing address:  Rua Senador Vergueiro 157/305
                  Flamengo - Rio de Janeiro, RJ - Brazil
                  CEP 22230

Phone number: (55)-(21)-5519063
------------------------------------------------------------------------

jeremy@cs.adelaide.edu.au (Jeremy Webber) (05/16/91)

In article <9105152020.AA15174@theory.TN.CORNELL.EDU> COS99284@UFRJ.BITNET (Luiz Felipe Perrone) writes:

     Process 1:
	   to.p2 ! h1; h2; s; r; i; b; x

     Process 2:
	   to.p2 ? h1; h2; s::buffer


These two message operations are not compabible.  Transputers require that a
receiver of a message expect a message of the same size as the sender is
sending.  The above would work if the Occam message operation translated to one
Transputer message operation, but it doesn't (and in general can't).

Rather, my guess is that in process 1 the Occam compiler is generating  a
separate "out" instruction for each element of the message list, which means
that in process 2 the element list must contain variables of the same type as
the arguments in process 1.

Hence for the above code, the effect is "undefined".

	-jeremy



     Placing STOPs here and there I have observed that Process 1 finishes and
   so it sends the message successfully. But what I'm trying to explain is why
   Process 2 never finishes. I have some wild guesses such as: the code the
   compiler generates for the input command in 2, is not appropriate to receive
   the message text (s::buffer) because the channel to.p2 was declared as CHAN
   OF ANY and not CHAN OF INT; INT; INT::()INT. Another one is that I may be
   experiencing some alignment problem due to retyping conversions.

     If someone knows why this happens or how I could send one message of varying
   length with any number of items of any type to a process that will see this
   message as a well defined header plus a text defined as an array of bytes
   of varying length, please let me know as soon as possible.

     I'm using this in the project of simulation kernel and I have to provide
   an elegant, flexible and easy to use interface between the simulator and
   the user's logical processes.

     Thank you all.

   ------------------------------------------------------------------------
   Luiz Felipe Perrone
   MSc student - COPPE - Dept. of Systems Engineering and Computer Science
   Universidade Federal do Rio de Janeiro - Brazil
   E-mail: COS99284@UFRJ (BITNET)
   Mailing address:  Rua Senador Vergueiro 157/305
		     Flamengo - Rio de Janeiro, RJ - Brazil
		     CEP 22230

   Phone number: (55)-(21)-5519063
   ------------------------------------------------------------------------
--
--
Jeremy Webber			   ACSnet: jeremy@chook.ua.oz
Digital Arts Film and Television,  Internet: jeremy@cs.adelaide.edu.au
3 Milner St, Hindmarsh, SA 5007,   Voicenet: +61 8 346 4534
Australia			   Papernet: +61 8 346 4537 (FAX)

sun@rt.eltn.utwente.nl (Johan Sunter) (05/16/91)

The problem lies in the fact that process 1 tries to iniate 7 communications
while process2 will only listen to three.

By the way, I compiled the problem on our Meiko In-Sun system using Ops and
noticed that process 1 does not terminate, and process 2 does! This consistent
with the previous remark, since the first three communications will succeed.
However, it is not known in advance how many bytes will actually be copied,
this is dependent upon who is first.

The proper way to send these kinds of messages is to use buffers in both
processes and to use RETYPES to write the variables into and read them from
the buffer. Something like this:

    PROC process.1(CHAN OF ANY to.p2)
      [100]BYTE buffer:
      INT s, h1, h2:
      SEQ
        REAL32 r RETYPES [buffer FROM 0 FOR 4]:
        INT i RETYPES [buffer FROM 4 FOR 4]:
        BOOL b RETYPES [buffer FROM 8 FOR 1]:
        REAL64 x RETYPES [buffer FROM 9 FOR 8]:
        SEQ
          r := 1.5 (REAL32)
          i := 1
          b := TRUE
          x := 3.1516 (REAL64)
          s :=17 -- size of message text in bytes
        h1, h2 := 0, 0
        to.p2 ! h1; h2; s::buffer
    :

Notice the channel parameter in the heading! Global channels are definitely
not the way to go!

Johan Sunter
University of Twente
Enschede, Holland,
EE Dept., Control Laboratory
sun@rt.el.utwente.nl

llw@ghostwheel.eng.yale.edu (Louis L. Whitcomb) (05/17/91)

In article <9105152020.AA15174@theory.TN.CORNELL.EDU> COS99284@UFRJ.BITNET (Luiz Felipe Perrone) writes:

>   Dear netters,
>
>     I have tried to use channels of protocol ANY in a very particular
>   situation and my results were very strange...


Greetings:

  The behavior of software and hardware channel communication in
in the Inmos OCCAM2 compiler is not identical.

  Here's why: In all channel transactions, each argument of an "!"  and
"?"  statement is an individual transaction.  The number and length of
the arguments in both the ? and ! must be absolutely *identical* on
both the sending and receiving end.  In your example the seven !
arguments are received by four ? arguments of differing length.
You'll find that the ! has completed, the first four ? arguments have
taken the value of the first four ! arguments, and that the ? is
waiting (forever) for its fifth argument.

  Curiously, you'll find that your code sample will run fine in a
configuration where the channel "to.p2" is a hard link, but not when
it is a soft link. Try it.  The implementation of channel
communication in OCCAM2 behaves differently on hard and soft channels.

  The simplest example of this behavior I know of is the following
buffer process which looks to be a universal, protocol-independent
buffer:

PROC byte.buffer( CHAN OF ANY in, out )

  BYTE data :

  WHILE TRUE
    SEQ
      in  ? data
      out ! data
:

Which works fine over hard channels, but will work on soft channels if
and only if the sending and receiving processes are actually sending
and receiving *individual* bytes.

The moral of the story: If you use OCCAM2, use explicit protocols -
even though they are cumbersome and restrictive.  It is hard to track
down bugs without them.

Note that ihe implementation of channel communication in the newly
released INMOS ANSI C compiler does *not* suffer from this curious
design flaw.

  The Best,

      -Louis.
--
Louis L. Whitcomb              llw@corwin.eng.yale.edu    ph: (203) 432-4237  
Yale Robotics Laboratory                                  fx: (203) 432-7481 
Department of Electrical Engineering, 1968 Yale Station, New Haven, CT 06520

Geraint.Jones@comlab.oxford.ac.uk (05/19/91)

In article <LLW.91May17095750@corwin.eng.yale.edu> llw@ghostwheel.eng.yale.edu (Louis L. Whitcomb) writes (about CHAN OF ANY):
>->  
>->    The behavior of software and hardware channel communication in
>->  in the Inmos OCCAM2 compiler is not identical.
>->  ...
>->    Curiously, you'll find that your code sample will run fine in a
>->  configuration where the channel "to.p2" is a hard link, but not when
>->  it is a soft link. Try it.  The implementation of channel
>->  communication in OCCAM2 behaves differently on hard and soft channels.
>->  ...
>->  The moral of the story: If you use OCCAM2, use explicit protocols -
>->  even though they are cumbersome and restrictive.  It is hard to track
>->  down bugs without them.
>->  
>->  Note that ihe implementation of channel communication in the newly
>->  released INMOS ANSI C compiler does *not* suffer from this curious
>->  design flaw.

I'm not sure what you think is the design flaw: the programs in question
are not guaranteed to work (by the occam2 Reference Manual).  The only
`unexpected' behaviour is that Inmos' occam2 compiler happens to produce
code which makes this invalid non-program do what its author expected in case
the communication is on hard channels.  It is _very_ hard to guarantee that
all incorrect programs do something unexpected; the usual contract with a
language implementor is that all correct programs should only do the
expected.

The moral extracted from the story is fine, though.  Think of CHAN OF ANY
as one of those horrible messes that you end up having to use when the
other end of the channel is attached to something other than an occam process
whose behaviour you are able to determine.
									g

dbc@ecs.soton.ac.uk (Bryan Carpenter) (05/20/91)

In <LLW.91May17095750@corwin.eng.yale.edu> llw@ghostwheel.eng.yale.edu (Louis L. Whitcomb) writes:
>...

>The moral of the story: If you use OCCAM2, use explicit protocols -
>even though they are cumbersome and restrictive.  It is hard to track
>down bugs without them.

>Note that ihe implementation of channel communication in the newly
>released INMOS ANSI C compiler does *not* suffer from this curious
>design flaw.

I haven't looked at inmos C very closely.  How do they get round the 
"design flaw" (if that's what it is)?

Bryan

greeny@wotan.top.cis.syr.edu (Jonathan Greenfield) (05/20/91)

In article <1758@culhua.prg.ox.ac.uk> geraint@prg.ox.ac.uk (Geraint Jones) writes:
>I'm not sure what you think is the design flaw: the programs in question
>are not guaranteed to work (by the occam2 Reference Manual).  The only
>`unexpected' behaviour is that Inmos' occam2 compiler happens to produce
>code which makes this invalid non-program do what its author expected in case
>the communication is on hard channels.  It is _very_ hard to guarantee that
>all incorrect programs do something unexpected; the usual contract with a
>language implementor is that all correct programs should only do the
>expected.

A secure language implementation detects any violation of the language
definition, either at compile-time, or at run-time.  If a language cannot be
implemented in a secure manner, then the language design is flawed.  If a
language can be implemented in a secure manner, but a particular system fails
to do so, then the system design is flawed.

Jonathan

dbc@ecs.soton.ac.uk (Bryan Carpenter) (05/21/91)

In <1991May20.113104.25938@rodan.acs.syr.edu> greeny@wotan.top.cis.syr.edu (Jonathan Greenfield) writes:

>A secure language implementation detects any violation of the language
>definition, either at compile-time, or at run-time.  If a language cannot be
>implemented in a secure manner, then the language design is flawed.  If a
>language can be implemented in a secure manner, but a particular system fails
>to do so, then the system design is flawed.

This seems a bit hard on occam.  The ANY protocol fairly explicitly
*isn't* secure.  It's a low-level thing which, according to the
manual, is only supposed to be used for communicating with non-occam
peripherals and so forth.  For normal occam communication you're
expected to use checked protocols.

Bryan Carpenter

conor@lion.inmos.co.uk (Conor O'Neill) (05/21/91)

The "best" solution is probably to use a combination of counted-array
protocol, run-time assembled tables (I can't think of a better name),
and judicious use of RETYPEs where necessary.
(Yes - work is progressing (slowly) to add records).
I keep wanting to remove CHAN OF ANY from the compiler (:-)

Suppose we want to send a variable number of INTs down a channel;
we can use the following:

PROTOCOL message IS INT :: []INT :

PROC process.1(CHAN OF message to.p2)
  INT x, y, z :
  SEQ
    ...  initialise the variables

    to.p2 ! 3 :: [x, y, z]
:

Then the buffer process can be written as follows:

VAL max.message.size IS 100 : -- your choice here!

PROC buffer(CHAN OF message in, out)
  [max.message.size]INT buf :
  INT len :
  WHILE TRUE
    SEQ
      in  ? len :: buffer
      out ! len :: buffer
:

Unfortunately the `unpacking' process at the other end can't use
"run-time dis-assembled tables"! You have to un-pack the items yourself:

PROC process.2(CHAN OF message from.p1)
  INT x, y, z :
  SEQ

    [3]INT buf :  -- we know we're expecting 3 items
    INT len :
    SEQ
      from.p1 ? len :: buf
      ASSERT(len = 3)  -- check that we got what we're expecting
      x, y, z := buf[0], buf[1], buf[2]

    ... and use x, y, and z here
:

Obviously, if you want to communicate values of different types,
you might have to use RETYPES to assemble them into a buffer.
Alternatively, suppose we want to communicate a collection of
BYTEs and INTs:

PROTOCOL message IS INT :: []BYTE ; INT :: []INT :

then send like this:

to.p2 ! 5::[b1, b2, b3, b4, b5] ; 3::[x, y, z]

You may find that this is actually faster than sending eight
items individually.


Note that ASSERT(VAL BOOL test) is a predefine which has been added
to the D7205 occam compiler; it performs a compile-time test if possible,
otherwise it performs a run-time test.
It is basically equivalent to:

PROC ASSERT(VAL BOOL test)
  IF
    test
      SKIP
    TRUE
      STOP
:
---
Conor O'Neill, Software Group, INMOS Ltd., UK.
UK: conor@inmos.co.uk		US: conor@inmos.com
"It's state-of-the-art" "But it doesn't work!" "That is the state-of-the-art".

conor@lion.inmos.co.uk (Conor O'Neill) (05/21/91)

In article <9105161505.AA01949@rt.el.utwente.nl> sun@rt.eltn.utwente.nl (Johan Sunter) writes:
>    PROC process.1(CHAN OF ANY to.p2)
>      [100]BYTE buffer:
>      INT s, h1, h2:
>      SEQ
>        REAL32 r RETYPES [buffer FROM 0 FOR 4]:
>        INT    i RETYPES [buffer FROM 4 FOR 4]:
>        BOOL   b RETYPES [buffer FROM 8 FOR 1]:
>        REAL64 x RETYPES [buffer FROM 9 FOR 8]:
                                  ^^^^^^^^^^^^

Note that there is an implementation restriction in current INMOS
compilers that this RETYPES must be word-aligned.
It will be caught by a run-time check.
(Yes, I know that this example should be caught at compile-time).

This is because transputers cannot access non-word-aligned objects efficiently.



---
Conor O'Neill, Software Group, INMOS Ltd., UK.
UK: conor@inmos.co.uk		US: conor@inmos.com
"It's state-of-the-art" "But it doesn't work!" "That is the state-of-the-art".

conor@lion.inmos.co.uk (Conor O'Neill) (05/21/91)

In article <LLW.91May17095750@corwin.eng.yale.edu> llw@ghostwheel.eng.yale.edu (Louis L. Whitcomb) writes:
>Note that ihe implementation of channel communication in the newly
>released INMOS ANSI C compiler does *not* suffer from this curious
>design flaw.

I don't know how you got this impression, but the ANSI C compiler
(which was released last August!) uses exactly the same method as occam,
and so behaves in the same way.

---
Conor O'Neill, Software Group, INMOS Ltd., UK.
UK: conor@inmos.co.uk		US: conor@inmos.com
"It's state-of-the-art" "But it doesn't work!" "That is the state-of-the-art".

conor@lion.inmos.co.uk (Conor O'Neill) (05/21/91)

In article <1991May20.113104.25938@rodan.acs.syr.edu> greeny@top.cis.syr.edu (Jonathan Greenfield) writes:
>A secure language implementation detects any violation of the language
>definition, either at compile-time, or at run-time.  If a language cannot be
>implemented in a secure manner, then the language design is flawed.  If a
>language can be implemented in a secure manner, but a particular system fails
>to do so, then the system design is flawed.
>
>Jonathan

The name `Anarchic protocol' indicates that it circumvents any
compiler checking. Once CHAN OF ANY is used, it is no longer a
secure language implementation.

Maybe we should remove CHAN OF ANY (:-)

---
Conor O'Neill, Software Group, INMOS Ltd., UK.
UK: conor@inmos.co.uk		US: conor@inmos.com
"It's state-of-the-art" "But it doesn't work!" "That is the state-of-the-art".

Geraint.Jones@comlab.oxford.ac.uk (05/21/91)

In article <1758@culhua.prg.ox.ac.uk> I wrote:

>  I'm not sure what you think is the design flaw: the programs in question
>  are not guaranteed to work (by the occam2 Reference Manual).  The only
>  `unexpected' behaviour is that Inmos' occam2 compiler happens to produce
>  code which makes this invalid non-program do what its author expected in case
>  the communication is on hard channels.  It is _very_ hard to guarantee that
>  all incorrect programs do something unexpected; the usual contract with a
>  language implementor is that all correct programs should only do the
>  expected.

In article <1991May20.113104.25938@rodan.acs.syr.edu> greeny@top.cis.syr.edu (Jonathan Greenfield) replies:

>  A secure language implementation detects any violation of the language
>  definition, either at compile-time, or at run-time.  If a language cannot be
>  implemented in a secure manner, then the language design is flawed.  If a
>  language can be implemented in a secure manner, but a particular system fails
>  to do so, then the system design is flawed.

But, but, but, come now.  Declaring a `CHAN OF ANY' gives the implementation
the right to assume that the programmer is going to use the channel properly.
That is what it says in the manual.  It is just like all the odd pragmas in
other languages (like those for turning off array bounds checks*) which you use
to assert to the compiler that _you_ the programmer will take responsibility
for guaranteeing a property which the compiler would otherwise be obliged to
check.  If you didn't want to make that guarantee, you didn't ought to have
declared the CHAN OF ANY.  

		( *  I don't know what the equivalent is for C programmers,
		     nor quite how to explain to C programmers what array
		     bounds checks are.					    )

The implementation can only be `secure' in the sense that it implements the
language as defined.  In any non-trivial language with while loops, you
will never get a mechanical guarantee from the compiler that the program
terminates.  In the same way, in any dialect of occam with CHAN OF ANY,
you will not get a mechanically checked guarantee of proper channel use.
And serve you right.  Of course, you might want a compiler for particular
applications to reject CHAN OF ANY declarations, but then it wouldn't be
an occam2 compiler, would it?
									g

greeny@wotan.top.cis.syr.edu (Jonathan Greenfield) (05/23/91)

In article <1772@culhua.prg.ox.ac.uk> geraint@prg.ox.ac.uk (Geraint Jones) writes:
>
>The implementation can only be `secure' in the sense that it implements the
>language as defined.

That's all that I said.  Perhaps I should not have implied more than that.
  
>In any non-trivial language with while loops, you
>will never get a mechanical guarantee from the compiler that the program
>terminates.  In the same way, in any dialect of occam with CHAN OF ANY,
>you will not get a mechanically checked guarantee of proper channel use.
>And serve you right.  Of course, you might want a compiler for particular
>applications to reject CHAN OF ANY declarations, but then it wouldn't be
>an occam2 compiler, would it?

Sure enough, you are correct.  That just says that "unsatisfactorily" matched
processes synchronizing via a CHAN OF ANY can be part of a *valid* occam
program.  (Analogously, as you point out, an infinite loop can be part of a
valid Pascal (for instance) program.)

Now, I'm really not familiar with the occam 2 definition of communication
over a CHAN OF ANY, but the fact that such programs are valid seems to lead
to a problem.  Namely, the parallel composition of two deterministic, valid
processes may yield one (overall) process when the composition is within a
single transputer, and may yield a completely different process (STOP, for
example) when the composition involves two transputers.  

Now I haven't checked, but I have been of the impression that the occam 
definition has intended to make PAR and PLACED PAR identical in composing 
two or more processes into a single (overall) process.  (That is, the only 
difference should be in the system's implementation of the composition.  
Abstractly, the composition is identical.)  If this is the case, then the
system would appear to be doing something to violate the definition of 
occam.

If, on the other hand, occam does prescribe such a differentiation, then
the system is fine, but (at least this feature of) occam sure is a mess.
I know I wouldn't want to be working on the semantics for such language
features (so tied to implementation details).

Any thoughts shedding further or better light on this question shall be
greatly appreciated.


Jonathan

pete@ohm.york.ac.uk (-Pete French.) (05/23/91)

in article <1991May22.112448.22321@rodan.acs.syr.edu>, greeny@wotan.top.cis.syr.edu (Jonathan Greenfield) says:
> 
> Now, I'm really not familiar with the occam 2 definition of communication
> over a CHAN OF ANY, but the fact that such programs are valid seems to lead
> to a problem.  Namely, the parallel composition of two deterministic, valid
> processes may yield one (overall) process when the composition is within a
> single transputer, and may yield a completely different process (STOP, for
> example) when the composition involves two transputers.  
> 
> Now I haven't checked, but I have been of the impression that the occam 
> definition has intended to make PAR and PLACED PAR identical in composing 
> two or more processes into a single (overall) process.  (That is, the only 
> difference should be in the system's implementation of the composition.  
> Abstractly, the composition is identical.)  If this is the case, then the
> system would appear to be doing something to violate the definition of 
> occam.

Yes the two are completely identical - but what you are attempting to do is
to place a program whos behaviour is _UNDEFINED_ usig the two sorts of PAR.
You end up with 2 programs both of whos behaviour is undefined - hence they
may behave differently for the 2 different PARs. It was really a bit of
a red herring for someone to mention that the program would work correctly
if the channel was a link - this is purely an accident of implementation.

CHAN OF ANY is supposed to be used where a channel will be used by moer than
one protocol - but not at the same time. The processes should still
input and output the same types of value. If they dont then the behaviour
cannot be predicted.


To continue this a bit further - I have often come across people trying to
use ANY protocols to make such things as universal buffers by feeding in
various protocols at one end and then reading out as BYTEs at the other.
Perhaps a usefull extension to occam would be something along the lines
of

CHAN OF ANYBYTE

which would work like a CHAN OF ANY but would guarantee that the data would
be sent as single consecutive bytes (this would be very innefficient though)
this would enable general purpose buffers to be written... so you could have
a library process called buffer.4k that could be used between and two channels
of the same type to insert a 4kbyte buffer.

Well written occam programs dont need this of course :-)

-bat.
-- 
-Pete French. (the -bat. )         /  "Two wrongs don't make a right,
Adaptive Systems Engineering      /    - but three lefts do !"

"Look here, a Brit who has obviously been driving in California!"