HP OpenVMS Systems Documentation

Content starts here

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:

  • When a cooperating process places a read request for which no write request is pending in a designated mailbox. This is called an unsolicited read request.
  • When a cooperating process places a write request for which no read request is pending in a designated mailbox. This is called an unsolicited write request.
  • When room becomes available in the mailbox.

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

The operating system provides the following function codes:

  • IO$_SETMODE!IO$M_READATTN---Read attention AST
  • IO$_SETMODE!IO$M_WRTATTN---Write attention AST
  • IO$_SETMODE!IO$M_MB_ROOM_NOTIFY---Room in the mailbox attention AST

These function codes take the following device- or function-dependentarguments:

  • P1---AST address (request notification is disabled if the address is 0)
  • P2---AST parameter returned in the argument list when the AST service routine is called
  • P3---Access mode to deliver AST; maximized with requester's mode

These functions are enabled only once; they must be explicitlyreenabled after the AST has been delivered if you desire repeatnotification. All types of enable functions, and more than one of eachtype, can be set at the same time. The number of enable functions islimited 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 unsolicitedmessage.

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 toProcess A. Process A responds to the AST by issuing a read request tothe mailbox. The data is then transferred to complete the I/O operation.

If several requesting processes have set ASTs for unsolicited messagesat the same mailbox, all ASTs are delivered when the first unsolicitedmessage is placed in the mailbox. However, only the first process torespond 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 themailbox, it might find the mailbox empty. If this request does notinclude the function modifier IO$M_NOW, it is queued before the nextmessage arrives in the mailbox.

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

Figure 4-6 Read Attention AST


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

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

4.3.5 Wait for Writer/Reader

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

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

The following function codes and modifiers are provided:

  • IO$_SETMODE!IO$M_READERWAIT---Waits for a read channel to be assigned to the mailbox.
  • IO$_SETMODE!IO$M_WRITERWAIT---Waits for a write channel to be assigned to the mailbox.

These function codes require no function-dependent arguments.

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

4.3.6 Set Protection

On VAX and Alpha systems, the set protection functions allow the userto set volume protection on a mailbox (see Section 4.1.4). Therequester must either be the owner of the mailbox or have BYPASSprivilege. The OpenVMS operating system provides the following functioncode:

IO$_SETMODE!IO$M_SETPROT---Set protection

This function code takes the following device- or function-dependentargument:

P2---A volume protection mask

The protection mask specified by P2 is a 16-bit mask with 4 bits foreach class of owner: SYSTEM, OWNER, GROUP, and WORLD, as shown inFigure 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 orunspecified, the mask is set to allow all read, write, and logicaloperations.

The I/O status block for the set protection function (seeFigure 4-10) returns SS$_NORMAL in the first word if the request wassuccessful. If the request was not successful, the $QIO system servicereturns SS$_NOPRIV and both longwords of the I/O status block arereturnedas zeros.

4.3.7 Get Mailbox Information

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

IO$_SENSEMODE---Get mailbox contents information

The following function codes and modifiers are provided:

  • IO$_SENSEMODE!IO$M_READERCHECK---If a $QIO SENSEMODE with IO$M_READERCHECK is issued and no read channels are assigned to the mailbox, then the SS$_NOREADER condition value is returned in the IOSB.
  • IO$_SENSEMODE!IO$M_WRITERCHECK---If a $QIO SENSEMODE with IO$M_WRITERCHECK is issued and no write channels are assigned to the mailbox, then the SS$_NOWRITER condition value is returned in the IOSB.

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 mailboxread, write, set protection, and get mailbox information QIO functionsare shown in Figures 4-8, 4-9, 4-10, and4-11.

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

SS$_ACCVIO
SS$_EXQUOTA
SS$_ILLIOFUNC
SS$_INSFMEM
SS$_MBFULL
SS$_MBTOOSML
SS$_NOPRIV
SS$_NORMAL

(The OpenVMS system messages documentation provides explanations andsuggested 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 InformationFunction


4.5 Mailbox Driver Programming Examples

This section contains the following programming examples:

  • Example 4-1 shows a MACRO32 program that creates a mailbox and puts mail into it.
  • Example 4-2 assigns a read-only channel to the mailbox.
  • Example 4-3 assigns a write-only channel to the mailbox.

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

Next, the mailbox is read. If there is no mail in the mailbox, theprogram waits because IO$M_NOW is not specified. IO$M_NOW should bespecified if there is any doubt about the availability of data in themailbox, 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 separateprocesses and show the unidirectional mailbox synchronization features.Note that these examples require the /STANDARD=VAXC qualifier whencompiled 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 followingfunctions:

  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 string10$:    .ASCII  /SYS$OUTPUT/            ;Name string of output device20$:                                    ;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 stringNAMEBOX: .ASCII /146_MAIN_ST/           ;Name stringENDBOX:                                 ;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 lengthOUT_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