Document revision date: 30 March 2001

## OpenVMS I/O User's Reference Manual

Previous | Contents | Index

## Chapter 4
Mailbox Driver

The operating system supports a virtual device, called a mailbox, that is used for communication between processes. Mailboxes provide a controlled, synchronized method for processes to exchange data. Although mailboxes transfer information much like other I/O devices, they are not hardware devices. Rather, mailboxes are a software-implemented way to perform read and write operations between processes.

The OpenVMS Programming Concepts Manual and the OpenVMS System Services Reference Manual contain additional information about using mailboxes.

## 4.1 Mailbox Operations

This section describes the following mailbox operations:

- Creating mailboxes
- Deleting mailboxes
- Protecting mailboxes

### 4.1.1 Creating Mailboxes

To create a mailbox and assign a channel and logical name to it, a process uses the Create Mailbox and Assign Channel ($CREMBX) system service. A logical name can optionally be associated with the mailbox. If a logical name is specified for the mailbox, the system enters the logical name in a logical name table and gives it an equivalence name of MBAn, where n is a unique unit number.

$CREMBX also establishes the characteristics of the mailbox. These characteristics include a protection mask, a permanence indicator, maximum message size, buffer quota, and direction in which I/O can be performed (read, write, or read/write). A mailbox is created as either temporary or permanent; both types require privilege to create. Applications and restrictions on how to use temporary and permanent mailboxes are described in the following sections. (Refer to the OpenVMS System Services Reference Manual for additional information on creating mailboxes.)

Other processes can assign additional channels to a mailbox using either the $CREMBX or the Assign I/O Channel ($ASSIGN) system service. The mailbox is identified by its logical name both when it is created and when it is assigned channels by cooperating processes. Channels assigned to the mailbox can specify the direction that I/O can be performed on the channel.

Figure 4-1 shows the use of $CREMBX and $ASSIGN.

Figure 4-1 Multiple Mailbox Channels

If sufficient dynamic memory for the mailbox data structure is not available when a mailbox is created, a resource wait occurs if resource wait mode is enabled.

When a mailbox is created, a certain amount of space is specified for buffering messages that have been written to the mailbox but have not yet been read. The bufquo argument to the $CREMBX system service specifies this amount or quota. If that argument is omitted, its value defaults to the system parameter DEFMBXBUFQUO.

A message written to a mailbox, in the absence of an outstanding read request, is queued to the mailbox, and the size of the message (the QIO P2 argument) is subtracted from the available buffering space. After the message is read, it is added back to the available buffering space.

If a process attempts to write to a mailbox that is full or has insufficient buffering space and if the process has resource wait enabled (which is the default case), the process is placed in miscellaneous resource wait mode until sufficient space is available in the mailbox. If resource wait is not enabled, the I/O completes with the status return SS$_MBFULL in the I/O status block (IOSB).

Channels can be assigned to mailboxes as bidirectional (read/write), read only, or write only. This allows for greater synchronization between users of the mailbox. To specify a unidirectional channel to the mailbox, specify the flags argument for the $CREMBX or $ASSIGN system services.

The flags argument is a longword bit mask that enables you to specify that the channel assigned to the mailbox is a read-only or write-only channel. If the flags argument is not specified, the default channel behavior is read/write. A channel assigned to the mailbox as read only is considered a reader. A channel assigned to the mailbox as write only is considered a writer. A channel assigned to the mailbox as read/write is considered both a reader and a writer.

For the $ASSIGN system service, the $AGNDEF macro defines a symbolic name for each flag bit. These flags are as follows:

- AGN$M_READONLY---When this flag is specified, $ASSIGN assigns a read-only channel to the mailbox device. An attempt to issue a $QIO WRITE operation on the mailbox channel causes an illegal I/O operation error.
- AGN$M_WRITEONLY---When this flag is specified, $ASSIGN assigns a write only channel to the mailbox device. An attempt to issue a $QIO READ operation on the mailbox channel causes an illegal I/O operation error.

