asyncio (BPX1AIO, BPX4AIO) — Asynchronous I/O for sockets

Function

The asyncio callable service performs I/O operations against a socket asynchronously. It also provides synchronous operations for compatibility with the regular functions.

Requirements

Operation Environment
Authorization: Supervisor state or problem state, any PSW key
Dispatchable unit mode: Task or SRB
Cross memory mode: PASN = HASN
AMODE (BPX1AIO): 31-bit
AMODE (BPX4AIO): 64-bit
ASC mode: Primary mode
Interrupt status: Enabled for interrupts
Locks: Unlocked
Control parameters: All parameters must be addressable by the caller and in the primary address space.

Format

CALL BPX1AIO,(Aiocb_length,
              Aiocb,
              Return_value,
              Return_code,
              Reason_code)

AMODE 64 callers use BPX4AIO with the same parameters. All addresses in the Aiocb structure are doublewords.

Parameters

Aiocb_length
Supplied parameter
Type:
Integer
Length:
Fullword

The name of a fullword that contains the length of the Aiocb control block that is being passed in the next parameter. To determine the value of Aiocb_length, use the BPXYAIO macro (see BPXYAIO — Map asyncio parameter list).

Aiocb
Supplied parameter and returned parameter
Type:
Structure
Length:
Specified by the Aiocb_length parameter.

The name of an Aiocb structure to be used to control this I/O operation. See usage note 3 for information about on setting the Aiocb fields.

The BPXYAIO macro (see BPXYAIO — Map asyncio parameter list) maps the Aiocb.

Return_value
Returned parameter
Type:
Integer
Length:
Fullword
The name of a fullword in which the asyncio service returns the results of the request:
  • 0 : indicates an asynchronous request has been successfully scheduled.

    When the I/O completes, the return value, return code, and reason code of the requested function are returned in the Aiocb, and the application is notified. See usage note 2 for more information about asynchronous input/output.

  • -1: indicates the system could not schedule the request, or the request itself failed immediately, for reasons such as parameter errors. Refer to Return_code and Reason_code for more details. There is no I/O completion notification.

    When the I/O function itself is rejected immediately, the return code and reason code are specific to that function. They are documented with the description of the regular version of the function.

  • +1 : indicates the operation successfully completed synchronously, meaning one of the following occurred:
    • AioOk2CompImd is specified, and the operation is able to be completed immediately.
    • AioSync is specified.
    • The function is Aio#Cancel, and AioCancelNoWait is not specified.
    The system returns the return value, return code, and reason code of the requested function in the Aiocb. There is no I/O completion notification.
    Note: These values are returned upon successful completion only. Immediate failures are always reported with a Return_value of -1.
Return_code
Returned parameter
Type:
Integer
Length:
Fullword
The name of a fullword in which the asyncio service stores the return code. The asyncio service returns Return_code only if Return_value is -1. See z/OS UNIX System Services Messages and Codes for a complete list of possible return code values. The asyncio service can return one of the following values in the Return_code parameter:
Return_code Explanation
EAGAIN One of the following occurred:
  • The maximum number of queued signals was exceeded for this process (JrMaxQueuedSigs). This limit is specified with the MAXQUEUEDSIGS parameter of the BPXPRMxx parmlib member.
  • The maximum number of outstanding asynchronous requests that are permitted for this process was exceeded (JrMaxAsyncIO). The Async I/O maximum is twice the sum of MAXQUEUEDSIGS and the process's file limit. The file limit is taken from RLIMIT_NOFILE or the BPXPRMxx MAXFILEPROC parameter.
EALREADY The Aiocb has already been canceled.
EBADF The AioFd field does not contain a valid descriptor or the descriptor of a socket. The following reason codes can accompany the return code: JRFileDesNotInUse, JRFileNotOpen.
EFAULT A supplied data area cannot be referenced.
EINVAL A parameter is not valid. For example, AioBuffSize is negative, or AioCmd or AioNotifyType are unsupported values. The following reason codes can accompany the return code: JrAsyncBadAiocbLen, JrAsyncBadOffset, JrAsyncBadNotifyType, JrAsyncBadMsgHdrLen, JrAsyncBadSockAddr, JrAsyncBadCmd.
EIO There was a network or transport failure.
EMVSINITIAL Support for unauthorized user exits failed to initialize.
ENOSYS The socket transport or physical file system does not support asynchronous I/O. Possible value: JrAsyncOpNotSupp.
EOPNOTSUP If the return code is JrMsgFlagInvalidFlag, the TCPIP stack does not support the specified AioPosixFlags value. If the return code is JrAsyncAnr, a previous accept() operation was processed on this server socket, and because of this the use of asynchronous accept_and_receive is not supported.
EPERM The caller is not authorized. Consult Reason_code to determine the exact reason the error occurred. If the return code is JrAsyncAuthErr, one of the following flags was set by an unauthorized caller: AioCallB4, AioUseUserKey, or AioCommBuff.

Refer also to the regular versions of the various functions for errors that might be detected before the system schedules the request,Start of changeor if the request was processed asynchronously (AioSync was specified).End of change

Reason_code
Returned parameter
Type:
Integer
Length:
Fullword

The name of a fullword in which the asyncio service stores the reason code. The asyncio service returns Reason_code only if Return_value is -1. Reason_code further qualifies the Return_code value.

