NSEND(2)

NAME
nsend, ntry_send, nrecv, ntry_recv - Send and receive LAM network messages.

C SYNOPSIS
#include <net.h>
int nsend (struct nmsg *header);
int ntry_send (struct nmsg *header);
int nrecv (struct nmsg *header);
int ntry_recv (struct nmsg *header);

FORTRAN SYNOPSIS

subroutine NSND (nnode, nevent, ntype, nlength, nflags, ndata, ndsize, nmsg, ierror)

subroutine NRCV (nevent, ntype, nlength, nflags, ndata, ndsize, nmsg, ierror)

integer nevent, ntype, nlength, nflags, ndata(*), ndsize, ierror
<type> nmsg(*)

DESCRIPTION
The network message-passing functions add routing and packetization to the datalink functions, dsend(2) and drecv(2). nrecv() blocks if there is no synchronizing message to receive. nsend() will block if there is no synchronizing receiving process or forwarding process to take its message (see "Blocking").

ntry_send() and ntry_recv() never cause the calling process to block. The message is either immediately transferred, or an error is immediately returned, indicating that the process would have blocked. See nprobe(2) for similar functionality.

  Network Message Descriptor
All of the functions accept a pointer to a network message descriptor which is an extension of the local level message descriptor used by ksend(2) and krecv(2). The network message descriptor is defined in <net.h>.

    struct nmsg {
    	int	nh_dl_event;
    	int	nh_dl_link;
    	int	nh_node;
    	int	nh_event;
    	int	nh_type;
    	int	nh_length;
    	int	nh_flags;
    	int	nh_data[NHDSIZE];
    	char	*nh_msg;
    };

nh_dl_event
    unused

    This field is unchanged by nrecv() but is set to the event of the synchronizing process (either the intended receiver or a forwarding process) after calling nsend(). See dsend(2).

nh_dl_link
    unused

    This field is unchanged by nrecv() but is set to the output link number if the message was forwarded to a datalink output process after calling nsend(). See dsend(2).

nh_node
    This field is used by nsend() to identify the remote node running the intended receiver. It is not used by nrecv(). A receiving process thus cannot directly specify the source node of a message. Instead, receiving processes are "matched" to messages by one or both of nh_event and nh_type. Two special node identifiers are defined in <net.h>. LOCAL refers to the local node and causes nsend() to bypass its routing step. ORIGIN refers to the node from which lamboot(1) was invoked.

    This field is never altered.

nh_event
    An event is an arbitrary positive integer used by the LAM kernel to synchronize processes within a node. Synchronization occurs when two events are equal. nsend() transfers the message to the destination node and then to the highest priority process blocked on the event in the message's nh_event field and a matching type (see below). Thus, the sender calling nsend() must set nh_event to the same value as the receiver calling nrecv().

    This field is never altered.

nh_type
    This field further filters messages that match on event. A message will be transferred to a receiver only if the nh_type fields of the sender and receiver processes have at least one bit set in an identical position. In other words, the bitwise logical AND of the type fields specified by the two parties must not equal zero. A zero value matches any other value of nh_type.

    This field remains unchanged after calling nsend(), but is set to the sender's nh_type after calling nrecv().

nh_length
    This field holds the length (in bytes) of the message to be sent. If the sender and the receiver specify different lengths, the lesser amount will be transferred to the receiver. Messages longer than the maximum network packet size, defined by MAXNMSGLEN in <net.h>, will be implicitly broken down into a series of smaller messages, which will be recombined by the receiver. Because of this packetization, one call to nsend() can introduce many messages into the network, a possible source of confusion during debugging.

    This field remains unchanged after calling nsend(), but is set to the minimum of the sender's and receiver's lengths after calling nrecv().

nh_flags
    This field is normally set to 0. When the NOBUF flag (defined in <net.h>) is set in nh_flags buffers will not be used. Flags used to assure that the data representation is correct for the receiving node are discussed under "Data Representation".

    This field is never altered.

