AMDC-96 Reference

Revision 1.2.1.3


Locations

A location has three components:

The AMDC system polls the locations to see if there is anything to do. If it finds a location with messages in its input queue, it will get the first message from the queue and execute the message's script, passing the script pointers to the message and the location.

Here are functions that operate on locations:

void amdc_putLoc(Location loc, Message msg);
put the message msg into the table at the location loc. The message will be associated with its tag field. More than one message with the same tag field may be put in the table: messages in the table are sorted by tag in increasing order. Do nothing if msg is NULL.
Message amdc_getLoc(Location loc, Tag tag);
removes and returns the first message from the table in loc which has the tag field tag. Returns NULL if there is no such message.
Message amdc_getArbLoc(Location loc);
removes and returns an arbitrary message from the table at location loc. Returns NULL if there is no message in the table.
int amdc_numLoc(Location loc, Tag tag);
returns the count of messages in the table at loc which have the tag tag.
int amdc_presentLoc(Location loc, Tag tag);
returns TRUE if there are any messages in the table at loc which have the tag tag; this is faster than using the value returned by amdc_numLoc() to decide whether messages are present or not.
Tag amdc_firstTagLoc(Location loc);
returns the first tag in ascending order of any message in the table at location loc. Returns NO_MSG_TAG if the table is empty.
Tag amdc_nextTagLoc(Location loc, Tag prev);
returns the next tag in ascending order of any message in the table at loc following tag prev. Returns NO_MSG_TAG if there is no message with a higher tag than prev.
LocName amdc_getNameOfLoc(Location loc);
returns the name of the location loc.
void amdc_enqueueAtLoc(Location loc, Message msg);
puts the message msg at the end of the input queue of location loc. It performs no operation if the message is NULL.

Location names

A location name is composed of a symbol and an array of three unsigned long integers.

A location name is of data type LocName. Its definition is


#define NUM_X 3

typedef struct { Symbol S; unsigned long X[NUM_X];} LocName;

Experience has shown that three long integers are usually enough without wasting too much space.

Locations are distributed over the nodes (machines, processes) of a parallel computer in a manner controlled by the kind of symbol in the location's name.

Here are the procedures used to initialize a location name:

LocName amdc_3DLocName(Symbol symbol, unsigned long X0, unsigned long X1, unsigned long X2);
allocate a new structure of type LocName: the symbol field is initialized to symbol, and the array of three unsigned integers is filled up with X0 at index 0, with X1 at index 1 and X2 at index 2.
LocName amdc_2DLocName(Symbol symbol, unsigned long X0, unsigned long X1);
allocate a new structure of type LocName: the symbol field is initialized to symbol, and the array of three unsigned integers is filled up with X0 at index 0, with X1 at index 1 and 0 at index 2.
LocName amdc_1DLocName(Symbol symbol, unsigned long X0);
allocate a new structure of type LocName: the symbol field is initialized to symbol, and the array of three unsigned integers is filled up with X0 at index 0, and with zeros in all other X fields.
LocName amdc_0DLocName(Symbol symbol);
allocate a new structure of type LocName: the symbol field is initialized to symbol, and zeros in all the X fields.

Note that there is no way to change a location's name once the location has been created.


Symbols

Symbols represent names of parallel/distributed data structures.

Symbol creation:

Symbol amdc_newSymbol(int kind);
allocate a new symbol at run time of kind kind.
AMDC_AbsoluteSymbol(I, K)
allocate a symbol at compile time. I is a small positive integer. K is a kind.

Kinds of symbols:

AMDC_SYMB_0
allocates locations on node 0. Don't use this unless, e.g., only node zero can access I/O.
AMDC_SYMB_X0
allocates locations on the node whose number is loc.X[0]%numberOfNodes.
AMDC_SYMB_HASH
allocates locations by hashing their names. Use this to spread computation statistically via the law of large numbers.
AMDC_SYMB_HERE
allocate the location on the same node that created the symbol.

Predefined symbols:

AMDC_NULL_SYMBOL
AbsoluteSymbol(0,SYMB_0): Used to represent null pointers.
AMDC_PROCESS_SYMBOL
AbsoluteSymbol(0,SYMB_X0): Used to name the locations to which the processes are attached.
AMDC_SymbolNode(S)
tells you the node that created the symbol.
AMDC_SymbolKind(S)
tells you the kind of the symbol.

Messages

Messages have a header and a body. The header is used by the system, the body is used by you.

When you have a pointer to a message, your pointer points to the body; you can cast that pointer to any pointer type you want and access the data in the message through it.

The header contains

The data type of a message is Message.


Message creation and deletion

Message amdc_rawMsg(int leng);
creates a message with a body of length leng. The header is uninitialized except for (1) the script, which is set to a procedure rawScript (discussed below) which will put the message in the table of the location to which it is sent, and (2) the table which is set empty.
Message amdc_newMsg(Script script, Tag tag, int leng);
creates a new message with a body of length leng. The script is set to script, the tag is set to tag, the table is set empty, the location name is uninitialized. Run-time error if script is NULL.
Message amdc_copyMsg(Message msg);
creates a copy of the message msg, including the header and the body and with all the messages in its table copied into the table of the new message as well. Returns NULL is msg is NULL.
void amdc_freeMsg(Message msg);
deletes the message msg and all messages in its table. No effect if msg is NULL.

Access to message header