The following reason codes may be reported: JrAsyncAuthErr, JrAsyncBadAiocbLen, JrAsyncBadCmd, JrAsyncBadMsgHdrLen, JrAsyncBadNotifyType, JrAsyncBadOffset, JrAsyncBadSigNo, JrAsyncBadSockAddr, JrAsyncExitModeTCB, JrAsyncOpNotSupp, JrAsyncSigKey0Err, JrReadUserStorageFailed, JrWriteUserStorageFailed, JrSyscallAbend, JrMsgInvalidFlag, JrAsyncANR.

Usage notes

  1. Start of change See Callable services available to SRB mode routines for more information about programming considerations for SRB mode.End of change
  2. Asynchronous input/output. The asyncio service provides the capability to asynchronously perform those functions that are potentially blocking. These include the accept, connect, and receive and send types of functions.
    The general flow of an asynchronous request is as follows:
    1. All the parameters that are normally used on the regular version of the function are specified through the Aiocb structure. Parameters necessary to control the features of an asynchronous request are also specified here.
    2. After some preliminary checking, the system schedules the request and returns control to the caller. The AioRc field is set to EINPROGRESS. The application is free to continue with other work until it is notified that the I/O has completed. See usage note 3 for more information about AioNotifyType.
      I/O completion usually occurs under the following conditions:
      • For reads, data is available or arrives from the network.
      • For writes, system buffers are available to hold the caller's data. This is the point at which the caller's buffers can be reused or freed. It does not imply anything about the progress of the actual data transmission.
      • For accept, a connection request is available or arrives.
      • For connect, this depends on the socket type and specific transport. It is usually the point at which you can start sending and receiving on the socket. This does not necessarily mean that the server has accepted this connection.
      • For accept_and_recv, connection request and the initial data from the client are available.

      The Aiocb and any areas pointed to from the Aiocb, such as a receive buffer, must remain valid until the I/O has completed.

    3. When it can complete the I/O, the system schedules an SRB to the caller's address space to perform the following sequence:
      1. Optionally, call the exit program for preprocessing. See AioCallB4 in this topic for more information.
      2. If the operation has been successful up to this point, transfer the I/O data from or to the caller's buffers.
      3. Update the AioRv, AioRc, and AioRsn fields of the Aiocb with the status of the operation.
      4. Perform the I/O completion notification as specified by AioNotifyType and other fields in the Aiocb:
        • Send a signal
        • Send a message
        • Call the exit program, passing the Aiocb
        • Post the ECB

        Only one type of notification is issued.

        If no notification is requested, the application can check the AioRc field periodically until it changes from EINPROGRESS.

    The asyncio service supports AF_INET and AF_INET6 sockets; it cannot be used with AF_UNIX sockets.

  3. Aiocb control block. The values set into this control block control the asyncio operation. The BPXYAIO macro (see BPXYAIO — Map asyncio parameter list) maps the Aiocb. The caller is responsible for setting the following fields.
    Field
    Description
    Function-specific fields
    AioCmd
    Specifies the function to be performed:
    • Aio#Accept for accept (BPX1ACP, BPX4ACP)
    • Aio#Anr for accept_and_recv (BPX1ANR, BPX4ANR)
    • Aio#Connect for connect (BPX1CON, BPX4CON)
    • Aio#Read for read (BPX1RED, BPX4RED)
    • Aio#Write for write (BPX1WRT, BPX4WRT)
    • Aio#ReadV for readv (BPX1RDV, BPX4RDV)
    • Aio#WriteV for writev (BPX1WRV, BPX4WRV)
    • Aio#Recv for recv (BPX1RCV, BPX4RCV)
    • Aio#Send for send (BPX1SND, BPX4SND)
    • Aio#RecvFrom for recvfrom (BPX1RFM, BPX4RFM)
    • Aio#SendTo for sendto (BPX1STO, BPX4STO)
    • Aio#RecvMsg for recvmsg (BPX1RMS, BPX4RMS)
    • Aio#SendMsg for sendmsg (BPX1SMS, BPX4SMS)
    • Aio#SelPoll for select (BPX1SEL, BPX4SEL) or poll (BPX1POL, BPX4POL).
    • Aio#Cancel to cancel a prior asyncio request. See the usage notes for more information about canceling operations.

    For details on their semantics and returned information, refer to the descriptions of the regular versions of these functions.

    AioFd
    The socket descriptor.
    AioBuffPtr
    The address of the buffer for the particular operation:

    In 64-bit mode, AioBuffPtr is a doubleword pointer field, and is at a different offset within the Aiocb.

    AioBuffSize
    Specifies the size of whatever AioBuffPtr points to:
    • For read/write, recv/send, recvfrom/sendto, and accept_and_recv — the length of the data buffer.
    • For readv/writev — the number of elements in the iov array.
    • For recvmsg/sendmsg — the length of the msghdr.
    • For selpoll — the number of elements in the PollFD array.
    • For cancel — this field is ignored.
    AioBuffAlet
    For read/write, recv/send, recvfrom/sendto, readv/writev, and accept_and_recv operations, this field contains the ALET of whatever is pointed to by AioBuffPtr. For all other operations, this field is ignored. See usage note 20 for more information about using ALETs.
    AioSockAddrPtr
    Contains the address of a sockaddr structure area in the caller's primary address space. The sockaddr contains the address of the remote partner.

    The sockaddr structure itself is supplied to the sendto and connect functions and returned by the recvfrom, accept_and_recv, and accept functions.

    In 64-bit mode, AioSockAddrPtr is a doubleword pointer field, and is at a different offset within the Aiocb.

    AioSockAddrLen
    Contains the length of the sockaddr structure pointed to by AioSockAddrPtr.

    This field is supplied to all functions that use AioSockAddrPtr. It is updated with the returned sockaddr length by the recvfrom, accept, and accept_and_recv functions. The following functions allow a value of 0 to be specified, indicating that no sockaddr structure is to be returned: Aio#Accept, Aio#ANR and Aio#Connect.

    AioLocSockAddrPtr
    Contains the address of a sockaddr structure area in the caller's primary address space. In 64-bit mode, AioLockSockAddrPtr is a doubleword pointer field and is at a different offset within the Aiocb. The accept_and_recv function updates this field with the local sockaddr structure.
    AioLocSockAddrLen
    Contains the length of the sockaddr structure asyncio pointed to by AioLocSockAddrPtr. If you do not want the local sockaddr structure, specify 0 for AioLocSockAddrLen.
    AioAnrSocket
    Used by the accept_and_recv function. On input contains one of the following:
    • -1, indicating that the system is to assign a new descriptor to the accepted connection. The new descriptor is returned in this parameter. Note that a valid accepted socket descriptor is returned for partial success cases as defined by the accept_and_recv service. (See accept_and_recv (BPX1ANR, BPX4ANR) — Accept a connection and receive the first block of data.)
    • If supported by the system, the value of a reusable socket descriptor with which the accepted connection is to be associated. Socket descriptors are reused after they have been used on a send_file that specified SF_REUSE. Reusable socket descriptors are created initially through an accept, an accept_and_recv, or through the asyncio commands AIO#ACCEPT and AIO#ANR. (See send_file (BPX1SF, BPX4SF) — Send a file on a socket.)
    AioMsgIovAlet
    Specifies the ALET of the recvmsg/sendmsg msghdr's iov. See the usage notes for more information about using ALETs.
    AioIovBufAlet
    Specifies the ALET of all buffers pointed to from the iov that is used with the readv/writev and recvmsg/sendmsg functions. See the usage notes for more information about using ALETs.
    AioPosixFlags
    Start of changeOn input, contains the MSG_FLAGS value for the recv/send, recvfrom/sendto, recvmsg/sendmsg, and accept_and_recv functions (such as MSG_OOB and MSG_PEEK). For more information about the format of this field, see BPXYMSGF — Map the message flags
    Several of the MSG_FLAGS are particularly useful with asyncio:Start of change
    MSG_CONNTERM
    The asyncio will not complete until the socket session ends. AioBuffSize must be set to 0 and the other MSG_FLAGS cannot be used.
    • This flag provides a way to be notified at the time that a TCP socket session ends, independent of any actual receive-type operations outstanding on the socket.
    • Any other outstanding requests are also be completed at connection termination.
    MSG_WAITALL
    The asyncio will not complete normally until the requested amount of data has arrived.
    MSG_PEEK
    Just the front of the data will be received, without being removed from the socket. For example, if your messages contain a fixed header that contains the length of the full message, just the header can be received asynchronously while the whole message is later received synchronously by the worker thread that will process the message. This also allows the asyncio to be done with a relatively small buffer and the worker thread will know how large a buffer needs to be allocated to hold the whole message.
    End of change
    End of change
    Asynchronous feature fields
    AioNotifyType
    Specifies the type of asynchronous notification:
    • Aio#Posix — Sets the return value, code, and reason fields of the Aiocb. Optionally, sends the signal specified in the AioSigEvent structure.
    • Aio#MVS — Sets the return value, code, and reason fields of the Aiocb. Optionally, calls the exit program or posts the ECB.
    • Aio#MsqQ (AIO_MSGQ) -- Sets the return value, code, and reason fields of the Aiocb, and sends the message specified in the AioMsgEvent structure.

    Default: Aio#Posix.

    AioExitPtr
    Specifies the address of a program that the system is to call when the I/O completes. The Aiocb from the original request is passed to the exit. See 6 for details. In 64-bit mode, AioExitPtr is a doubleword pointer field, and is at a different offset within the Aiocb.
    AioExitData
    An eight-byte area that is reserved for use by the application and the exit program. The system does not inspect or change this area.
    AioExitModeTcb
    For authorized TCB callers only, this specifies the mode (SRB or TCB) in which the exit program is to be called:
    • 0 — on an SRB in the caller's address space. This is the default.
    • 1 — on the caller's TCB.

    For non-authorized callers the exit is always run on the caller's TCB. If the caller's TCB ends before the I/O completes, the system does not run the exit.

    AioECBPtr
    Specifies the address of an ECB in the caller's home address space that the system is to post when the I/O completes.
    AioSigEvent
    For Aio#Posix, this is a SigEvent structure that controls the signal generation. It contains the following fields:
    • Sigev_Notify - Set to Sigev_Signal (0) to send the signal, or Sigev_none (1) to not send any signal. Default: Sigev_Signal.
    • Sigev_Signo - Set to the signal number to be sent.

    In 64-bit mode, SigEvent is a larger structure with several doubleword pointer fields; consequently, AioSigEvent is larger and at a different offset within the Aiocb.

    AioMsgEvent
    For Aio#MsgQ, this is a structure that specifies the I/O completion message. See msgsnd (BPX1QSN, BPX4QSN) — Send to a message queue for more information about messages and message queues. This structure overlays the AioSigEvent area and contains fields which correspond directly to the parameters in the msgsnd function:
    • For AioMsgev_QID, specifies the message queue identifier that will receive the message.
    • For AioMsgev_Addr/AioMsgev_Addr64, specifies the address of the message buffer. This buffer is defined by the Msgbuf/Msgbuf64 structure in BPXYMSG and contains the message type and message text. For C programs the name of this address field is the same for both 31-bit and 64-bit amodes, and the msgbuf structure is user-defined as described in the msgsnd() function in z/OS XL C/C++ Runtime Library Reference.
    • For AioMsgev_Size, specifies the length of the message text. This value does not include the length of the message type field that precedes the text in the message buffer. The message text length is limited to 240 bytes.
    • For AioMsgev_Flag, specifies the action to take if the message queue fills up. Specify 0 to wait, or IPC_NOWAIT, defined in BPXYIPCP, to not wait.
    AioSiCode
    A halfword signal code value that is to be associated with this I/O. This is only meaningful for I/O completion notification via signals. When the I/O completes and the completion signal is delivered through sigwaitinfo() or sigtimedwait(), the Si_code field of the resulting siginfo structure contains the value specified here. The halfword specified here occupies the lower half of the fullword Si_code. Normally the Si_code is set to SI_ASYNCIO# for asynchronous I/O completions, but if AioSiCode is not zero, that value will be used when the signal is sent. The meaning of this value is up to the application, and is not interpreted by the system.
    AioTimeOut
    A word that contains the timeout value for SelPoll. It can also be used to set a time limit for other synchronous operations (AioSync), such as Aio#Recv, Aio#Accept, and Aio#ANR. This value is expressed in milliseconds (1000ths of a second). If the operation times out, it fails with a return code of ETIMEDOUT.
    • A value of Aio#Forever (0) (the default) means to wait forever.
    • For SelPoll only, a value of Aio#NoWaiting (-1) means to not wait at all.

    Note: The SO_RCVTIMEO socket option can be used to achieve a timeout function for asynchronous receive type operations. For more information see the setsockopt() function in z/OS XL C/C++ Runtime Library Reference.

    AioOk2CompImd
    Specifies that the system may complete an asynchronous request immediately if it can do so without waiting, and without making any task switches. Otherwise, the system schedules the request for normal asynchronous processing.

    If the request completes successfully and immediately, the Return_Value from asyncio is 1. The system returns the results of the function itself in the Aiocb. In this case there is no I/O completion notification.

    On an asynchronous read (or on accept_and_recv) , if data has already arrived, this option avoids the extra overhead of scheduling the SRB and performing the notification. You must code the program to handle the received data in two places: after the call to asyncio and after the notification.

    For the best performance, you should always set AioOk2CompImd and be able to handle I/O completion at the point of the call.

    Default: Off, or it is not all right to complete immediately. The system issues the I/O completion notification.

    AioSync
    Specifies that the system is to run the request synchronously. The caller will wait or block, as necessary, subject to the current value of the nonblocking state of the socket.

    If the request is successful, the Return_value from asyncio is 1. The system returns the results of the function itself in the Aiocb. There is no I/O completion notification.

    This option provides equivalence with the regular versions of the functions. It is useful for synchronous operations that must be cancelable, for operations whose waits should be limited by AioTimeOut, and for calling the select() function with the much more efficient poll() interface.

    Default: Off, or asynchronous.

    AioTcbAffinity
    Specifies that the I/O request should be canceled if the caller's TCB terminates. This field should be set if the Aiocb or buffer areas are in task-related storage and therefore will be freed when the task terminates.

    Default: Off, or do not cancel the I/O for any type of I/O complete notification other than TCB Exit. For TCB Exits, the exit cannot be run after the TCB terminates, so the I/O will be canceled.

    AioCancelNoWait
    Specifies that a cancel operation is not to wait for all I/O completion notifications to finish before it returns to the caller. See usage note 13 for more information about canceling operations.

    Default: Off, or wait.

    AioCancelNoNotify
    Specifies that a cancel operation is to skip the I/O completion notifications that have not already been issued. See usage note 13 for more information about canceling operations.

    Default: Off, or issue the notifications.

    AioCallB4
    For authorized callers only. When on, this specifies that the exit program is to be called on the SRB for preprocessing before arrived data is transferred to the user's buffer. This provides a way to defer read buffer allocation until after the data has arrived. This call is in addition to the call that is made after the I/O has completed. See usage note 6 for more information about I/O completion exits. Usage note 9 has information about preprocessing.

    Default: Off, or do not call the exit for preprocessing.

    AioUseUserKey
    For authorized callers only. When on, this specifies that the storage key in AioUserKey is to be used for all references to the functional parameters and data buffers. Only the Aiocb will be referred to with the caller's key.

    Default: Off, or use the caller's key for all storage references.

    AioUserKey
    The key to be used for all references to the functional parameters and data buffers. This is only used when AioUseUserKey is on.
    AioCommBuff
    For authorized callers only. Specifies that the I/O buffers for this request reside in common storage, and may be addressed from any address space. Examples of common storage are ECSA and CADS data spaces. Having I/O buffers in common storage allows the system to copy data to them without having to have the caller's address space present, which improves the overall performance of asynchronous I/O. This flag is processed only for stream sockets; only for the operations of Aio#Read, Aio#ReadV, or Aio#Recv; and only with I/O complete notification via an SRB exit or an ECB. The Aiocb and the iov for Aio#ReadV do not have to be in common. It is critical that any outstanding I/O that has specified AioCommBuff be canceled explicitly before the descriptor is closed.

    Default: Off, or the buffers reside in the caller's address space.

    AioACEE
    For SRB-mode callers only. Specifies the address of a security environment (ACEE) in the caller's home address space that is to be used for any multilevel security checks that may be done by TCP/IP during this I/O. This provides SRBs with a capability similar to the task-level security that is available with the TCBSENV field of a task's TCB. This field is ignored for TCB-mode callers, for whom the TCBSENV field will be used if it is nonzero, and if multilevel security checks are necessary. Before the specified ACEE can be freed or invalidated, you must ensure that this I/O has completed or been canceled; or that the socket is closed.

    Default: Off, or use task-level security.

    The following fields, which are set by the system, pass back the results of the requested function, as defined for the regular version of that function:
    • AioRv — Return_Value
    • AioRc — Return_Code
    • AioRsn — Reason_Code

    These fields are meaningful only after a successfully scheduled asynchronous request has completed, or when the asyncio service has a Return_value of 1.

    The AioRc field is set to EINPROGRESS when a request is successfully scheduled. This value is changed to reflect the final results of the operation when the I/O completes.

    The AioRc field is set to ETIMEDOUT for any function that times out because the AioTimeOut field is used.

    The AioRc field is set to ECANCELLED for a request that is subsequently canceled. See usage note 13 for more information about canceling operations.

    Note: There are two ways to request that there be no notification: Assuming that the Aiocb has been initialized to zeros, you can set Sigev_Notify to Sigev_none, or you can set AioNotifyType to Aio#MVS. If no notification is used, the program can occasionally check the AioRc field until it is no longer equal to EINPROGRESS.

    Callers of BPX1AIO (BPX4AIO) are considered authorized if the program is running in supervisor state or a system key, or if the program is APF-authorized.

  4. Unauthorized callers. Unauthorized callers are restricted in the following ways:
    • Exits are run on the caller's TCB. If that TCB ends before the I/O has completed, the exit is not run.

      There are restrictions on the use of exits. See this topic for more information.

    • Authorized TSO commands are not permitted while any asynchronous I/O is outstanding in a TSO address space.
    • The AioCallB4 and AioUseUserKey options are not available.
    • The AioCancelNoWait option is not available if exits are pending for the TCB from which the cancel call is made.
  5. Using message queues for I/O completion notifications. These messages can be received with the BPX1QRC (msgrecv) function. If the message buffer address is 0, a default message is sent. The default message type will be SIGIO#, which is the number 23 and is defined in BPXYSIGH. The default message text will be eight bytes long and contain the Aiocb address. For 31-bit callers the high word of the eight bytes is 0 and the aiocb address is in the lower word.

    The program should be designed to respond to the message queue in a timely manner so that waiting is avoided. These messages are sent from a system SRB, and waiting will tie up this critical resource and impact overall performance. Using small messages and a large queue can also help avoid waiting. If IPC_NOWAIT is specified and the queue fills up, or there is any other error in trying to send the message, the message will be lost. The system SRB will issue an EC6 abend with reason code FsAioMsgQError. The dump or logrec record produced will contain the return and reason codes from the internal call to BPX1QSN msgsnd() and potentially other diagnostic information about the problem.

    The length of the message text is limited to 240 bytes.

  6. I/O completion exit You specify an exit program by setting AioNotifyType to Aio#MVS and putting the exit's address into the AioExitPtr field.

    The exit is called in the AMODE of the caller, AMODE 31 for BPX1AIO and AMODE 64 for BPX4AIO.

    The exit is passed the original Aiocb to correlate this completion with the original request. The Aiocb contains an application area (AioExitData) that can be used to communicate with the exit. Note that since the application allocates the Aiocb in the first place, the areas before and after the control block are also available for related use. The Aiocb can be embedded in a larger application control block that can easily be reached from the Aiocb.

    The exit is usually called to process received data, or free the storage that has been tied up with this request. At this point, the Aiocb contains the final return value, return code, and reason code of the function.

    When a request has been canceled, the AioRv field is -1, and the AioRc field is set to ECANCELED. See usage note 13 for more information about canceling operations.

  7. Authorized exits. When the calling program is authorized, the exit is run on a system SRB; it is authorized and in key 0.

    Because the exit program is running on an SRB, the rules for SRB-mode callers must be followed if the exit makes any calls to z/OS UNIX functions. In particular, register 2 must be set before a call, to identify the process to which the exit belongs. See Callable services available to SRB mode routines for details. Note, though, that the discussion on recovery for user SRBs is not relevant, because the exit is running on a z/OS UNIX SRB.

    Guideline: There is an upper limit to the number of SRBs that are allowed to run at the same time. If this limit is reached, other I/O completions remain queued until an SRB becomes available.

    The AioExitModeTCB flag can be used to run the exit on the original TCB rather than on the system SRB. In this case the restrictions that are listed for Unauthorized Exits apply. The exit is entered in the key of the first caller of BPX1AIO (BPX4AIO) in this process. This key cannot be changed.

  8. Unauthorized exits When the calling program is not authorized, the exit is run on the caller's TCB in the caller's state and key. There are some restrictions:
    • A C program calling BPX1AIO (BPX4AIO) with an exit specified must be POSIX(OFF). POSIX signal handling and POSIX threading, as provided by Language Environment®, are not supported for any task in the program's process.
    • A program may not have invoked the BPX1MSS (BPX4MSS) service to register a signal interrupt routine.
    • The exit program is not in any way an extension of the main program. A C exit must establish its own C environment on entry. (This is significantly different from C signal handling.) In order for the I/O interrupt to be delivered, the thread that calls BPX1AIO (BPX4AIO) must remain dubbed.
    • All callers on all threads of a given process that are doing BPX1AIO (BPX4AIO) calls must be running with the same storage key.
    • The I/O interrupt targets the RB that made the original call to BPX1AIO (BPX4AIO) for a given thread. If the target RB is not the top RB, the interrupt is deferred until the target RB becomes the top RB.
    • A program must not have blocked the SIGIO signal, because the system uses this signal to schedule the exits.
    • If the exit program ends abnormally, the system cleans up that request and continues with other exits that are waiting to be run on that TCB. There is no dump, and the originator of that request is not notified of the problem. To have these abends percolated to the TCB, so that the TCB's mainline recovery will be run or the TCB will be terminated, set the ThliTcbExitPerc bit on before you issue the call to BPX1AIO (BPX4AIO).

    The exit is free to do whatever is supported within the environment from which it is called. It may issue another call to asyncio.

    Guideline: The exit should not issue any blocking calls, and should not enter into long delays. This ties up the system SRB on which the exit is running. Unauthorized exits are blocking the TCB that made the original request.
  9. Preprocessing exit. Authorized callers can call the exit for preprocessing before the data is transferred, by using the AioCallB4 flag. This call is on the system SRB, and at a point before arrived data is moved into the application's receive buffer. It provides a way for the application to defer committing the necessary storage until just before it is actually needed.
    This deferred allocation applies to the receive buffers only. All other structures that are related to the call must be present, and the total requested data length must be specified correctly. For read, recv, recvfrom, and accept_and_recv, AioBuffPtr may be 0; but AioBuffSize must be set to the amount that is being requested. For readv, the following conditions must be met:
    • AioBuffPtr must point to an iov.
    • AioBuffSize must contain a nonzero number of iov entries.
    • The sum of the length fields in those entries must equal the amount being requested.
    • The iov buffer pointers may be zero.
    For recvmsg, there must be a valid msghdr structure with its associated sockaddr area, and an iov structure as described for readv. You can specify a simple one-element iov on the initial call to carry the length information, and replace this with another iov to be used for the data transfer.

    Note that you cannot use deferred allocation with AioOk2CompImd.

    When the preprocessing exit is called, the AioRv value usually contains the amount of data that is available, up to the requested amount. You can allocate smaller buffers when they will be sufficient. You should be prepared for cases in which AioRv is zero, when you should allocate buffers for the original requested amount. The actual amount of data that is received is returned in AioRv on the I/O completion call to the exit.

    The preprocessing call is only made when the operation has, up to this point, been successful. The preprocessing call is in addition to, not a replacement of, the call that is made after the I/O completes. The exit can use the AioExitData area to record its entry, and thus distinguish between the first and second calls during a successful operation. If AioRv is -1, this is the only call that is made to the exit.

    The preprocessing exit can change the following Aiocb fields to affect subsequent processing: AioBuffPtr, AioBuffAlet, AioExitPtr, and AioECBPtr. You may not change the function.

  10. Effect of process termination on exits. When the caller's process terminates:
    • Exits for requests that have not yet completed are not called.
    • SRB exits that are about to be called or are already running may continue to completion, with some exceptions. If the process' address space abnormally ends, the exit is not able to finish. If the exit suspends, or calls a system service that suspends, it can be abnormally ended with a 47B abend code. If you have recovery, you should not take a dump or write an error record for 47B abends, but retry and return.

      SRB-mode routines should not call asyncio after it has entered process termination. See Callable services available to SRB mode routines.

  11. Environment at entry to the exit. The exit program receives control in the asyncio caller's address space and in the following environment:
    Operation Environment
    Authorization: Same as the caller of asyncio
    Dispatchable unit mode: SRB or TCB
    Cross memory mode: PASN = HASN
    AMODE: Same as the caller of asyncio
    ASC mode: Primary mode
    Interrupt status: Enabled for interrupts
    Locks: Unlocked
    Control parameters: All parameters are addressable in the primary address space in key 0 storage.
    On entry, register 1 points to a parameter list that contains:
    • The address of the Aiocb that was specified on the asyncio call now completing
    • The address of a 2K work area for the exit's use
    • The address of the length of the work area
    Diagram showing the contents of register 1 on entry to the exit program

    For authorized exits on the SRB, the work area is in key 0. For unauthorized exits, or authorized exits running on the TCB, it is in the key of the caller of asyncio.

    Registers at entry: The contents of the registers on entry to the exit are:
    Register
    Contents
    0
    Undefined
    1
    Parameter list address
    2-12
    Undefined
    13
    Address of a 136-byte save area. The first two words are reserved for standard save area conventions, and must not be used.
    14
    Return address
    15
    Entry address
    AR 0-15
    Undefined
  12. Environment at return from the exit. On return from the exit, the entry environment must be restored.
    Registers at exit: On return from the exit, the register contents must be:
    Register
    Contents
    2-13
    Restored from the entry values
    0,1,14,15
    Undefined
    AR 0-15
    Restored from the entry values

    No return of status information is defined for the exit program.

  13. Canceling an operation. You can cancel prior requests to asyncio with the Aio#Cancel function of asyncio.
    AioFd is set to the descriptor of the original operation, and:
    • To cancel a specific request, AioBuffPtr is set to the address of the Aiocb of the request that is to be canceled.

      Your program does not have to worry about timing or serialization with regard to the Aiocb that is being canceled. If that request has already finished, this attempt to cancel it will be ignored.

    • To cancel all outstanding asyncio requests on a specific descriptor, AioBuffPtr is set to zero.
      Note: SelPoll operations cannot be canceled this way. You cancel them by specifying the Aiocb of the SelPoll request.

    Cancel releases any blocked requests from their waits, and drives through the I/O completion notifications as it does for a failed request. The original AioRc is set to ECANCELED. Any requests that are not currently blocked are allowed to complete normally. If they attempt to enter a blocked wait they are failed with ECANCELED. Exits that are about to be called are still called normally, and those that are running are not interrupted. Aio#Cancel only "cancels" blocked requests, causing them to fail with ECANCELED.

    Synchronous requests (those with AioSync) are also broken out of their blocking waits. They are returned with an AioRc of ECANCELED.

    Usually the Aio#Cancel function waits until all I/O completion notifications have finished before asyncio returns to the caller. When asyncio returns, all exits have run, ECBs have been posted, and signals have been sent. The system is finished with the original request Aiocbs and buffers, and they can be freed by the application, subject to its own design. Note that for ECB and signal notifications, there is no coordination with the waiter or signal receiver, so there may still be application code running that is dealing with the request that has just been canceled. Because of timing, you can never tell which requests will finish normally and which requests will be canceled. You know, however, that the system is finished with the request and that any I/O complete notifications that are to be issued have been issued when asyncio returns to your program.

    In this case the successful Return_value is 1, and AioRv contains one of the following values:
    • AIO_CANCELED (1), if the requested operations were canceled.
    • AIO_NOTCANCELED (2), if at least one of the requested operations cannot be canceled because it is in progress.
    • AIO_ALLDONE (3), if all of the operations have already completed; that is, nothing was found to be canceled.
    If you do not want to wait for all I/O completion notifications, you can set the AioCancelNoWait flag. In this case the Return_value is 0 if any requests were found to be canceled. Your program must maintain its own tally of requests still outstanding if this is significant to it. If no requests were found to be canceled, the Return_value is 1, and AIO_ALLDONE is returned in AioRv.
    Note: A program cannot wait for a cancel operation if it is running on the same TCB that pending exits would run on.
    If you do not want the I/O completion notification to be issued, you can set the AioCancelNoNotify flag. If the request is still outstanding at the time of the cancel, the I/O completion notification is suppressed. This means that a specified exit program that has not already run will not be run. Setting this flag also stops the system from updating the Aiocb with the results of the operation, so that the AioRc field tends to remain with a value of EINPROGRESS. TCB exits that were scheduled to run at the time of an I/O completion but that have not yet run when the cancel is issued are skipped.
    Note: The effectiveness of this flag is unpredictable, because the I/O completion notification may be in progress, or it may already have been made.

    Canceling all requests on a given descriptor does not stop new requests from being made, or otherwise affect the descriptor. The program can start afresh or close the descriptor, depending on why it issued the cancel.

    The asynchronous features of asyncio do not apply to Aio#Cancel; that is, you cannot specify a signal, an exit program, or an ECB. AioTimeOut does not apply to Aio#Cancel.

    Cancel succeeds regardless of whether any outstanding requests have been found to cancel.

    An individual request can be canceled only once. Subsequent attempts to explicitly cancel the same request fail with EALREADY.

    Aio#Cancel cannot be used to cancel any operations other than those that are started with asyncio. You cannot cancel a read(), for example.

    A cancel operation itself is not cancelable.

  14. Effect of close

    Closing a descriptor deletes all requests that are still cancelable on that descriptor. I/O completion notifications are not issued for these requests. If you need exits to be run or ECBs to be posted, you must issue cancel for the descriptor before you issue close for the descriptor.

    In most cases, close() will flush out and wait for requests that are still in progress to be deleted. However, it cannot wait for requests that are already in the I/O complete exit programs; or that are just about to call these exits, post the I/O complete ECB, or send the I/O complete signal. Consequently, application code related to asyncio requests on the just-closed descriptor may still be in progress when the close() function returns.

    Descriptors that are part of an Aio#SelPoll request are removed from that operation. The request remains outstanding, and may complete as a result of activity on one of the other descriptors or when it times out. If all the descriptors for a particular SelPoll happen to be closed, no special action is taken; the request either times out or hangs forever.

  15. Multiple asynchronous operations on a single socket

    Not all asynchronous operations support being called to start another I/O before the prior I/O has completed on that same socket. First of all, and most important, each call must have its own Aiocb and buffer or data areas; otherwise a serious and immediate error occurs for all of the operations, and the results are very unpredictable if two operations are using the same areas. In general, starting two or more asynchronous operations on a single socket is analogous to having two or more threads calling the regular synchronous versions of these operations at the same time, and the results are pretty much the same.

    Aio#Accept and Aio#ANR may be called more than once. Each inbound connection request will complete a distinct call.

    Aio#Connect: Stream (TCP) sockets may not be connected more than once. It does not make sense to connect UDP sockets several times simultaneously, because each connection replaces the previous one, and results will be unpredictable. The results of issuing requests that depend on the connection, such as Aio#Write, before the connection has completed are unpredictable.

    Aio#Read, Aio#ReadV, Aio#Recv, Aio#RecvMsg, Aio#RecvFrom: For stream (TCP) sockets, the receive-type operations should not be called more than once before each call completes, as the results are unpredictable. The main reason for this is that the arrival of any data from the network can start the completion of one of these requests while the actual data movement occurs later, and so the data on the stream can be received by different threads out of order.

    Aio#Write, Aio#WriteV, Aio#Send, Aio#SendTo, Aio#SendMsg: For stream (TCP) sockets, the send-type operations should not be called more than once before each call completes. Data may be transmitted on the network out of order, and, in general, results are unpredictable. For datagram (UDP) sockets, the send-type operations may be called more than once, because each distinct call defines a single datagram, and there is no implied order of arrival in UDP for these datagrams. Beware of sending too much data, though. If there is network congestion, or the receiver is slow, you can tie up a large amount of system storage with uncontrolled asynchronous sends, and eventually the BPX1AIO calls will start to fail with ENOBUFS.

    Aio#SelPoll may be called more than once, but be aware that any one event will complete all the calls at the same time.

    Aio#Cancel is not an asynchronous operation.

  16. Blocking and nonblocking

    A socket must not be set to nonblocking state if you want I/O completion to wait for data.

    If the socket is in nonblocking state and there is no data available, either the asyncio request has its I/O completion driven very quickly with an AioRc of EWOULDBLOCK, or the asyncio call fails with a Return_code of EWOULDBLOCK.

    Note that Aio#ANR does not support nonblocking I/O.

  17. Signal considerations

    Signals do not interrupt asynchronous operations unless they lead to the termination of the caller's process.

  18. Asynchronous select and poll
    The Aio#SelPoll command can be used for either an asynchronous select() function or an asynchronous poll() function. The poll() interface structure is used in both cases. AioBuffPtr contains the address of a PollFD array, from BPXYPOLL, and AioBuffSize contains the number of elements in the array.
    • For the poll function, the PollFD structure is used in the same way as for poll (BPX1POL, BPX4POL).
    • For the select function, the SelFlags member of the Sel structure from BPXYSEL is mapped over the PollEvents and PollRevents members of the PollFD structure for input and output, respectively. The select event bits have the same meaning as they do for select (BPX1SEL, BPX4SEL), but they are input and output with the technique used by poll events. The triple bit map scheme of select (BPX1SEL, BPX4SEL) is not used.
    These bits occupy different bytes in the PollEvents field, and the intended function is determined according to which bits are used. If no bits are set, the operation is considered to be a poll for nothing, rather than a select for nothing.

    The entire PollFD array must consistently use only one type of bit. You cannot use select and poll bits for the same file descriptor, nor can you use select bits for one descriptor and poll bits for another. For the sake of performance, the input array is not checked to enforce this rule, and results are unpredictable if the rule is broken. The first occurrence of select bits that are turned on causes the operation to be a select() rather than a poll().

    The AioTimeOut field can be used to specify a timeout value for the operation.

    Aio#SelPoll can only be used with socket descriptors.

    Aio#SelPoll operations cannot be canceled by descriptor; the specific aiocb must be canceled.

    Negative descriptors in the PollFd array are ignored, as documented for poll(). Otherwise, the first bad descriptor causes the whole operation to fail at that point in the array. This is a little different from the behavior of poll().
    Guideline: For performance reasons, do not use asynchronous select or poll if you can use any other asynchronous operation on each descriptor.

    For example, doing Aio#Read for each of five sockets is much faster and more efficient than doing one Aio#SelPoll for that same set of sockets. This is because when an Aio#Read completes for one socket you have the data; the other sockets are unaffected and remain ready for inbound data. On the next Aio#Read only that one socket has to be readied again. When Aio#SelPoll completes for any socket, all the others are taken out of their prepared state. You still have to issue another call to actually get the data. On the next Aio#SelPoll all the sockets must be "put back" into their prepared state again.

  19. asyncio vs. synchronous (regular) select

    Asynchronous I/O is similar to the select() and poll() functions in that you can wait for data from many different descriptors at the same time. Asynchronous I/O, though, is much faster and much more efficient for large numbers of descriptors. With the asyncio service you also have control over when you wait for the next event.

  20. Using ALETS

    ALETS are generally usable only for synchronous requests (AioSync), with the exception of recvmsg/sendmsg. A preprocessing exit (AioCallB4) could update the SRB it is running on with an ALET for a data space, but this would add too many instructions to the operation to be practical for the general read or write. You could, however, consider using a Common Area Data Space (CADS).

Related services

Characteristics and restrictions

The asyncio service supports AF_INET and AF_INET6 sockets; it cannot be used with AF_UNIX sockets.

Examples

For an example that uses this callable service, see BPX1AIO (asyncio) example.