nh_data
    This field is a convenient data pouch within the network message descriptor. Its array size is NHDSIZE words, which is defined in <net.h> and is set to 8. It can be used for sending short messages (in which case nh_length is set to 0) or for appending control information to the message body.

    After calling nrecv() the nh_data field is overwritten with the sender's values of the same field. The sender's nh_data will not change.

nh_msg
    This field holds the address of the first byte of data to be sent or received. The data must be stored contiguously in memory.

    This field is never altered.

  Data Representation
On nodes of different architectures, data may have different representations. For example, integers may be stored with the most significant byte first in memory (big-endian) or with the most significant byte last in memory (little-endian). Also, the representation of floating point numbers may conform to the IEEE standard or may follow a vendor specific format. All fields in the network message structure, except the data referenced by nh_msg, are automatically converted if passed to a node with different data representation. The nh_data field is assumed to hold all integers.

The nh_flags field of the message structure can be set to the following data representation flags. Each flag assumes a data type, and will make the appropriate change in the data representation of the given field. They will have no effect if data conversion is not needed.

DINT4DATA
    nh_data holds 8 32-bit integers (default).

DFLT4DATA
    nh_data holds 8 single 32-bit real numbers.

DFLT8DATA
    nh_data holds 4 64-bit real numbers.

DRAWDATA
    nh_data representation will not be changed.

DINT4MSG
    nh_msg points to 32-bit integers.

DFLT4MSG
    nh_msg points to 32-bit real numbers.

DFLT8MSG
    nh_msg points to 64-bit real numbers.

DRAWMSG
    nh_msg representation will not be changed (default).

If nh_data or nh_msg contains a mixture of data types, the user will have to change the representation using the function suites ltot(3), ttol(3), etc.

  Example Usage
The following example passes a message between two nodes with similar data representations, utilizing a minimum level of synchronization. This is intended only as a summary of a simple case. Many variations can be constructed using the detailed information given in the above section.

    /* Sender */
    #include <net.h>
    struct nmsg nhead;
    char *msg = "Hello, world";
    nhead.nh_node = 10
    nhead.nh_event = 6
    nhead.nh_type = 0
    nhead.nh_flags = 0
    nhead.nh_length = strlen(msg) + 1;
    nhead.nh_msg = msg;
    nsend(&nhead);
    /* Receiver */
    /* Assume this code is running on node 10. */
    #include <net.h>
    struct nmsg nhead;
    char msg[16]
    nhead.nh_event = 6
    nhead.nh_type = 0
    nhead.nh_flags = 0
    nhead.nh_length = sizeof(msg);
    nhead.nh_msg = msg;
    nrecv(&nhead);

  Blocking
A process calling nrecv() blocks until the message sent by the process calling nsend() entirely arrives. A process calling nsend() blocks only until its message is picked up by:

a)  a local receiver calling nrecv()

b)  a local buffer process

c)  a local forwarding process such as a datalink

The only thing that is guaranteed by a successful return from nsend() is that the message has entirely left the calling process.

The loose blocking behaviour of nsend() introduces a fundamental danger of LAM message passing: a sender can transmit a message that may never be received due to programming error or deadlock. This message will never be dropped or timed out. Some LAM process will always be stuck with it, waiting for a synchronizing nrecv() that may never happen. If that unfortunate process is a buffer, it can be located by the user and swept clean (see sweep(1)). However, if the process is a link proprietor, the link is henceforth plugged and useless.

Besides the legitimate buffer process, datalink processes can each hold one or more messages. NOBUF does not affect these implicit buffers.

ERRORS

EWOULDBLOCK
    ntry_send() or ntry_recv() failed because the message could not be sent or received, respectively. A call to nsend() or nrecv() would have blocked.

BUGS
Multi-packet messages can inter-mingle packets if sent to the same node, event and type. The solution for this type of communication structure is to use tsend(2) and trecv(2).

SEE ALSO
dsend(2), nprobe(2), tsend(2)