Tag amdc_getTag(Message msg);
returns the tag of message msg. Returns NO_MSG_TAG if msg is NULL.
void amdc_setTag(Message msg, Tag tag);
sets the tag of message msg to tag. Run-time error if msg is NULL.
int amdc_getLeng(Message msg);
returns the length of message msg. Run-time error if msg is NULL.
Script amdc_getScript(Message msg);
returns the script of message msg. Run-time error if msg is NULL.
void amdc_setScript(Message msg, Script script);
sets the script of message msg to script. Run-time error if either msg or script is NULL.
LocName amdc_getLocName(Message msg);
returns the location name of message msg. Run-time error if msg is NULL.
void amdc_setLocName(Message msg, LocName locName);
sets the location name of message msg to locName. Run-time error if msg is NULL.
Destiny amdc_getDest(Message msg);
returns a Destiny structure for message msg, containing its tag, location name, and script. Run-time error if msg is NULL.
void amdc_setDest(Message msg, Destiny dest);
sets the tag, location name, and script for message msg from the contents of the Destiny structure dest. Run-time error if msg is NULL.

Sending messages

All sends perform no operation if the message is NULL.

void amdc_sendMsg(Message msg);
send msg to the location named in its header.
void amdc_sendTo(Message msg, LocName locName);
send msg to the location named locName.
void amdc_sendToAs(Message msg, LocName locName, Tag tag);
set the tag of msg to tag and send it to the location named locName.
void amdc_sendToAsDo(Message msg, LocName locName, Tag tag, Script script);
set the tag of msg to tag, the script to script, and send it to the location named locName.
void amdc_sendToDest(Message msg, Destiny dest);
sets the tag, location name, and script for message msg from the contents of the Destiny structure dest and sends it.

Destiny

Yes, Destiny is an unusual name. The idea is rather simple. If you do a remote procedure call by sending a message, you need to indicate where the result is to be sent. But of course, the result message must also have a tag and execute a script when it arrives. A Destiny combines a location name, tag, and script, so you can specify all those in one place. The data type is:


typedef struct {   

    LocName locName;       

    Tag tag;       

    Script script;

 } Destiny;

Why call it a Destiny? It says where message is going, what tag it will be known by, and what it will do, which comes pretty close to what we mean by destiny. The operations on destinies are

Destiny amdc_makeDest(LocName locName, Tag tag, Script script);
returns a Destiny structure with the location name set to locName, the tag field set to tag, and the script set to script. Run-time error if script is NULL.
Destiny amdc_getDest(Message msg);
returns a Destiny structure for message msg, containing its tag, location name, and script. Run-time error if msg is NULL.
void amdc_setDest(Message msg, Destiny dest);
sets the tag, location name, and script for message msg from the contents of the Destiny structure dest. Run-time error if msg is NULL.
void amdc_sendToDest(Message msg, Destiny dest);
sets the tag, location name, and script for message msg from the contents of the Destiny structure dest and sends it. Do nothing if msg is NULL.

Scripts

A script is a pointer to a function that takes a message as its first parameter and a location as its second. The script is contained in a message and is executed when that message is dispatched at a location. The data structure is:


struct MessageStruct; 

struct LocationStruct; 

typedef void (*Script)(struct MessageStruct*,struct LocationStruct*); 

Raw script

There is a built-in script that is placed in a message when it is created by amdc_rawMsg(). When executed, it will simply place the message in the table at the location.


void amdc_rawScript(Message msg, Location loc)

{

       amdc_putLoc(loc, msg);

}


Processes

When run with command line parameter -n num, an AMDC program will run with num processes, i.e. on num nodes.

Functions for processes:

Location amdc_getMyLoc(void);
gives process a pointer to its location.
int amdc_getMyId(void);
gives a process its own number.
int amdc_getNumNodes(void);
tells a process how many nodes are running.
void amdc_pollLocations(void);
allows the AMDC system to poll the locations on this node to run a few scripts.
void amdc_pollBlock(void);
like pollLocations(), but if there are no locations with messages present, it will wait for more messages to arrive from other nodes. If all nodes are blocked and no messages are in transit, the program terminates.

Tables attached to messages

Tables of messages can be attached to messages. Their function is much like attachments on e-mail, memos, and letters: the cover message indicates how the attached messages are to be used. For example, a broadcast message may deliver a copy of an attached message to a set of locations.

void amdc_putMsg(Message tbl, Message msg);
put the message msg into the table at the message tbl. The message will be associated with its tag field. More than one message with the same tag field may be put in the table: they are queued. Run-time error if tbl is NULL. Do nothing if msg is NULL.
Message amdc_getMsg(Message msg, Tag tag);
removes and returns the first message from the table in msg which has the tag field tag. Returns NULL if there is no such message. Run-time error if msg is NULL.
Message amdc_getArbMsg(Message msg);
removes and returns an arbitrary message from the table in msg. Returns NULL if there is no message in the table. Run-time error if msg is NULL.
int amdc_numMsg(Message msg, Tag tag);
returns the count of messages in the table at msg which have the tag tag. Run-time error if msg is NULL.
int amdc_presentMsg(Message msg, Tag tag);
returns TRUE if there are any messages in the table at msg which have the tag tag. Run-time error if msg is NULL.
Tag amdc_firstTagMsg(Message msg);
returns the first tag in ascending order of any message in the table at msg. Returns NO_MSG_TAG if the table is empty. Run-time error if msg is NULL.
Tag amdc_nextTagMsg(Message msg, Tag prev);
returns the next tag in ascending order of any message in the table at msg following tag prev. Returns NO_MSG_TAG if there is no message with a higher tag than prev. Run-time error if msg is NULL.

Prepared by Virgil Bistriceanu based on version 1.1 released by Thomas Christopher. Last modified 10/23/1996.