For the $CREMBX system service, the $CMBDEF macro defines a symbolic name for each flag bit. These flags are as follows:

- CMB$M_READONLY---When this flag is specified, $CREMBX assigns a read-only channel to the mailbox device. An attempt to issue a $QIO WRITE operation on the mailbox channel causes an illegal I/O operation error.
- CMB$M_WRITEONLY---When this flag is specified, $CREMBX assigns a write-only channel to the mailbox device. An attempt to issue a $QIO READ operation on the mailbox channel causes an illegal I/O operation error.

Refer to the OpenVMS System Services Reference Manual for a syntax description of the $CREMBX and $ASSIGN system services.

The programming examples at the end of this section ( Section 4.5) show mailbox creation, interprocess communication, and synchronization.

### 4.1.2 Deleting Mailboxes

As each process finishes using a mailbox, it deassigns the channel using the Deassign I/O Channel ($DASSGN) system service. Temporary mailboxes or permanent mailboxes that have been marked for deletion are actually deleted when no more channels are assigned to them.

If a mailbox channel is deassigned, any incomplete I/O requests on the mailbox channel for the process deassigning the channel are removed.

Permanent mailboxes that have not been marked for deletion must be explicitly deleted using the Delete Mailbox ($DELMBX) system service. An explicit deletion can occur at any time. As is true for temporary mailboxes, the mailbox is deleted when no processes have channels assigned to it.

When a temporary mailbox is deleted, its message buffer quota is returned to the process that created it. (No quota charge is made for permanent mailboxes.)

### 4.1.3 Mailbox Message Format

There is no standardized format for mailbox messages and none is imposed on users.

### 4.1.4 Mailbox Protection

Mailboxes (both temporary and permanent) are protected by a code, or mask, that is similar to the code used in protecting volumes. As with volumes, four types of users (defined by UIC) can gain access to a mailbox: SYSTEM, OWNER, GROUP, and WORLD. However, only three types of access---logical I/O, read, and write---are meaningful to users of a mailbox. Therefore, when creating a mailbox, you can specify logical I/O, read, and write access to the mailbox separately for each type of user. Logical I/O access is required for any mailbox operation. The set protection function modifier provides additional control of mailbox access (see Section 4.3.6).

For additional information on temporary mailboxes and mailbox protection, see the description of the $CREMBX system service in the OpenVMS System Services Reference Manual.

## 4.2 Mailbox Driver Device Information

You can obtain information on mailbox characteristics by using the Get Device/Volume Information ($GETDVI) system service. (Refer to the OpenVMS System Services Reference Manual.)

$GETDVI returns mailbox characteristics when you specify the item code DVI$_DEVCHAR. Table 4-1 lists these characteristics, which are defined by the $DEVDEF macro.

Table 4-1 Mailbox Characteristics
Characteristic1 | Meaning
--- | ---
Dynamic Bits (Conditionally Set)
DEV$M_SHR | Device is shareable.
DEV$M_AVL | Device is available.
Static Bits (Always Set)
DEV$M_REC | Device is record-oriented.
DEV$M_IDV | Device is capable of input.
DEV$M_ODV | Device is capable of output.
DEV$M_MBX | Device is a mailbox.

1Defined by the $DEVDEF macro.

DVI$_DEVCLASS and DVI$_DEVTYPE return the device class and device type names, which are defined by the $DCDEF macro. The device class for mailboxes is DC$_MAILBOX. The device type is DT$_MBX (or DT$_SHRMBX if the mailbox is a shared memory mailbox). DVI$_DEVBUFSIZ returns the buffer size, which is the maximum message size in bytes.

DVI$_DEVDEPEND returns a longword field in which the two low-order bytes contain the number of messages in the mailbox. (The two high-order bytes are not used and should be ignored.)

DVI$_UNIT returns the mailbox unit number. Using mailbox to hold a termination message for a subprocess or a detached process requires that the parent process obtain this number to pass to the mbxunt argument of the $CREPRC system service.

## 4.3 Mailbox Function Codes

