[OpenVMS documentation]
[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
Updated: 11 December 1998

OpenVMS I/O User's Reference Manual


Previous Contents Index

4.3.4 Set Attention AST

Set attention AST functions specify that an asynchronous system trap (AST) be delivered to the requesting process in the following cases:

If a message exists in the mailbox when a request to enable a write attention AST is issued, the AST routine is activated immediately. If no message exists, the AST is delivered when a write request message arrives. Therefore, the requesting process need not repeatedly check the mailbox status. You must have both logical I/O and read access to the mailbox prior to performing a set attention AST function.

The operating system provides the following function codes:

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

These functions are enabled only once; they must be explicitly reenabled after the AST has been delivered if you desire repeat notification. All types of enable functions, and more than one of each type, can be set at the same time. The number of enable functions is limited only by the AST quota for the process.

Figure 4-5 shows the write attention AST function. In this figure, an AST is set to notify Process A when Process B sends an unsolicited message.

Figure 4-5 Write Attention AST (Read Unsolicited Data)


Process A uses the IO$_SETMODE!IO$M_WRTATTN function to request an AST. When Process B sends a message to the mailbox, the AST is delivered to Process A. Process A responds to the AST by issuing a read request to the mailbox. The data is then transferred to complete the I/O operation.

If several requesting processes have set ASTs for unsolicited messages at the same mailbox, all ASTs are delivered when the first unsolicited message is placed in the mailbox. However, only the first process to respond to the AST with a read request receives the data. Therefore, when the next process to respond to an AST issues a read request to the mailbox, it might find the mailbox empty. If this request does not include the function modifier IO$M_NOW, it is queued before the next message arrives in the mailbox.

Figure 4-6 shows the read attention AST function. In this figure, an AST is set to notify Process A when Process B issues a read request for which no message is available.

Figure 4-6 Read Attention AST


Process A uses the IO$_SETMODE!IO$M_READATTN function to specify an AST. When Process B issues a read request to the mailbox, the AST is delivered to Process A. Process A responds to the AST by sending a message to the mailbox. The data is then transferred to complete the I/O operation.

If several requesting processes set ASTs for read requests for the same mailbox, all ASTs are delivered when the first read request is placed in the mailbox. Only the first process to respond with a write request is able to transfer data to Process B.

4.3.5 Wait for Writer/Reader

The wait for writer/reader mailbox driver function waits until a channel is assigned to the mailbox with the requested access direction. This function returns immediately if a channel is already assigned to the mailbox with the proper access direction. This function always returns immediately if issued on a bidirectional mailbox channel. Any channel assigned bidirectionally to the mailbox satisfies both types of wait requests.

The wait function requires the same synchronization techniques as all other $QIO functions. $QIO Wait should not be issued without any synchronization of its completion. If no synchronization is performed, the program behaves as if no $QIO Wait function had been issued (except for the small delay caused by issuing the $QIO Wait).

The following function codes and modifiers are provided:

These function codes require no function-dependent arguments.

These functions are enabled only once. Once the $QIO operation completes, these functions must be explicitly reenabled.

4.3.6 Set Protection

On VAX and Alpha systems, the set protection functions allow the user to set volume protection on a mailbox (see Section 4.1.4). The requester must either be the owner of the mailbox or have BYPASS privilege. The OpenVMS operating system provides the following function code:

This function code takes the following device- or function-dependent argument:

The protection mask specified by P2 is a 16-bit mask with 4 bits for each class of owner: SYSTEM, OWNER, GROUP, and WORLD, as shown in Figure 4-7.

Figure 4-7 Protection Mask


Only logical I/O, read, and write functions have meaning for mailboxes. A clear (0) bit implies that access is allowed. If P2 is 0 or unspecified, the mask is set to allow all read, write, and logical operations.

The I/O status block for the set protection function (see Figure 4-10) returns SS$_NORMAL in the first word if the request was successful. If the request was not successful, the $QIO system service returns SS$_NOPRIV and both longwords of the I/O status block are returned as zeros.

4.3.7 Get Mailbox Information

The get mailbox information function allows the user to find out the number of unread messages and bytes in the mailbox. The following function code is provided:

The following function codes and modifiers are provided:

These function codes require no function-dependent arguments.

4.4 I/O Status Block

On VAX and Alpha systems, the I/O status blocks (IOSB) for mailbox read, write, set protection, and get mailbox information QIO functions are shown in Figures 4-8, 4-9, 4-10, and 4-11.

Appendix A lists the I/O status returns for these functions. In addition to the IOSB return values, the following statuses can be returned in R0 by the call to the system service:

(The OpenVMS system messages documentation provides explanations and suggested user actions for both types of returns.)

Figure 4-8 IOSB Contents---Read Function


Figure 4-9 IOSB Contents---Write Function


Figure 4-10 IOSB Contents---Set Protection Function


Figure 4-11 IOSB Contents---Get Mailbox Information Function


4.5 Mailbox Driver Programming Examples

This section contains the following programming examples:

Example 4-1 creates a mailbox and puts mail into it; no matching read is pending on the mailbox. First, the program shows that if the function modifier IO$M_NOW is not used when mail is deposited, the write function waits until a read operation is performed. In this case, IO$M_NOW is specified and the program continues after the mail is left in the mailbox.

Next, the mailbox is read. If there is no mail in the mailbox, the program waits because IO$M_NOW is not specified. IO$M_NOW should be specified if there is any doubt about the availability of data in the mailbox, and it is important for the program not to wait.

It is up to the user to coordinate the data that goes into and out of mailboxes. In this example, the process reads its own message. Normally, two mailboxes are used for interprocess communication: one for sending data from process A to process B, and one for sending data from process B to process A. If a program is arranged in this manner, there is no possibility of a process reading its own message.

Example 4-2 and Example 4-3 work together from two separate processes and show the unidirectional mailbox synchronization features. Note that these examples require the /STANDARD=VAXC qualifier when compiled on Alpha systems.

Example 4-2 performs the following functions:

  1. Assigns a read-only channel to the mailbox.
  2. Waits for another program to assign a writable channel to the mailbox.
  3. Reads, using the IO$M_WRITERCHECK function modifier, what has been written to the mailbox.
  4. When SS$_NOWRITER is returned from the read operation, goes back to Step 2 and waits for another writer.

Example 4-3 is a writer to the mailbox. It performs the following functions:

  1. Assigns a write-only channel to the mailbox.
  2. Waits for a reader.
  3. Gathers user input until the user enters Ctrl/Z, then writes that input to the mailbox.

Example 4-1 Mailbox Driver Program Example 1

; ********************************************************************* 
; 
 
        .TITLE  MAILBOX DRIVER PROGRAM EXAMPLE 
        .IDENT  /01/ 
 
; 
; Define necessary symbols. 
; 
 
        $IODEF                          ;Define I/O function codes 
 
; 
; Allocate storage for necessary data structures. 
; 
 
; 
; Allocate output device name string and descriptor. 
; 
 
DEVICE_DESCR:                           ; 
        .LONG   20$-10$                 ;Length of name string 
        .LONG   10$                     ;Address of name string 
10$:    .ASCII  /SYS$OUTPUT/            ;Name string of output device 
20$:                                    ;Reference label 
 
; 
; Allocate space to store assigned channel number. 
; 
 
DEVICE_CHANNEL:                         ; 
        .BLKW   1                       ;Channel number 
 
; 
; Allocate mailbox name string and descriptor. 
; 
 
MAILBOX_NAME:                           ; 
        .LONG   ENDBOX-NAMEBOX          ;Length of name string 
        .LONG   NAMEBOX                 ;Address of name string 
NAMEBOX: .ASCII /146_MAIN_ST/           ;Name string 
ENDBOX:                                 ;Reference label 
 
; 
; Allocate space to store assigned channel number. 
; 
 
MAILBOX_CHANNEL:                        ; 
        .BLKW   1                       ;Channel number 
 
; 
; Allocate space to store the outgoing and incoming messages. 
; 
 
IN_BOX_BUFFER:                          ; 
        .BLKB   40                      ;Allocate 40 bytes for 
                                        ;received message 
        IN_LENGTH=.-IN_BOX_BUFFER       ;Define input buffer length 
 
OUT_BOX_BUFFER:                         ; 
        .ASCII  /SHEEP ARE VERY DIM/    ;Message to send 
        OUT_LENGTH=.-OUT_BOX_BUFFER     ;Define length of message to 
                                        ;send 
 
; 
; Finally, allocate space for the I/O status quadword. 
; 
 
STATUS:                                 ; 
        .QUAD   1                       ;I/O status quadword 
; 
; ********************************************************************* 
; 
;                      Start Program 
; 
; ********************************************************************* 
; 
 
; 
; The program first creates a mailbox and assigns a channel to the 
; process output device.  Then a message is placed in the mailbox and 
; a message is received from the mailbox (the same message).  Finally, 
; the program prints the contents of the mailbox on the process output 
; device. 
; 
 
START:  .WORD   0                       ;Entry mask 
        $CREMBX_S CHAN=MAILBOX_CHANNEL,- ;Channel is the mailbox 
                PROMSK=#^X0000,-        ;No protection 
                BUFQUO=#^X0060,-        ;Buffer quota is hex 60 
                LOGNAM=MAILBOX_NAME,-   ;Logical name descriptor 
                MAXMSG=#^X0060          ;Maximum message is hex 60 
        CMPW    #SS$_NORMAL,R0          ;Successful mailbox creation? 
        BSBW    ERROR_CHECK             ;Find out 
        $ASSIGN_S -                     ;Assign channel 
                DEVNAM=DEVICE_DESCR,-   ;Device descriptor 
                CHAN=DEVICE_CHANNEL     ;Channel 
        CMPW    #SS$_NORMAL,R0          ;Successful channel assign? 
        BSBW    ERROR_CHECK             ;Find out 
 
; 
; The program now writes to the mailbox using a write request that 
; includes the function modifier IO$M_NOW so that it need not wait for 
; a read request to the mailbox before continuing to the next step in 
; the program. 
; 
 
        $QIOW_S FUNC=#IO$_WRITEVBLK!IO$M_NOW,- ;Write message NOW 
                CHAN=MAILBOX_CHANNEL,-  ;to the mailbox channel 
                P1=OUT_BOX_BUFFER,-     ;Write buffer 
                P2=#OUT_LENGTH          ;Buffer length 
        CMPW    #SS$_NORMAL,R0          ;Successful write request? 
        BSBW    ERROR_CHECK             ;Find out 
 
; 
; Read the mailbox. 
; 
 
        $QIOW_S FUNC=#IO$_READVBLK,-    ;Read the message 
                CHAN=MAILBOX_CHANNEL,-  ;in the mailbox channel 
                IOSB=STATUS,-           ;Define status block to 
                -                       ;receive message length 
                P1=IN_BOX_BUFFER,-      ;Read buffer 
                P2=#IN_LENGTH           ;Buffer length 
        CMPW    #SS$_NORMAL,R0          ;Successful read request? 
        BSBW    ERROR_CHECK             ;Find out 
 
; 
; The program now determines how much mail is in the mailbox (this 
; information is in STATUS+2) and then prints the mailbox message on 
; the process output device. 
; 
 
        MOVZWL  STATUS+2,R2             ;Byte count into R2 
        $QIOW_S FUNC=#IO$_WRITEVBLK,-   ;Write function to the 
                CHAN=DEVICE_CHANNEL,-   ;output device channel 
                P1=IN_BOX_BUFFER,-      ;Address of buffer to write 
                P2=R2,-                 ;How much to write 
                P4=#32                  ;Carriage control 
; 
; Finally, deassign the channel and exit. 
; 
 
EXIT:   $DASSGN_S CHAN=DEVICE_CHANNEL   ;Deassign channel 
        RET                             ;Return 
 
; 
; This is the error checking part of the program.  Normally, some kind 
; of error recovery would be attempted at this point if an error was 
; detected.  However, this example program simply exits. 
; 
 
ERROR_CHECK:                            ; 
        BNEQ    EXIT                    ;System service failure, exit 
        RSB                             ;Otherwise, return 
 
        .END    START 

Example 4-2 assigns a read-only channel to the mailbox.

Example 4-2 Mailbox Driver Program Example 2

/* 
 * C program to demonstrate the new features of the Mailbox driver           
 * This program is a Mailbox READER.  It assigns a READ_ONLY channel to the  
 * mailbox.  It's partner program is a Mailbox WRITER.                       
 */ 
 
#include "sys$library:descrip"          /* Descriptor structure definitions  */ 
#include "sys$library:libdef"           /* LIB RTL symbol definitions        */ 
#include "sys$library:stdio"            /* Standard C symbol definitions     */ 
#include "decc$library:[include]ssdef"  /* System Service status code def'ns */ 
#include "decc$library:[include]cmbdef" /* CREMBX definitions                */ 
#include "decc$library:[include]agndef" /* ASSIGN definitions                */ 
#include "decc$library:[include]iodef"  /* I/O definitions                   */ 
 
#define $ARRAY_DESCRIPTOR(name,size,array_name)                    \
    char array_name[ size ];                                       \
    struct dsc$descriptor_s name =                                 \
       { size, DSC$K_DTYPE_T, DSC$K_CLASS_S, array_name } 
 
main() 
 
{ 
# define max_msg_len 256 
$DESCRIPTOR(mailbox_name_desc,"MAILBOX_EXAMPLE"); 
$ARRAY_DESCRIPTOR(read_buffer_desc,max_msg_len,read_buffer); 
int status, mailbox_channel; 
int true=1, false = 0; 
struct io_status_block {                        /*  I/O status block */ 
    short int condition; 
    short int count; 
    int dev; 
    } iosb; 
 
/*                                                                             
 * Create a permanent mailbox with a READONLY channel.  It's logical name    
 *  will be entered into the LNM$PERMANENT_MAILBOX logical name table.       
 */                                                                             
 
    SYS$CREMBX(1,&mailbox_channel,0,0,0,0,&mailbox_name_desc,CMB$M_READONLY); 
        
/*                                                                             
 * Mark it for deletion                                                   
 */ 
    SYS$DELMBX(mailbox_channel); 
 
/*                                                                             
 * Loop forever, first waiting til a WRITE channel is assigned to the mailbox 
 * and then reading data from it until the WRITER deassigns. 
 */ 
    while (TRUE) 
    { 
       /* First, check to see if there is a WRITER assigned to the mailbox */ 
        status = SYS$QIOW ( 
            0, 
            mailbox_channel, 
            IO$_SENSEMODE|IO$M_WRITERCHECK, 
            &iosb, 
            0,0, 
            0,0,0,0,0,0); 
        
        /* If there was no WRITER, then wait for one.*/ 
        if (iosb.condition == SS$_NOWRITER) 
        status = SYS$QIOW ( 
            0, 
            mailbox_channel, 
            IO$_SETMODE|IO$M_WRITERWAIT, 
            &iosb, 
            0,0, 
            0,0,0,0,0,0); 
 
        /* 
         * While the status is good, READ from the mailbox, and write it to  
         */ 
        while (status == SS$_NORMAL) 
        { 
            status = SYS$QIOW( 
                0, 
                mailbox_channel, 
                IO$_READVBLK|IO$M_WRITERCHECK, 
                &iosb, 
                0,0, 
                read_buffer_desc.dsc$a_pointer,max_msg_len, 
                0,0,0,0); 
            status=iosb.condition; 
            read_buffer_desc.dsc$w_length = iosb.count; 
            lib$put_output(&read_buffer_desc); 
        } 
    } 
} 
 

Example 4-3 assigns a write-only channel to the mailbox.

Example 4-3 Mailbox Driver Program Example 3

 
/* 
 * C program to demonstrate the new features of the Mailbox driver           
 * This program is a Mailbox WRITER.  It assigns a WRITE_ONLY channel to the 
 * mailbox.  It's partner program is a Mailbox READER.                       
 */ 
 
#include "sys$library:descrip"          /* Descriptor structure definitions  */ 
#include "sys$library:libdef"           /* LIB RTL symbol definitions        */ 
#include "sys$library:rmsdef"           /* RMS status code def'ns            */ 
#include "sys$library:stdio"            /* Standard C symbol definitions     */ 
#include "decc$library:[include]ssdef"  /* System Service status code def'ns */ 
#include "decc$library:[include]cmbdef" /* CREMBX definitions                */ 
#include "decc$library:[include]agndef" /* ASSIGN definitions                */ 
#include "decc$library:[include]iodef"  /* I/O definitions                   */ 
 
#define $ARRAY_DESCRIPTOR(name,size,array_name)                    \
    char array_name[ size ];                                       \
    struct dsc$descriptor_s name =                                 \
       { size, DSC$K_DTYPE_T, DSC$K_CLASS_S, array_name } 
 
main() 
{ 
#define max_msg_len 256 
$DESCRIPTOR(mailbox_name_desc,"MAILBOX_EXAMPLE"); 
$DESCRIPTOR(prompt_string_desc,"DATA TO SEND TO MAILBOX 
    (<CTRL Z> to terminate) >>>"); 
$ARRAY_DESCRIPTOR(write_buffer_desc,max_msg_len,write_buffer); 
int status, mailbox_channel, wait_efn; 
int true=1, false = 0; 
int MORE_ROOM_AST(); 
struct io_status_block {                              /*  I/O status block */ 
    short int condition; 
    short int count; 
    int dev; 
    } iosb; 
 
/*                                                                             
 * Create a permanent mailbox with a WRITEONLY channel.  It's logical name   
 *  will be entered into the LNM$PERMANENT_MAILBOX logical name table.       
 */ 
 
    SYS$CREMBX(1,&mailbox_channel,0,0,0,0,&mailbox_name_desc,CMB$M_WRITEONLY); 
        
/*                                                                             
 * Mark it for deletion 
 */ 
    SYS$DELMBX(mailbox_channel); 
 
/*                                                                             
 * Loop forever, first waiting til a READ channel is assigned to the mailbox 
 * and then write data until there is no more data to write.    
 */ 
    while (TRUE) 
    { 
        /* 
         * Wait for a READER to assign a channel.  If a READER is already 
         * assigned, this will return immediatly.  
         */ 
        status = SYS$QIOW ( 
            0, 
            mailbox_channel, 
            IO$_SETMODE|IO$M_READERWAIT, 
            &iosb, 
            0,0, 
            0,0,0,0,0,0); 
        while (status) 
        { 
            write_buffer_desc.dsc$w_length = max_msg_len; 
            status = lib$get_input( 
                &write_buffer_desc, 
                &prompt_string_desc, 
                &write_buffer_desc.dsc$w_length); 
            /* 
             * If at end of file (user typed <CTRL Z>) 
             * then stop here. 
             */ 
            if (status == RMS$_EOF) SYS$EXIT(SS$_NORMAL); 
 
            /* Keep trying to write the message, until it fits in the mailbox 
             * Note that if the NORSWAIT function modifier had been eliminated 
             * below, then the ROOM_NOTIFY and the retry loop could have been 
             * removed.  ROOM_NOTIFY was used in this example simply to show  
             * its' use. It would be more appropriately used when the program 
             * has other things it can be working on, as opposed to the       
             * example below in which the program is not doing anything except 
             * WAITING for room in the mailbox.                               
             */ 
            status = SS$_NOREADER;                /* Force attempt to WRITE */ 
            while (status != SS$_NORMAL) 
                { 
                status = SYS$QIOW( 
                    0, 
                    mailbox_channel, 
                    IO$_WRITEVBLK|IO$M_READERCHECK|IO$M_NORSWAIT, 
                    &iosb, 
                    0,0, 
                    write_buffer_desc.dsc$a_pointer, write_buffer_desc.dsc$w_length, 
                    0,0,0,0); 
                if (iosb.condition == SS$_NOREADER) SYS$EXIT(SS$_NOREADER); 
                if (status == SS$_MBFULL) 
                { 
                    LIB$GET_EF(&wait_efn); 
                    SYS$CLREF(wait_efn); 
                    SYS$QIOW (            
                        0, 
                        mailbox_channel, 
                        IO$_SETMODE|IO$M_MB_ROOM_NOTIFY, 
                        &iosb, 
                        0,0, 
                        MORE_ROOM_AST,wait_efn,0,0,0,0); 
                        SYS$WAITFR(wait_efn); 
                } 
            } 
        } 
    } 
} 
 
MORE_ROOM_AST(efn_to_set) 
int efn_to_set; 
{ 
    SYS$SETEF(efn_to_set);                                   
} 
 


Previous Next Contents Index

[Site home] [Send comments] [Help with this site] [How to order documentation] [OpenVMS site] [Compaq site]
[OpenVMS documentation]

Copyright © Compaq Computer Corporation 1998. All rights reserved.

Legal
6136PRO_014.HTML