---
name: "drecv"
section: "2"
platform: "linux"
package: "lam2-dev"
version: "6.3.2-3"
release: "Debian 2.2 (Potato)"
platforms: ["linux"]
url: "https://new.carta.tech/dsend"
---

# drecv(2)

Send and receive LAM datalink messages.

Part of [dsend(2)](/dsend/2.md).

## NAME

dsend, dtry\_send, drecv, dtry\_recv - Send and receive LAM datalink messages.

## SYNOPSIS

```
#include <net.h>
#include <events.h>
int dsend (struct nmsg *header);
int dtry_send (struct nmsg *header);
int drecv (struct nmsg *header);
int dtry_recv (struct nmsg *header);
```

## DESCRIPTION

These datalink functions pass a network message from one process to another and are the basis for all forms of LAM network communication. Although they can be invoked directly, they are most often called by the network and transport functions. The datalink functions do not supply message routing, buffering or packetization. The user supplies the event of the forwarding process and the message length is restricted to MAXNMSGLEN, defined in \<net.h\>.

*dsend()* and *drecv()* are typically used to send messages to, or receive messages from, nearest neighbour nodes (see "Typical Usage"). *dtry\_send()* and *dtry\_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.

### Network Message Structure

All of the functions accept a pointer to a message structure which is an extension of the local level message structure used by [ksend(2)](/ksend/2.md) and [krecv(2)](/krecv/2.md). The network message structure is defined in \<net.h\> as:

```
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;
};
```

The usage of each field in the network message structure is described below.

- nh\_dl\_event

  This field is used by *dsend()* to synchronize the sending process and a) a forwarding process such as a link output process, or b) a local receiving process. In the first case, the synchronization is between *nh\_dl\_event* and the published event of the forwarding process. The forwarding event is returned by [getroute(2)](/getroute/2.md). In the second case, the synchronization is between *nh\_dl\_event* and the local receiver's *nh\_event* field. The *nh\_dl\_event* field is not used by *drecv()*.

-

  The *nh\_dl\_event* field remains unchanged after calling *dsend()* or *drecv()*.

- nh\_dl\_link

  If *nh\_dl\_event* refers to a link output process, a specific link number must be given in the *nh\_dl\_link* field. Link output processes may handle multiple links. This field is not used by *drecv()*.

-

  The *nh\_dl\_link* field remains unchanged after calling *dsend()* or *drecv()*.

- nh\_node

  This field is used by *dsend()* to identify the remote node running the intended receiver. Typically, the destination node is an immediate neighbour of the local node. The *nh\_node* field is not used by *drecv()*. 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*.

-

  The *nh\_node* field is never altered.

- nh\_event

  An event is an arbitrary positive integer used by the LAM daemon to synchronize processes within a node. Synchronization occurs when two events are equal. In a datalink transfer, *nh\_dl\_event* in the sender equals *nh\_event* in the local receiver. When the local receiver is a forwarding process, the message begins a journey through the network system. Much more than one simple datalink transfer is taking place and the sender must give more information beyond *nh\_dl\_event* in the *nh\_node* and *nh\_event* fields. The message may be transmitted through a physical communication link to a neighbour node. On the destination remote node, the *nh\_event* given by the original sender is copied to *nh\_dl\_event* and another typical datalink transfer occurs between a system process and the ultimate intended receiver calling *drecv()*. Thus, the sender calling *dsend()* must set *nh\_event* to the same value as the intended receiver calling *drecv()*. If the datalink functions present too much complexity, try [nsend(2)](/nsend/2.md) and [nrecv(2)](/nrecv/2.md).

-

  The *nh\_event* field is never altered.

- nh\_type

  This field further filters messages that match on event. A message will be passed 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*. The *dsend()* function compares *nh\_dl\_event* and *nh\_event* to decided if the receiver is a forwarding process. If they are equal, *nh\_type* is used as described above. Otherwise, usage of *nh\_type* is deferred until the message arrives at the destination node for synchronization with the ultimate intended receiver and special type values are immediately used to codify the message and control synchronization with the forwarding process. If *nh\_event* is negative, a type signifying a system message is used, otherwise the type identifies a user message. Application programs should not directly specify negative values for *nh\_event*. If the datalink functions present too much complexity, try [nsend(2)](/nsend/2.md) and [nrecv(2)](/nrecv/2.md).

-

  The *nh\_type* field remains unchanged after calling *dsend()*, but is set to the sender's *nh\_type* after calling *drecv()*.

- 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. The maximum length of messages transferred with *dsend()* and *drecv()* is MAXNMSGLEN, defined in \<net.h\> and usually set to 8192 bytes. Forwarding processes in the LAM network subsystem always use MAXNMSGLEN.

-

  The *nh\_length* field remains unchanged after calling *dsend()*, but is set to the minimum of the sender's and receiver's lengths after calling *drecv()*.

- nh\_flags

  This field is normally set to 0. Flags used to ensure that the data representation is correct for the receiving node are discussed under "Data Representation".

-

  The *nh\_flags* 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 currently 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 *drecv()* 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.

-

  The *nh\_msg* 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 functions ltoti4(3), ttoli4(3), etc.

### Typical Usage

The typical usage of the datalink functions is for nearest neighbour message passing, when the user wishes to avoid the expense of automatic message routing (as provided by [nsend(2)](/nsend/2.md)) and other network level overheads. To synchronize the sender and receiver, the sender must set *nh\_node* to the destination neighbour's node ID, *nh\_dl\_event* to the link process event connecting the neighbour node, *nh\_dl\_link* to the specific link number and *nh\_event* to its counterpart in the receiver.

### Blocking

A process calling *drecv()* blocks until the message sent by the process calling *dsend()* entirely arrives. A process calling *dsend()* blocks only until its message is picked up by a) a local receiver calling *drecv()* or b) the local forwarding process identified by *nh\_dl\_event*. The only thing that is guaranteed by a successful return from *dsend()* is that the message has entirely left the calling process.

The loose blocking behaviour of *dsend()* 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 *drecv()* that may never happen. If the process is a link proprietor, the link could become plugged and useless. A link input process may hold one message. A link output process may hold several messages, depending on its internal implementation.

## ERRORS

- EWOULDBLOCK

  One of the non-blocking functions, *dtry\_send()* or *dtry\_recv()*, failed because the message could not be sent or received, respectively. A call to *dsend()* or *drecv()* would have blocked.

## SEE ALSO

[nsend(2)](/nsend/2.md), [tsend(2)](/tsend/2.md)