The mailbox I/O functions are read, write, write end-of-file, set attention AST, wait for writer/reader, and get mailbox information.

No buffered I/O byte count quota checking is performed on mailbox I/O messages. Instead, the byte count or buffer quota of the mailbox is checked for sufficient space to buffer the message being sent. The buffered I/O quota and AST quota are also checked.

### 4.3.1 Read

Read mailbox functions are used to obtain messages written to the mailbox. The operating system provides the following mailbox function codes:

- IO$_READVBLK---Read virtual block
- IO$_READLBLK---Read logical block
- IO$_READPBLK---Read physical block

IO$_READLBLK, IO$_READVBLK, and IO$_READPBLK all perform the same operation. To issue a read request, a process can specify any of the read function codes.

The following device- or function-dependent arguments are used with these codes:

- P1---The starting virtual address of the buffer that is to receive the message. If P2 specifies a zero-length buffer, P1 is ignored. On OpenVSM Alpha, P1 can be a 64-bit address.
- P2---The size of the buffer in bytes (limited by the maximum message size for the mailbox). A zero-length buffer may be specified. If a message longer than the buffer is read, the alternate success status SS$_BUFFEROVF is returned in the I/O status block. In such cases, the message is truncated to fit the buffer. The driver does not provide a means for recovering the deleted portion of the message.

The following function modifiers can be specified with a read request:

- IO$M_WRITERCHECK---Completes the I/O operation with SS$_NOWRITER status if the mailbox is empty and no write channels are assigned to the mailbox. If no writer is assigned to the mailbox when the $QIO is issued and no data is in the mailbox, the $QIO completes immediately. If no data is in the mailbox but a writer is assigned, the $QIO operation completes when either a message is written or all writers deassign their channels to the mailbox. IO$M_WRITERCHECK is ignored if the channel on which it is issued is read/write because a writer is always assigned.
- IO$M_NOW---Completes the I/O operation immediately with no wait for a write request from another process
- IO$M_STREAM---Ignores QIO record boundaries. The read operation transfers message data to the user's buffer until either P2 bytes are transferred, all message data currently in the mailbox is transferred, or an end-of-file message is encountered. If a WRITEOF message is within the records required to be read in order to fulfill the request for P2 bytes, the read request terminates successfully with the bytes it was able to read before finding the WRITEOF message and the end-of-file message becomes the first message in the mailbox. The next read request processes the end-of-file message. If the read request is a READ STREAM, then the request must be for greater than 0 bytes. $QIO READ STREAM can return fewer than P2 bytes with a return value of SS$_NORMAL if the mailbox is emptied by the $QIO READ STREAM request or a WRITEOF message is encountered.
  Figure 4-2 shows $QIO READ STREAM operations.

  Figure 4-2 $QIO READ STREAM Operation

  A READ IO$M_STREAM (without IO$M_NOW specified) on an empty mailbox waits until some data has been written to the mailbox. It terminates with:
  - 0 bytes read if the next data written is an end-of-file message.
  - Fewer than P2 bytes read if the next data written is less than P2 bytes but greater than 0 bytes. (READ IO$M_STREAM ignores writes of 0 bytes.)
  - P2 bytes read if the next data written is greater than or equal to P2 bytes.
  If a $QIO READ STREAM is fulfilled by multiple $QIO WRITE requests, the sender PID returned in the IOSB of the $QIO READ STREAM reflects the first write request. A $QIO READ STREAM is charged BUFQUO for the request. This BUFQUO is released when the read request is met. A $QIO READ STREAM request that would cause BUFQUO to be exceeded for the mailbox when the mailbox has no writes pending returns an SS$_EXQUOTA error.
  A $QIO READ STREAM issued to a mailbox that would cause BUFQUO to be exceeded because BUFQUO is occupied by write requests still executes. This happens because by allowing the mailbox to temporarily exceed BUFQUO, BUFQUO is freed. Similarly, a $QIO WRITE that is issued to a mailbox that would cause BUFQUO to be exceeded, because the BUFQUO is occupied by read stream requests, still executes.

Reads of 0 bytes are handled differently depending on which functional modifiers are specified. If IO$M_STREAM is specified, then the $QIO returns SS$_NORMAL with 0 bytes read. The contents of the mailbox remain exactly as they were before the $QIO was issued. A $QIO READ STREAM of 0 bytes does not remove a 0 byte record, nor does it remove an end-of-file marker. If IO$M_STREAM is not specified, then $QIO returns one of the following:

- SS$_NORMAL (if 0 bytes were written with the corresponding $QIO WRITE performed)
- SS$_BUFFEROVF (if the corresponding $QIO WRITE wrote more than 0 bytes with 0 bytes read)
- SS$_ENDOFFILE (if a WRITEOF function was performed as the corresponding $QIO write function)

For a 0-byte nonstream read, a record is actually removed from the mailbox in order to meet the $QIO READ request. Note that the use of the word "immediately" does not imply that synchronization of the $QIO request should not be performed.

Figure 4-3 shows the read mailbox functions. In this figure, Process A reads a mailbox message written by Process B. As the figure indicates, a mailbox read request requires a corresponding mailbox write request (except in the case of an error). The requests can be made in any sequence; the read request can either precede or follow the write request.

Figure 4-3 Read Mailbox

If Process A issues a read request before Process B issues a write request, one of two events can occur. If Process A did not specify the function modifier IO$M_NOW, Process A's request is queued before Process B issues the write request. When Process B's write request occurs, the data is transferred from Process B, through the system buffers, to Process A to complete the I/O operation.

However, if Process A did specify the IO$M_NOW function modifier, the read operation is completed immediately. That is, no data is transferred from Process B to Process A, and Process A's request is not queued until Process B issues the write request. In this case, the I/O status returned to Process A is SS$_ENDOFFILE.

If Process B sends a message (with no function modifier; see Section 4.3.2) before Process A issues a read request (with or without a function modifier), Process A finds a message in the mailbox. The data is transferred and the I/O operation is completed immediately, regardless of whether IO$M_NOW is specified on the read request.

### 4.3.2 Write

Write mailbox functions are used to transfer data from a process to a mailbox. The operating system provides the following mailbox function codes:

- IO$_WRITEVBLK---Write virtual block
- IO$_WRITELBLK---Write logical block
- IO$_WRITEPBLK---Write physical block

IO$_WRITEVBLK, IO$_WRITELBLK, and IO$_WRITEPBLK all perform the same operation. To issue a write request, a process can specify any of the write function codes.

These function codes take the following device- or function-dependent arguments:

- P1---The starting virtual address of the buffer that contains the message being written. If P2 specifies a zero-length buffer, P1 is ignored. On OpenVMS Alpha, P1 can be a 64-bit address.
- P2---The size of the buffer in bytes (limited by the maximum message size for the mailbox). A zero-length buffer produces a zero-length message to be read by the mailbox reader.

The following function modifiers can be specified with a write request:

- IO$M_READERCHECK---Completes the I/O operation immediately, with SS$_NOREADER status, if no read channels are assigned to the mailbox. If a $QIO WRITE with IO$M_READERCHECK is issued and is outstanding and all read channels assigned to the mailbox are then deassigned, the $QIO completes with SS$_NOREADER status. IO$M_READERCHECK is ignored if the channel on which it is issued is bidirectional read/write, because there is always a reader assigned. If SS$_NOREADER is returned for a write request, the $QIO WRITE operation does not place any data in the mailbox. If SS$_NOREADER is returned for a write end-of-file message request, the $QIO WRITE operation does not place the end-of-file marker in the mailbox.
- IO$M_NOW---Completes the I/O operation immediately without waiting for another process to read the mailbox message. $QIO WRITE, without IO$M_NOW specified, does not complete until the data is read. $QIO WRITE NOW completes when the data is in the mailbox. If both IO$M_READERCHECK and IO$M_NOW are specified and no read channel is assigned to the mailbox, a status of SS$_NOREADER is returned and the data is not placed in the mailbox. If a read channel is assigned, the IO$M_READERCHECK modifier is ignored.
- IO$M_NORSWAIT---If the mailbox is full, the I/O operation fails with a status return of SS$_MBFULL rather than placing the process in resource wait mode. Note that IO$M_NORSWAIT does not disable resource waits that may occur elsewhere in the $QIO operation. For example, IO$M_NORSWAIT does not affect any resource waiting that occurs when I/O processing routines try to allocate an I/O request packet while passing the I/O request to the mailbox driver.

A $QIO WRITE of 0 bytes causes a 0-byte long message to be placed in the mailbox. When this data is read by a $QIO READ without IO$M_STREAM specified, the $QIO READ returns an SS$_NORMAL status and 0 bytes. When this data is read by a $QIO READ STREAM in an attempt to read P2 bytes (P2 being greater than 0), the data is ignored. However, a $QIO READ STREAM of 0 bytes has no effect on the mailbox. A $QIO WRITE READERCHECK of 0 bytes, when no read channel is assigned to the mailbox, returns an SS$_NOREADER error and the 0-byte record is not placed in the mailbox. A message that is 0 bytes long is charged 1 byte of mailbox BUFQUO.

Figure 4-4 shows the write mailbox function. In this figure, Process A writes a message to be read by Process B. As in the read request example, a mailbox write request requires a corresponding mailbox read request (unless an error occurs) and the requests can be made in any sequence.

If Process A issues a write request before Process B issues a read request, one of two events can occur. If Process A did not specify the function modifier IO$M_NOW, Process A's write request is queued before Process B issues a read request. When this request occurs, the data is transferred from Process A to Process B to complete the I/O operation.

However, if Process A did specify the IO$M_NOW function modifier, the write operation is completed immediately. The data is available to Process B and is transferred when Process B issues a read request.

If Process B issues a read request (with no function modifier) before Process A issues a write request (with or without the function modifier), Process A finds a request in the mailbox. The data is transferred and the I/O operation is completed immediately.

Figure 4-4 Write Mailbox

### 4.3.3 Write End-of-File Message

Write end-of-file message functions are used to insert a special message in the mailbox. The process that reads the end-of-file message is returned the status code SS$_ENDOFFILE in the I/O status block. The message count of the Get Mailbox Information function reflects this end-of-file message; however, the mailbox byte count of this function does not include end-of-file markers. An end-of-file message is charged 1 byte of mailbox BUFQUO.

This function takes no arguments. The operating system provides the following function code:

> IO$_WRITEOF---Write end-of-file message

The following function modifiers can be specified with a write end-of-file request:

- IO$M_READERCHECK---Completes the I/O operation immediately, with SS$_NOREADER status, if no read channels are assigned to the mailbox. If a $QIO WRITEOF with IO$M_READERCHECK is issued and is outstanding and all read channels assigned to the mailbox are then deassigned, the $QIO completes with SS$_NOREADER status. IO$M_READERCHECK is ignored if the channel on which it is issued is bidirectional read/write, because there is always a reader assigned. If SS$_NOREADER is returned for a write end-of-file message request, the $QIO WRITEOF operation does not place the end-of-file marker in the mailbox.
- IO$M_NOW---Completes the I/O operation immediately without waiting for another process to read the mailbox message. If both IO$M_READERCHECK and IO$M_NOW are specified, and no read channel is assigned to the mailbox, a status of SS$_NOREADER is returned and the end-of-file message is not placed in the mailbox.
- IO$M_NORSWAIT---If the mailbox is full, the I/O operation fails with a status return of SS$_MBFULL instead of placing the process in resource wait mode. Note that IO$M_NORSWAIT does not disable resource waits that may occur elsewhere in the $QIO operation. For example, IO$M_NORSWAIT does not affect any resource waiting that occurs when I/O processing routines try to allocate an I/O request packet while passing the I/O request to the mailbox driver.

Previous | Next | Contents | Index

| privacy and legal statement |
6136PRO_013.HTML